Solved

Terminating a child process - Win32 in Delphi

Posted on 2004-04-29
4
1,212 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 2
  • 2
4 Comments
 
LVL 17

Accepted Solution

by:
geobul earned 100 total points
ID: 10948370
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
ID: 10949927
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
ID: 10950113
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
ID: 10950313
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

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

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…
Hello everybody This Article will show you how to validate number with TEdit control, What's the TEdit control? TEdit is a standard Windows edit control on a form, it allows to user to write, read and copy/paste single line of text. Usua…
In this video, viewers are given an introduction to using the Windows 10 Snipping Tool, how to quickly locate it when it's needed and also how make it always available with a single click of a mouse button, by pinning it to the Desktop Task Bar. Int…
This tutorial will teach you the special effect of super speed similar to the fictional character Wally West aka "The Flash" After Shake : http://www.videocopilot.net/presets/after_shake/ All lightning effects with instructions : http://www.mediaf…
Suggested Courses
Course of the Month3 days, 13 hours left to enroll

630 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