7606

why does ::CreateProcess(path,cmd,…) fail with error “File not found”?

Question:

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.

Answer1:

You can:

<ul><li>

Use CreateProcessA to match your ANSI file path:

bool x = ::CreateProcessA("C:\\Convert_Shrink.exe", GetCommandLineA(), NULL, NULL, false, 0,NULL,NULL, &info, &processinfo); </li> </ul>

<strike> * Provide a file path which matches the string format required by your Unicode settings:</strike>

bool x = ::CreateProcess(_T("C:\\Convert_Shrink.exe"), GetCommandLine(), NULL, NULL, false, 0,NULL,NULL, &info, &processinfo);

or

<ul><li>

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);

</li> </ul>

(as @dolphy noted, the argument has to be a writable string)

<ul><li>

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); </li> </ul>

or

<ul><li>

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); </li> </ul>

Answer2:

Just for the record. CreateProcessAsUser calls SearchPath internally. SearchPath uses the File System Redirector <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/aa384187%28v=vs.85%29.aspx" rel="nofollow">https://msdn.microsoft.com/en-us/library/windows/desktop/aa384187%28v=vs.85%29.aspx</a>

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".

Answer3:

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.

Answer4:

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);

<a href="http://msdn.microsoft.com/en-us/library/ms682425%28v=vs.85%29.aspx" rel="nofollow">From Microsoft</a>:

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.

Recommend

  • How to get a server-side variable into JavaScript
  • How to get the “temp folder” in Windows 7?
  • How does Windows locate files input in the shell?
  • Serializing C# classes to MongoDB without using discriminators in subdocuments
  • std::function as sighandler_t
  • C++11 std::threads and waiting for threads to finish
  • Regex for Words with Apostrophes (Java)
  • Split string that used to be a list
  • SQL Query and Unicode Issue
  • The binary operator LessThan is not defined for the types 'System.Nullable`1[System.DateTime]&#
  • tcpdf encode chinese character
  • PHP: Convert single-quoted string into double-quoted
  • Dealing with foreign characters in django query
  • grep: matching on literal “+”
  • Reading in Russian characters (Unicode) using a basic_ifstream
  • Azure PDF Sharp not using Unicode font
  • Greek letters in a GUI - PYTHON
  • How do I include superscripts in NSString?
  • Find the associated program to open a file using Java
  • C++ slows over time reading 70,000 files
  • Delphi. Analog of Memo/RichEdit
  • Express.js : POST data as KEY of a req.body object instead of VALUE of req.body?
  • How to remove last utf8 char of a python string
  • Does SmartGit support git-svn?
  • The symbol you provided is not a function
  • custom string delimiters stringtemplate-4
  • SIP API media codecs
  • JSR-330 support in Picocontainer : @Inject … @Named(\"xxx)
  • Creating a DropDownList
  • Who propagate bugfixes across branches (corporate development)?
  • Code in Job's Script Block after Start-Process Does not Execute
  • Visual Studio 2010 debugger build correctly - compiler pdb and linker pdb not in synch?
  • How to get Eclipse Oxygen to run on Java 9
  • MailKit: The IMAP server replied to the 'EXAMINE' command with a 'BAD' response
  • Scrapy recursive link crawler
  • swift auto completion not working in Xcode6-Beta
  • Resize panoramic image to fixed size
  • XCode can't find symbols for a specific iOS library/framework project
  • PHP: When would you need the self:: keyword?
  • Memory offsets in inline assembly