Link to home
Start Free TrialLog in
Avatar of pede
pede

asked on

PostMessage to process

Hi, Im trying to figure out how I can stop a process started with the following code:

function WinExecAndWait32(FileName:String; Visibility : integer):integer;
var
 zAppName:array[0..512] of char;
 zCurDir:array[0..255] of char;
 WorkDir:String;
 StartupInfo:TStartupInfo;
 ProcessInfo:TProcessInformation;
begin
 StrPCopy(zAppName,FileName);
 GetDir(0,WorkDir);
 StrPCopy(zCurDir,WorkDir);
 FillChar(StartupInfo,Sizeof(StartupInfo),#0);
 StartupInfo.cb := Sizeof(StartupInfo);

 StartupInfo.dwFlags := STARTF_USESHOWWINDOW;
 StartupInfo.wShowWindow := Visibility;
 if not CreateProcess(nil,
   zAppName,                      { pointer to command line string }
   nil,                           { pointer to process security attributes }
   nil,                           { pointer to thread security attributes }
   false,                         { handle inheritance flag }
   CREATE_NEW_CONSOLE or          { creation flags }
   NORMAL_PRIORITY_CLASS,
   nil,                           { pointer to new environment block }
   nil,                           { pointer to current directory name }
   StartupInfo,                   { pointer to STARTUPINFO }
   ProcessInfo) then Result := -1 { pointer to PROCESS_INF }

 else begin
---->   PostThreadMessage(ProcessInfo.hThread, WM_QUIT, 0, 0); { I tried this, but no go }
   WaitforSingleObject(ProcessInfo.hProcess,INFINITE);
   MainForm.Win32ExecHandle := -1;
   Result := SUCCESS;
 end;
end;


I want another thread to be able to stop the process. I assume posting a WM_QUIT message would be the nicest way to do it (I'd prefer not to use TerminateProcess). But the question is, which handle should I post to? As you can see above I post a quit message right before I wait for the process to end. But it never ends. Im testing this by executing notepad, which shows up but never stops unless I close it manually.
Avatar of Russell Libby
Russell Libby
Flag of United States of America image


The PostThreadMessage expects a thread id, not a thread handle, which is what you are passing. Try using the dwThreadId from the ProcessInfo. Also capture the return value of PostThreadMessage so you can determine if you should call GetLastError (to find out what went wrong)

Russell

listening...
Avatar of pede
pede

ASKER

I forgot to mention it, but I already tried with dwThreadId, which didnt work either. I got invalid thread identifier in both cases.

But! I just discovered something interesting:

This fails:

   if not PostThreadMessage(ProcessInfo.dwThreadId, WM_QUIT, 0, 0) then begin
    MessageBox(0, pchar(SysErrorMessage(GetLastError)), 'LastError', MB_ICONERROR);
   end;
   WaitforSingleObject(ProcessInfo.hProcess,INFINITE);


This works:

   Sleep(2000);
   if not PostThreadMessage(ProcessInfo.dwThreadId, WM_QUIT, 0, 0) then begin
    MessageBox(0, pchar(SysErrorMessage(GetLastError)), 'LastError', MB_ICONERROR);
   end;
   WaitforSingleObject(ProcessInfo.hProcess,INFINITE);

Looks like the main thread isnt initialized when CreateProcess returns (please correct me if Im mistaken). The reason I try to quit at once is just that I thought it was the easiest way to test if it worked or not. I just want the ability to abort it, so unless I try to abort a split second after CreateProcess it will be fine. This could happen though, even if very unlikely. Is there a function that can wait until the main thread is created for sure?

Regards,
Pede
ASKER CERTIFIED SOLUTION
Avatar of Russell Libby
Russell Libby
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of pede

ASKER

Looks good, thanks