Jump to content
Ian Branch

Closing an external App.

Recommended Posts

Hi Team,

D10.3.3, Win 10.

I am experimenting with closing an external App programaticaly.

I have the following code..

procedure TForm10.Button2Click(Sender: TObject);
var
  hnd: HWND;
begin
  //
  hnd := FindWindow(nil, PChar('MyTestApp'));
  //
  if hnd = 0 then
    MessageDlg('MyTestApp is apperently not running.', mtInformation, [mbOK], 0)
  else
    MessageDlg('MyTestApp is apperently running.', mtInformation, [mbOK], 0);
  //
end;

Even though MyTestApp is clearly running, the FindWindow doesn't seem to find it.

Should this work?

Is there something I have missed?

Is this a known issue/bug?

Is there an alternative?

 

Related - What actual Application property is the application name in the FindWindow(nil, PChar('AppName')); ?

 

Regards & TIA,

Ian

 

Edited by Ian Branch
clarification in text

Share this post


Link to post

On windows 10, this may be a permissions issue. Applications that were launched elevated are not visible to applications that are not elevated.  

Share this post


Link to post

For FindWindow you need the name of the main window, not the application.  Often this would begin with a T, but could be anything you have set it to.  Look in the main form source for Tform1=class(Tform) and try 'Tform1' in the FindWindow call.

Share this post


Link to post

Are you trying to prevent running the same app twice?

https://lonewolfonline.net/prevent-multiple-instances-delphi-application-running/

https://stackoverflow.com/questions/8688078/preventing-multiple-instances-but-also-handle-the-command-line-parameters

 

As mentioned above, FindWindow need window class names or window titles.

https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-findwindowa

 

Unless you want to enumerate processes to find the main window(s), calling taskkill could be an alternative.

https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/taskkill

 

Share this post


Link to post

Hi Guys,

Thank you for your inputs.

The picture is that I have a head application that runs one or more function specific applications using the shellexecute functionality.  That all works fine.

The individual apps can be run as a standalone app.

As it stands, each individual App has to be closed.

What I would like to do is when the head app is closed it automatically closes any apps that are open.  Even if the subordinate apps were run from outside the head app.

Perhaps to complicate matters, the main form of each subordinate app is defined as follows.  

type
  TMainForm = class(TForm)
   ....
   ...

I tried..

FindWindow(nil, PChar('TMainForm'));

but that didn't work. 😞

Regards,

Ian

Share this post


Link to post

Hi Team,

Accidentally got it sorted.

I should have had..

FindWindow(PChar('TMainForm'), nil);

And this works.  However I would rather use the Application's name rather than having to go into each of the apps and change their class definition.

So, I still don't understand exactly what goes into 

FindWindow(nil, PChar('MyApp'));

for 'MyApp'.

Regards & TIA,

Ian

Share this post


Link to post

Read the documentation. It's the text of the window. Documentation is always the first port of call. Don't guess. 

 

You talk about the name of the application. Well, an application name isn't something well defined in programing terms. There may be conventions that the executable file has a name that matches what you think of the application name. But nothing enforces that. You need to decide on the right way to identify your process.

 

If you try to kill windows with the class name TMainForm then there will be collateral damage. You'll kill my program's main window! 

 

So, try to work out how to robustly identify your process. 

Edited by David Heffernan

Share this post


Link to post

Hi David,

I am clearly having a mental block on this subject.  Starting to feel like a dunce. 😞

Which documentation are you referring to?

When I did F1 on FindWindow in Delphi it took me to "FMX.Platform.Win.FindWindow".  Singularly unhelpful.

I don't understand what you mean by "It's the text of the window.". 😞

Regards,

Ian

Share this post


Link to post

Ah Ha!  It's the Main Window/Form Title.

Sorted.

Hmm.  Not an issue in my case but what happens if the Form/Window doesn't have a Caption?

 

Regards & Thanks for your input Guys.

Ian

Share this post


Link to post

It not the caption. Its the window text. By default the system uses that text as the caption, but it is possible to have windows with no caption, that do have window text. 

Share this post


Link to post

And I was that close....

OK.  I guess my question of what/where is the Windows Text still applies?

Share this post


Link to post

Window text is simple an attribute owned by the window. Programs can do what they want with it. Top level windows typically display it in the caption. Edit controls display it as the text to be edited. 

Share this post


Link to post

Processes are the right way here. Listing all running processes, you can check their parent process and thus easily find all of them being spawned by your process. Of course you can traverse all the call chain to find processes being spawned by processes being spawned by processes being spawned by your process 🙂

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×