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:TProcessInform ation;
begin
StrPCopy(zAppName,FileName );
GetDir(0,WorkDir);
StrPCopy(zCurDir,WorkDir);
FillChar(StartupInfo,Sizeo f(StartupI nfo),#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(ProcessI nfo.hThrea d, WM_QUIT, 0, 0); { I tried this, but no go }
WaitforSingleObject(Proces sInfo.hPro cess,INFIN ITE);
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.
function WinExecAndWait32(FileName:
var
zAppName:array[0..512] of char;
zCurDir:array[0..255] of char;
WorkDir:String;
StartupInfo:TStartupInfo;
ProcessInfo:TProcessInform
begin
StrPCopy(zAppName,FileName
GetDir(0,WorkDir);
StrPCopy(zCurDir,WorkDir);
FillChar(StartupInfo,Sizeo
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(ProcessI
WaitforSingleObject(Proces
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.
listening...
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(ProcessI nfo.dwThre adId, WM_QUIT, 0, 0) then begin
MessageBox(0, pchar(SysErrorMessage(GetL astError)) , 'LastError', MB_ICONERROR);
end;
WaitforSingleObject(Proces sInfo.hPro cess,INFIN ITE);
This works:
Sleep(2000);
if not PostThreadMessage(ProcessI nfo.dwThre adId, WM_QUIT, 0, 0) then begin
MessageBox(0, pchar(SysErrorMessage(GetL astError)) , 'LastError', MB_ICONERROR);
end;
WaitforSingleObject(Proces sInfo.hPro cess,INFIN ITE);
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
But! I just discovered something interesting:
This fails:
if not PostThreadMessage(ProcessI
MessageBox(0, pchar(SysErrorMessage(GetL
end;
WaitforSingleObject(Proces
This works:
Sleep(2000);
if not PostThreadMessage(ProcessI
MessageBox(0, pchar(SysErrorMessage(GetL
end;
WaitforSingleObject(Proces
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
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Looks good, thanks
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