2

I'm trying to create something similar to a cmd with Microsoft Visual Studio Express 2013 for Windows Desktop in c++ and one of my function should start a process like open skype by typing "skype.exe". I searched in the internet and found the CreateProcess function that should do the work for me. when I created a function that receives a class value that I created called Line (the name of the class but it doesn't really metter) and used the CreateProcess function in the way that is shown bellow I have to type in my cmd "start skype.exe" but I want it to work like in the regular cmd by writing only "skype.exe", how can I do it? (the l.parameter is just a string that contains the word skype)

void execute(Line l){ STARTUPINFO si; PROCESS_INFORMATION pi; ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si); ZeroMemory(&pi, sizeof(pi)); LPSTR s = const_cast<char *>(l.parameter.c_str()); if (!CreateProcess(NULL, s, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) { printf("CreateProcess failed (%d).\n", GetLastError()); return; } // Wait until child process exits. WaitForSingleObject(pi.hProcess, INFINITE); // Close process and thread handles. CloseHandle(pi.hProcess); CloseHandle(pi.hThread);} 
0

2 Answers 2

3

First thing is that:

LPSTR s = const_cast<char *>(l.parameter.c_str()); 

is bad idea, CreateFile accepts for lpCommandLine non const buffer for a reason - it might modify it:

The system adds a terminating null character to the command-line string to separate the file name from the arguments. This divides the original string into two strings for internal processing.

so you should pass an array, for example:

TCHAR szCmd[MAX_PATH] = {0}; 

then to your question, if "start skype.exe" works for you and you want to enter only skype.exe at the command line - then why not concatenate strings? for example:

_tcscat(szCmd, _T("start ")); _tcscat(szCmd, parameter.c_str()); 

and pass szCmd to CreateProcess

the question is whether you use UNICODE build, if yes then make sure parameter is std::wstring, otherwise if you use non-UNICODE build (and it looks like thats true) then std::string is fine.

Sign up to request clarification or add additional context in comments.

1 Comment

Since the code is compiling with LPSTR, then UNICODE is clearly not defined, and the Ansi version of CreateProcess() does not modify the command buffer, only the Unicode version does. Also, running start as the command will not work anyway.
3

start is not an executable, it is a feature of cmd.exe, so to invoke start skype.exe via CreateProcess(), you would have to specify cmd.exe as the command and /C start skype.exe as its parameter.

Line l; line.parameter = "cmd.exe /C start skype.exe"; execute(l); 

But that is overkill in this situation, as start is not actually needed, despite what you claim. It is perfectly valid and preferable to invoke skype.exe directly as the command.

However, you have to provide the full path to skype.exe (same if you were to invoke start), otherwise CreateProcess() won't be able to find it, as Skype does not register its .exe file path in the App Paths key of the Registry, or the path to its Phone subfolder (where skype.exe resides) on the system's %PATH% environment variable.

For example:

Line l; line.parameter = "C:\\Program Files (x86)\\Skype\\Phone\\Skype.exe"; execute(l); 

Fortunately, Skype does store the full path to skype.exe in the Registry, specifically in the following key:

HKEY_CURRENT_USER\Software\Skype\Phone 

It is stored in a REG_SZ value named "SkypePath".

std::string GetSkypePath() { std::string sPath; HKEY hKey; if (RegOpenKeyExA(HKEY_CURRENT_USER, "Software\\Skype\\Phone", 0, KEY_QUERY_VALUE, &hKey) == 0) { char szPath[MAX_PATH+1] = {0}; DWORD dwPathLen = MAX_PATH; if (RegQueryValueExA(hKey, "SkypePath", NULL, NULL, (LPBYTE)szPath, &dwPathLen) == 0) sPath = szPath; RegCloseKey(hKey); } return sPath; } 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.