Reputation: 684
I am trying to have a C++ program call an already made C# program to run in the background.
STARTUPINFO info = {sizeof(info)};
PROCESS_INFORMATION processinfo;
DWORD error1 = GetLastError();
bool x = ::CreateProcess((LPCWSTR)"C:\Convert_Shrink.exe", GetCommandLine(), NULL, NULL, false, 0,NULL,NULL, &info, &processinfo);
DWORD error = GetLastError();
error1 is 0 before CreateProcess error is 2 after CreateProcess
error 2:
ERROR_FILE_NOT_FOUND 2 (0x2) The system cannot find the file specified.
I've changed it to C:\ \ incase they were checking for escape sequences but I still get error 2 and I'm not sure why.
Upvotes: 1
Views: 13233
Reputation: 1384
Just for the record. CreateProcessAsUser calls SearchPath internally. SearchPath uses the File System Redirector https://msdn.microsoft.com/en-us/library/windows/desktop/aa384187%28v=vs.85%29.aspx
So, if you are running a 32 bit app under WOW64 and you ask for a process using an exe in system32 dir e.g. "c:\windows\system32\myapp.exe", CreateProcessAsUser will look in syswow64 instead e.g."c:\windows\syswow64\myapp.exe". If your exe is not there you'll get a "file not found error".
Upvotes: 2
Reputation: 283624
You can:
Use CreateProcessA
to match your ANSI file path:
bool x = ::CreateProcessA("C:\\Convert_Shrink.exe", GetCommandLineA(), NULL, NULL, false, 0,NULL,NULL, &info, &processinfo);
* Provide a file path which matches the string format required by your Unicode settings:
bool x = ::CreateProcess(_T("C:\\Convert_Shrink.exe"), GetCommandLine(), NULL, NULL, false, 0,NULL,NULL, &info, &processinfo);
or
Use CreateProcessW
so you can pass a Unicode filepath (supports extended characters):
bool x = ::CreateProcessW(L"C\\\Convert_Shrink.exe", GetCommandLineW(), NULL, NULL, false, 0,NULL,NULL, &info, &processinfo);
(as @dolphy noted, the argument has to be a writable string)
Provide a file path which matches the string format required by your Unicode settings:
#if UNICODE
std::wstring exename =
#else
const char* exename =
#endif
_T("C:\\Convert_Shrink.exe");
bool x = ::CreateProcess(&exename[0], GetCommandLine(), NULL, NULL, false, 0,NULL,NULL, &info, &processinfo);
or
Use CreateProcessW
so you can pass a Unicode filepath (supports extended characters):
wchar_t exename[] = L"C:\\Convert_Shrink.exe";
bool x = ::CreateProcessW(exename, GetCommandLineW(), NULL, NULL, false, 0,NULL,NULL, &info, &processinfo);
Upvotes: 5
Reputation: 1977
I just looked up GetCommandLine(), and MSDN states that it gets the command line for the current process. MSDN entry for CreateProcess() states that the second argument is the command line command that you want to be executed, if I'm reading it correctly. So you are essentially telling CreateProcess() to run another instance of the C++ program, not the C# program.
(edit) Actually, upon closer inspection, the CreateProcess() documentation does not seem to clearly explain what will happen if you supply both the first and second arguments. It says that the first specifies the module and the second specifies the command line. What's the diff?
Sorry for the inconclusive answer, I would convert this answer into a couple of comments on your question if I could.
Upvotes: 0
Reputation: 6498
Have you tried casting the string to LPCTSTR
instead:
bool x = ::CreateProcess((LPCTSTR)"C:\Convert_Shrink.exe", GetCommandLine(), NULL, NULL, false, 0,NULL,NULL, &info, &processinfo);
The Unicode version of this function, CreateProcessW, can modify the contents
of this string. Therefore, this parameter cannot be a pointer to read-only
memory (such as a const variable or a literal string). If this parameter is a
constant string, the function may cause an access violation.
Upvotes: -2