Solved

Creating and Killing app within app

Posted on 1998-07-24
15
191 Views
Last Modified: 2011-09-20
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
Comment
Question by:bozo7
[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
  • 7
  • 5
  • 2
  • +1
15 Comments
 
LVL 5

Expert Comment

by:JimBob091197
ID: 1358659
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
 
LVL 1

Author Comment

by:bozo7
ID: 1358660
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
 
LVL 3

Expert Comment

by:vladika
ID: 1358661
Why method?
Are you declare  ThreadWndProc as Form1 method???

0
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!

 
LVL 5

Expert Comment

by:JimBob091197
ID: 1358662
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
 
LVL 5

Expert Comment

by:JimBob091197
ID: 1358663
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
 
LVL 1

Author Comment

by:bozo7
ID: 1358664
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
 
LVL 3

Expert Comment

by:Matvey
ID: 1358665
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
 
LVL 5

Expert Comment

by:JimBob091197
ID: 1358666
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
 
LVL 3

Expert Comment

by:Matvey
ID: 1358667
Great idea, if you have some time than it's very cool...
0
 
LVL 1

Author Comment

by:bozo7
ID: 1358668
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
 
LVL 5

Expert Comment

by:JimBob091197
ID: 1358669
Hi Bozo,
Glad it works for you.  Let me know if you want me to post an answer again.

Cheers,
JB
0
 
LVL 1

Author Comment

by:bozo7
ID: 1358670
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
 
LVL 5

Accepted Solution

by:
JimBob091197 earned 200 total points
ID: 1358671
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
 
LVL 1

Author Comment

by:bozo7
ID: 1358672
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
 
LVL 5

Expert Comment

by:JimBob091197
ID: 1358673
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

Free Tool: Postgres Monitoring System

A PHP and Perl based system to collect and display usage statistics from PostgreSQL databases.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

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

Suggested Solutions

The uses clause is one of those things that just tends to grow and grow. Most of the time this is in the main form, as it's from this form that all others are called. If you have a big application (including many forms), the uses clause in the in…
This article explains how to create forms/units independent of other forms/units object names in a delphi project. Have you ever created a form for user input in a Delphi project and then had the need to have that same form in a other Delphi proj…
In an interesting question (https://www.experts-exchange.com/questions/29008360/) here at Experts Exchange, a member asked how to split a single image into multiple images. The primary usage for this is to place many photographs on a flatbed scanner…

726 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