NO

Author Topic: CreateProcess problem  (Read 7996 times)

halsten

  • Guest
CreateProcess problem
« on: December 12, 2008, 10:16:18 AM »
Hello,

I am using CreateProcess to create a new process from my application, however it always fails.

Code: [Select]
ZeroMemory(&startup, sizeof(STARTUPINFO));
ZeroMemory(&processInfo, sizeof(PROCESS_INFORMATION));
startup.cb = sizeof(STARTUPINFO);
if (!CreateProcess(NULL, pszInputFilename, NULL, NULL, 0,  CREATE_NO_WINDOW | NORMAL_PRIORITY_CLASS, NULL, NULL, &startup, &processInfo)) {
MessageBox(0, "Couldn't load.", "Error", 0);
    return 0;
}

Any ideas? Thanks in advance.

Regards,
halsten

Offline Vortex

  • Member
  • *
  • Posts: 865
    • http://www.vortex.masmcode.com
Re: CreateProcess problem
« Reply #1 on: December 12, 2008, 11:31:43 AM »
Code: [Select]
CREATE_NO_WINDOW
What's the subsystem of the child process? Is it a GUI or a console application?

This worked for me :

Code: [Select]
#define WIN32_LEAN_AND_MEAN
#include <stdio.h>
#include <conio.h>
#include <windows.h>


int main(int argc,char *argv[])
{
STARTUPINFO si;
PROCESS_INFORMATION pi;
LPTSTR lpCommandLine="Msgbox.exe";
si.cb=sizeof(STARTUPINFO);
GetStartupInfo(&si);
si.lpReserved=0;
CreateProcess( 0, lpCommandLine, 0, 0, 0,  NORMAL_PRIORITY_CLASS, 0, 0, &si, &pi);
printf("To terminate the console application, click it and hit any key");
while (!_kbhit());
return 0;
}
Code it... That's all...

severach

  • Guest
Re: CreateProcess problem
« Reply #2 on: December 16, 2008, 02:12:43 AM »
Calling CreateProcess() directly is never a good idea. Using it properly is complicated and to make matters worse the function is buggy because some parameters do not behave as described in the help. CreateProcessW has an extra bug that CreateProcessA version doesn't which crashes your program when you do a particular thing that the help says is acceptable.

For your blue pill enjoyment there's WinExec() which claims to be depreciated but it seems to work quite well. There's ShellExec() that I use for URL launching that works pretty good too. There's also the C library exec and spawn functions which don't seem too well suited for Windows programmers.

Then there's the messy process of splitting and joining command lines for which I could find no API to help.

Stop now and take the blue pill while you still can.

Quote from: MSDN
WinExec Function
Note  This function is provided only for compatibility with 16-bit Windows. Applications should use the CreateProcess function.

Riiiight! I fell for that trick too and ended up coding the whole thing for WINDRES posted here on the Pelles-C forums. The upside is that I have a complete set of functions for command line management. Let's see how deep this rabbit hole goes.

Ok, so you want to use CreateProcess because the help told you to. 3 rules:

1. Assume that the writer of the CreateProcess Help is more incompetent than the writer of CreateProcess.
2. If it does nothing it's your fault for not surrounding CreateProcess with something else that is required.
3. If it crashes it's your fault because you believed something in the help that is not true.

You'll need to create a spawn function so you have something to show for your work once you get all the features working and bugs covered. You won't be writing this function from scratch because even without consideration for the bugs there are just too many things that need to be done to get basic functionality working. Start by finding the source for any spawn or exec function. The one I worked from is the one in the OpenWatcom C library: //depot/openwatcom/bld/clib/process/c/dospnwnt.c. I also looked at the implementation of ShellExec(), WinExec(), and msvcrt-spawn in the Wine code. Adapt the Watcom code to have more Windows friendly calling parameters then start working on the bugs.

To get you started here are a few lines from WINDRES.C.
Code: [Select]
// http://source.winehq.org/source/dlls/msvcrt/process.c
// if cszExeOrig==NULL then the executable is extracted from cszCmdLine
// if cszExeOrig contains no path info then the path is searched. Here is the search order
// WINDOWS/SYSTEM32 (or SYSTEM for Win9x)
// WINDOWS
// %PATH%
// The current directory is searched LAST.
// if you want to be assured that you are running a program from the current directory you must precede it with a path
// such as ".\\PROGRAM.EXE"
// These flags are selected to be cooperative with <process.h> _P_WAIT and friends, spawn, _searchenvWin, strtokcmdline, and _tcsdupRequote so they can be passed back and forth in a single variable
#define SEARCHENVWIN_NODUP (0x80) // The strings have already been strdup'd and can be written to, crashes will result if the caller has not provided writable strings
#define SEARCHENVWIN_NOEXECLEAN (0x100) // The quotes have already been cleaned from the Exe so don't do it again (this only applies when cszExeOrig is specified separately)
// Warning: if cszExeOrig is specified, the first parameter of cszCmdLine will be replaced with it.
INT_PTR __stdcall spawn(unsigned fPFlags, const TCHAR *cszExeOrig, const TCHAR * cszCmdLine, TCHAR * env);

When you think you  have the last bug smothered you need to write a program that does nothing except for display argv[0] to argv[argp-1].
Code: [Select]
C:>TESTPROG.EXE 1 TEST XYZ Pelles
TESTPROG.EXE 1 TEST XYZ Pelles
Run it from CMD and you'll see the right values. Run it from your CreateProcess variant and if you made the right mistake which the help says is not a mistake, you'll see something missing:
Code: [Select]
1 TEST XYZ Pelles
Some programs are partially functional with that mistake and some won't work at all. Knowing that your callers want to launch programs without dealing with such problems you'll spend a few more hours coding around that Windows bug.

CreateProcess might be fine for compiler and debugger authors but for the rest of us that want to launch programs without the hassle it's a train wreck!

Offline Vortex

  • Member
  • *
  • Posts: 865
    • http://www.vortex.masmcode.com
Re: CreateProcess problem
« Reply #3 on: December 16, 2008, 07:29:27 PM »
severach,

Can you run an application synchronously with WinExec? In other words, can your main application wait for the process launched with WinExec to be terminated?
« Last Edit: December 16, 2008, 07:32:56 PM by Vortex »
Code it... That's all...

severach

  • Guest
Re: CreateProcess problem
« Reply #4 on: December 19, 2008, 12:07:33 AM »
I tried WinExec and it seems to return asynchronously just like ShellExecute. If _P_WAIT is all you want and you're willing to pass in everything correctly rather than automate and extend everything without any memory leaks like I did then you can get your spawn function working in a short time from the Open Watcom code. So long as you don't need any fancy command line tricks you could use one of the exec or spawn functions.

severach

  • Guest
Re: CreateProcess problem
« Reply #5 on: December 23, 2008, 08:33:42 AM »
For parsing command lines I found CommandLineToArgvW in the MSDN help for GetCommandLine which lead me to CommandLineToArgvW and CommandLineToArgvA. The code isn't very good and won't properly unescape backslashes and quotes and doesn't translate backslashes and quotes in argv[0] properly so can only be used for simple command lines.

For WINDRES I wrote my command line parser in the style of strtok(). Though strtok() style is much more versatile I decided I needed this CommandLineToArgv variant because it would be easier to use. I tried to work the state centric code from Alexander A. Telyatnikov towards completion but that turned out to be unworkable. I then switched to my backslash complete character centric code and got it working fairly quickly. Then I noticed an offhand forum comment that said that quotes can also be escaped by doubling, a claim absent from most web descriptions of Windows command line parsing and MSDN. None of the source code implemented doubled quote escaping or unescaping. Doubled quotes escapes them and the math for doubled quotes is even less intuitive than the math for the quotes following the slashes. Then I discover that argv[0] is parsed differently than all the other argv[] because it's guaranteed to be a filename.

I couldn't get CommandLineToArgvW to crash other than with a NULL command line but I got it to produce some argv[] with surplus args and bogus argv[] pointers that will crash your program. I won't be using it.

Offline Vortex

  • Member
  • *
  • Posts: 865
    • http://www.vortex.masmcode.com
Re: CreateProcess problem
« Reply #6 on: December 23, 2008, 08:08:58 PM »
An alternative for command-line parsing is the __getmainargs function exported by msvcrt.dll
Code it... That's all...