Board index » delphi » CreateProcess - Tricky One?

CreateProcess - Tricky One?

Hi All,

I hope someone out there has an answer for this. I'm using CreateProcess in an application to Execute another
application (not mine) and this all works fine with the following code, the problem is that the application I
am executing in certain situations (about 75% of times) will itself execute another program, and when it
attempts to do this it just hangs, if I kill my program at this stage the it (the application mine started)
can then continue to run the program it's running without any problems. I've tried changing the creation flags
to CREATE_NEW_CONSOLE but no luck. So does anyone have any ideas, any help would be appreciated!

Function WinExecAndWait(Path : string; Visibility : word) : word;
var
    STARTUPINFO : TStartupInfo;
    PROCESS_INFORMATION : TProcessInformation;
    FError : Integer;
    zCmdLine : Array [0..512] of Char;
begin
     FillChar(StartupInfo,Sizeof(StartupInfo),#0);
     STARTUPINFO.cb := sizeof(STARTUPINFO);
     STARTUPINFO.dwFlags := STARTF_USESHOWWINDOW;
     STARTUPINFO.wShowWindow := Visibility;
     StrPCopy(zCmdLine, Path);
  // Start the child process.
  if not (CreateProcess( Nil, // No module name (use command line).
      zCmdLine,            // Command line.
      Nil,             // Process handle not inheritable.
      Nil,             // Thread handle not inheritable.
      FALSE,            // Set handle inheritance to FALSE.
      0,                // No creation flags.
      Nil,             // Use parents environment block.
      Nil,             // Use parents starting directory.
      STARTUPINFO,          // Pointer to STARTUPINFO structure.
      PROCESS_INFORMATION )   // Pointer to PROCESS_INFORMATION structure.
    )   then
        DroneMain.Memo1.Lines.Add('CreateProcess failed: ' + StrPas(zCmdLine))
  else
  begin
       DroneMain.Memo1.Lines.Add('Executing: ' + StrPas(zCmdLine));
       // Wait until child process exits.
       WaitForSingleObject( PROCESS_INFORMATION.hProcess, INFINITE );
  end;
    // Close process and thread handles.
    CloseHandle( PROCESS_INFORMATION.hProcess );
    CloseHandle( PROCESS_INFORMATION.hThread );
end;

 

Re:CreateProcess - Tricky One?


Hi Erik,

Thanks for the fast reply!

Quote
Erik Sperling Johansen wrote:

> Have you tried running this as a standalone app, outside of the Delphi
> IDE?

Yes, actually I had'nt been running it from the IDE at all as I have
code in it that prevents more than one instance of the same window
class running and as the form is of the same class, well you get the
picture.

Quote
> This might have something to do with how the de{*word*81} part of
> Delphi copes with new processes created without the
> DEBUG_ONLY_THIS_PROCESS creation flag. I haven't experimented very much
> with it, but you might try just adding this flag and see what happens...

I tried this, but with this Flag set the application won't start at all.
I did get somewhere however although I'm still in the same predicament
I removed the WaitForSingleObject function temporarily from the code,
and this time the other application was able to finish running the app
it wanted to then terminate. The only problem with this is I need my
app to wait for this program to terminate before it continues with it's
processing, so back to the old drawing board :) Any ideas?

Best Regards
James

Re:CreateProcess - Tricky One?


Quote
James Smith wrote:

> Hi All,

> I hope someone out there has an answer for this. I'm using CreateProcess in an application to Execute another
> application (not mine) and this all works fine with the following code, the problem is that the application I
> am executing in certain situations (about 75% of times) will itself execute another program, and when it
> attempts to do this it just hangs, if I kill my program at this stage the it (the application mine started)
> can then continue to run the program it's running without any problems. I've tried changing the creation flags
> to CREATE_NEW_CONSOLE but no luck. So does anyone have any ideas, any help would be appreciated!

Have you tried running this as a standalone app, outside of the Delphi
IDE? This might have something to do with how the de{*word*81} part of
Delphi copes with new processes created without the
DEBUG_ONLY_THIS_PROCESS creation flag. I haven't experimented very much
with it, but you might try just adding this flag and see what happens...

Regards,

Erik.

--
Need a custom component? Late on a project? Could use an util?
DOS Device driver? A VxD? NT drivers or services?
Applications of any kind?
Low rates, fast delivery!

When responding to news postings, please CC a copy to my email address.
Thanks.
Erik Sperling Johansen <e...@info-pro.no>

Re:CreateProcess - Tricky One?


Quote
James Smith wrote:
>Yes, actually I had'nt been running it from the IDE at all as I have
>code in it that prevents more than one instance of the same window
>class running and as the form is of the same class, well you get the
>picture.

Off topic, but...

When you've located the window handle of the previous form, send it a
custom message to determine whether it is alive or being designed.
Create a message handler that returns some funny value when it receives
the message. Then you won't have to worry about forms in design mode.

Quote
> I tried this, but with this Flag set the application won't start at all.
> I did get somewhere however although I'm still in the same predicament
> I removed the WaitForSingleObject function temporarily from the code,
> and this time the other application was able to finish running the app
> it wanted to then terminate. The only problem with this is I need my
> app to wait for this program to terminate before it continues with it's
> processing, so back to the old drawing board :) Any ideas?

Hmmm...

This other app, does it somehow communicate with your app? Does it
inherit handles?

Try replacing WaitForSingleObject with something like this? (I'm just
guessing now)

while WaitForSingleObject(ProcessInfo.hProcess, 0)<>WAIT_OBJECT_0 do
begin
  Application.ProcessMessages;
end;

You'll ofcourse have to disable the visible forms while waiting....

You could also create a thread which launches the process and waits for
it. Then, wait for the thread in your main app. Might work...

Also, try CREATE_NEW_PROCESS_GROUP in the flags...

Regards,

Erik.
--
Need a custom component? Late on a project? Could use an util?
DOS Device driver? A VxD? NT drivers or services?
Applications of any kind?
Low rates, fast delivery!

When responding to news postings, please CC a copy to my email address.
Thanks.
Erik Sperling Johansen <e...@info-pro.no>

Re:CreateProcess - Tricky One?


Quote
Erik Sperling Johansen wrote:

> Off topic, but...

> When you've located the window handle of the previous form, send it a
> custom message to determine whether it is alive or being designed.
> Create a message handler that returns some funny value when it receives
> the message. Then you won't have to worry about forms in design mode.

Ahh, top tip, thanks!!

Quote
> Hmmm...

> This other app, does it somehow communicate with your app? Does it
> inherit handles?

No it does'nt talk to my app at all, to fill you in a bit, it's a fidonet
mail tosser which at times needs to run another app to create special
archived packets of mail, I've set it to not inherit the handle from my
app but what it does when running the compression program I don't know.

Quote
> Try replacing WaitForSingleObject with something like this? (I'm just
> guessing now)

> while WaitForSingleObject(ProcessInfo.hProcess, 0)<>WAIT_OBJECT_0 do
> begin
>   Application.ProcessMessages;
> end;

You may have already recieved my message on the Delphi Experts Web Page,
but in case you havent and for the benefit of others that may come
across a similar problem I did managed to get around the problem in a
similar way to what you've suggested above, and I would expect the above
would work also although I havent tried it and to be honest now that
it's finally working I'm going to leave it alone. Here's what I did:

  GetExitCodeProcess(PROCESS_INFORMATION.hProcess, FExitCode);
  while FExitCode = STILL_ACTIVE do
  begin
        Application.ProcessMessages;
        GetExitCodeProcess(PROCESS_INFORMATION.hProcess, FExitCode);
  end;

This seems to work like a charm, so I'm a happy little vegemite.

Thankyou once again Erik for your help here, hope I may get the chance
return the favour sometime!

James

Other Threads