Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 208
  • Last Modified:

Creating and Killing app within app

I am trying to run 'another exe' from within my program. I have gotten the 'other exe' to run. But am having troubles getting the main program to kill the 'other exe'. I am using createprocess to start the 'other exe' I am trying to use the exitprocess to close the other app but it only closes the main program
Thanks for Help
0
bozo7
Asked:
bozo7
  • 7
  • 5
  • 2
  • +1
1 Solution
 
JimBob091197Commented:
Hi

The call to ExitProcess will kill the current process, that's why your main app closes.  To kill another process, call TerminateProcess.

Example:  I will start Notepad, then show you 2 ways to close Notepad from our app.  The 1st method is quick & dirty, the 2nd method is longer but safer.  You can choose which one you need.

First, declare these variables (in your form's public section):
    ProcessInfo: TProcessInformation;
    StartUpInfo: TStartUpInfo;

(1) To start Notepad:
procedure TForm1.btnStartNotepadClick(Sender: TObject);
begin
  ZeroMemory(@StartUpInfo, SizeOf(TStartUpInfo));
  with StartUpInfo do
    begin
      cb := SizeOf(TStartUpInfo);
      dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES;
      wShowWindow := SW_SHOWNORMAL;;
    end;
  CreateProcess(nil, PChar('C:\Windows\Notepad.exe'), nil, nil, True, NORMAL_PRIORITY_CLASS, nil, nil, StartUpInfo, ProcessInfo);
end;

(2) To kill Notepad (the quick & dirty way):
procedure TForm1.btnKillNotepadClick(Sender: TObject);
begin
  TerminateProcess(ProcessInfo.hProcess, 0);
end;

There is one major problem with this approach.  TerminateProcess will kill the process without prompting to save changes.  You can test this by starting Notepad using the above method and then entering some data before calling TerminateProcess.

The correct way to do this is to send a WM_CLOSE to Notepad.  But, how to get Notepad's HWND?  To do this we use EnumThreadWindows to enumerate each of the thread's windows (in this case there is only one window: Notepad).  This is done as follows:

(3) Closing Notepad "gently" (the safe method)
Declare a callback function as follows:
function ThreadWndProc(hWnd: HWND; lParam: LParam): Bool; stdcall;
begin
  // lParam is WM_CLOSE, because that's what we send in when
  // we call EnumThreadWindows.
  // Thus, the following will send WM_CLOSE to the window.
  SendMessage(hWnd, lParam, 0, 0);

  // Return True to continue enumeration.
  Result := True;
end;

Then, implement this code:
procedure TForm1.btnCloseNotepadClick(Sender: TObject);
begin
  if not (EnumThreadWindows(ProcessInfo.dwThreadId, @ThreadWndProc, WM_CLOSE)) then
    ShowMessage('EnumThreadWindows failed!');
end;

This should result in Notepad closing "normally".

Cheers,
JB
0
 
bozo7Author Commented:
The problem with the previous answer is the folowing :
 1: with the stdcall at the end of the function delcleration i get an 'Incorrect Method Declaration' error
 2: Take away the stdcall and at the @ThreadWndProc I get 'Variable Required'

Bozo
0
 
vladikaCommented:
Why method?
Are you declare  ThreadWndProc as Form1 method???

0
Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

 
JimBob091197Commented:
Hi

I copy & pasted the code straight from my Delphi 3 sample.  It worked fine, and should also work in Delphi 2 and 4.  (Not Delphi 1.)  I can e-mail you the sample if you want it.

As Vladika says, make sure that the "ThreadWndProc" callback function does NOT have "function TMyForm.ThreadWndProc" because it is NOT a method of your form.  It should be declared exactly as follows:
function ThreadWndProc(hWnd: HWND; lParam: LParam): Bool; stdcall;

Cheers,
JB
0
 
JimBob091197Commented:
Hi

I copy & pasted the code straight from my Delphi 3 sample.  It worked fine, and should also work in Delphi 2 and 4.  (Not Delphi 1.)  I can e-mail you the sample if you want it.

As Vladika says, make sure that the "ThreadWndProc" callback function does NOT have "function TMyForm.ThreadWndProc" because it is NOT a method of your form.  It should be declared exactly as follows:
function ThreadWndProc(hWnd: HWND; lParam: LParam): Bool; stdcall;

Cheers,
JB
0
 
bozo7Author Commented:
I am using Delphi 3.
It won't shutdown the exe I am opening consistently. Sometimes it does other times it doesn't.
JB if you could email me your sample that would be great. ross@stiix.com
Thanks
Bozo
0
 
MatveyCommented:
Hi all, can't say much about the example here, but I use a good component in such cases always. So you might consider using it too. I sent it to you.
0
 
JimBob091197Commented:
Hi all

bozo7: I have sent the sample to you.

Matvey: I got your mail.  Thanks.  The component you sent uses the "quick & dirty" method I described, that is "TerminateProcess".  This means that (in my example) if you run Notepad and type some text, then when you terminate Notepad it doesn't ask you if you want to save changes.  That's why I used the longer but safer method too, which uses "EnumThreadWindows".

But it's given me an idea.  It wouldn't be hard to modify that component (if the author, Kevin Savko, doesn't mind) so that it uses the "safe" method too.

Cheers,
JB
0
 
MatveyCommented:
Great idea, if you have some time than it's very cool...
0
 
bozo7Author Commented:
JB
Your example works great Thank You Very Much
I have not tried the component from Matvey yet. But if JB is right i will stick with the long and clean method.
Bozo

0
 
JimBob091197Commented:
Hi Bozo,
Glad it works for you.  Let me know if you want me to post an answer again.

Cheers,
JB
0
 
bozo7Author Commented:
JB
Please post you answer again
One thing i discovered is that the exe fired from within my exe is a systray application where the form close action is caNone. The only way to close the app is to call application.terminate
Any advice on calling application.terminate would help
Bozo
0
 
JimBob091197Commented:
Hi Bozo

Here is the answer again.

I'm not sure how you would get the Application object of the systray app.  In this case you may have to use the TerminateProcess method, but this is not ideal.

Did you write the systray app?

JB
0
 
bozo7Author Commented:
Yes I did write the systray app. it is only one form that would show our company logo.I want it to run while another program uses our security library. So i think i will try to do some message handling and trap a message to terminate application.
Any advice email me at
ross@stiix.com
Thank You, JB
Bozo
0
 
JimBob091197Commented:
Hi

Well, I was going to suggest you handle a msg to terminate the systray app, but you beat me to it.  :)

JB
0

Featured Post

Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

  • 7
  • 5
  • 2
  • +1
Tackle projects and never again get stuck behind a technical roadblock.
Join Now