Solved

Terminating a child process - Win32 in Delphi

Posted on 2004-04-29
4
1,137 Views
Last Modified: 2012-06-21
I have spawned a child process using CreateProcess and want to
terminate it politely i.e. not by using TerminateProcess which is
draconian.  I had thought of sending a WM_CLOSE message.  However, the
handle to the process (from ProcessInfo.hProcess) is not the same as
the app handle I need nor the handle of the spawned app's main form.

Does anybody know either
a) how I can get the appropriate handle
b) a better way of politely terminating the process than sending a
WM_CLOSE message.

The precise executable spawned is not known at designtime so I can't
look for the window by name.

Cheers.
0
Comment
Question by:Ency
  • 2
  • 2
4 Comments
 
LVL 17

Accepted Solution

by:
geobul earned 100 total points
Comment Utility
Hi,

var
  TargetHWND: HWND;
  TargetProcID: cardinal;

function EnumerateWindows(hWnd: HWND; lParam: LPARAM): BOOL; stdcall;
var ProcessId: cardinal;
begin
  GetWindowThreadProcessId(hWnd,@ProcessId);
  if ProcessID = TargetProcID then begin
    TargetHWND := hWnd;
    result := false; // stop enumeration
  end else
    result := true; // continue enumeration
end;

// usage:
TargetHWND := 0;
TargetProcID := ...; //your value here
EnumWindows(@EnumerateWindows, 0); // enumerate all top-level windows
if TargetHWND <> 0 then begin
  SendMessage(TargetHWND, WM_CLOSE, 0, 0);
end;

Regards, Geo
0
 

Author Comment

by:Ency
Comment Utility
Thanks for that.  However it does not seem to work.  Here's what I'm getting:

Firstly, the call back is working and is picking up (among many others) the main window of my spawned process.  
I know this because I've made API calls GetClassName and GetWindowText with the enumerated windows handles.  

The problem is that the process and thread IDs passed back by GetWindowThreadProcessId are different to the
Handle I get returned by CreateProcess in TProcessInformation.  I can only assume that a process or thread's ID is
not the same thing as its handle.

Have I misunderstood something?  If not is there some way of getting the process or thread ID from the handle
or vice versa?

For what it's worth the code that demonstrates this problem is below.
=========================================================================

var
  Target: TListView;

function EnumerateWindows(hWnd: HWND; lParam: LPARAM): BOOL; stdcall;
var
  ProcessId: cardinal;
  ThreadID: cardinal;
  lpString: PChar;
  ListItem: TlistItem;
begin
  lpString := StrAlloc(256);
  try
    ListItem := Target.Items.Add;
    GetClassName(hWnd,lpString,255);
    ListItem.Caption := lpString;
    GetWindowText(hWnd,lpString,255);
    ListItem.SubItems.Add( lpString );
    ThreadId := GetWindowThreadProcessId(hWnd,@ProcessId);
    ListItem.SubItems.Add( IntToSTr(ProcessId) );
    ListItem.SubItems.Add( IntToStr(ThreadId) );
    Result := True;
  finally
    StrDispose(lpString);
  end;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  ListView1.Items.BeginUpdate;
  try
    Target := ListView1;
    ListView1.Items.Clear;
    EnumWindows(@EnumerateWindows,0);
  finally
    ListView1.Items.EndUpdate;
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  ProcessInfo: TProcessInformation;
  StartupInfo: TStartupInfo;
begin
  { Null these records }
  FillChar( StartupInfo, SizeOf(StartupInfo), 0 );
  FillChar( ProcessInfo, SizeOf(ProcessInfo), 0 );

  StartupInfo.dwFlags := STARTF_USESHOWWINDOW;
  StartupInfo.wShowWindow := SW_SHOWNORMAL;

  if not CreateProcess( nil, PChar('c:\test\project1.exe'), nil, nil, False, NORMAL_PRIORITY_CLASS,
    nil, PChar('c:\test'), StartupInfo, ProcessInfo ) then
    raise Exception.Create( 'CreateProcess Failed' );

  label1.Caption := IntToStr(ProcessInfo.hProcess);
  label2.Caption := IntToStr(ProcessInfo.hThread);
end;


0
 

Author Comment

by:Ency
Comment Utility
Doh!

<sheepish>
I've just realised that TProcessInfo has members dwProcessId and dwThreadId.  I feel pretty silly now.
</sheepish>

Oh well I supose if you have to make a fool of yourself there's nothing quite like doing it on the internet.
0
 
LVL 17

Expert Comment

by:geobul
Comment Utility
Oh, I'm sorry. I really forgot to say where you should get the TargetProcID from. Glad you've managed it yourself.

Thanks for the grade :-)
0

Featured Post

What Should I Do With This Threat Intelligence?

Are you wondering if you actually need threat intelligence? The answer is yes. We explain the basics for creating useful threat intelligence.

Join & Write a Comment

Introduction The parallel port is a very commonly known port, it was widely used to connect a printer to the PC, if you look at the back of your computer, for those who don't have newer computers, there will be a port with 25 pins and a small print…
Introduction Raise your hands if you were as upset with FireMonkey as I was when I discovered that there was no TListview.  I use TListView in almost all of my applications I've written, and I was not going to compromise by resorting to TStringGrid…
It is a freely distributed piece of software for such tasks as photo retouching, image composition and image authoring. It works on many operating systems, in many languages.
Excel styles will make formatting consistent and let you apply and change formatting faster. In this tutorial, you'll learn how to use Excel's built-in styles, how to modify styles, and how to create your own. You'll also learn how to use your custo…

772 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

11 Experts available now in Live!

Get 1:1 Help Now