Finding a running instance of my app

R

Rune Jacobsen

Hey all,

Maybe someone knows this problem; I have a C# WinForms app that every
now and then has a new version that I deploy to my users using an
installation script written with the NSIS installer. To improve on this,
I want the installer to shut down any running instances of my
application when it does the installation.

To do this, I have implemented the following function to kill any
instances I find (yeah, I have the pinvoke for PostMessage and the other
functions right):

(Sorry if the posted code comes out wrong)

System.Diagnostics.Process[] myProcesses;
myProcesses = System.Diagnostics.Process.GetProcessesByName("MyApp");
foreach (System.Diagnostics.Process instance in myProcesses)
{
if( instance.MainWindowHandle == (System.IntPtr)0 )
{
IntPtr h = IntPtr.Zero;
int tid;
int pid;
do
{
pid = 0;
// get the window handle
h = FindWindowEx(IntPtr.Zero, h, null, null);
// get the process id (and thread id)
tid = GetWindowThreadProcessId(h, out pid);
if (pid == instance.Id)
{
PostMessage( h, 0x11, 0, 0 );
break;
}
} while( !h.Equals(IntPtr.Zero) );
}
else
PostMessage( instance.MainWindowHandle, 0x11, 0, 0 );
}

This is partially based on something I found on the web.

It fine if the Window of the application is open - then
instance.MainWindowHandle is ok, and the shutdown message works fine (I
used this because this is a systray based app, closing the Window does
nothing, but 0x11 is what Windows uses to shut down the app when the
system is going down, I figure I can use this for my own shutdown as
well). So that is no problem. If the user minimizes the application, the
window is hidden - in that case, it loops trough all the windows, and
sends the 0x11 message to any windows it finds that belongs to the found
process ID.

However, one thing that doesn't work, is if the main window of the
application is closed, and other windows are open - then
MainWindowHandle will return 0, AND the code above will not find any
windows owned by the process. Thus I can not post the message, and
nothing will happen.

Having the main window of my app closed while other of it's windows are
open isn't an uncommon situation with this program, so my question is -
does anyone know what to do? Why is the window not "existing" and owned
by the correct process when another window has been opened?

Any insight will be highly appreciated!

Thanks,

Rune
 
N

Nicholas Paldino [.NET/C# MVP]

Rune,

I wouldn't do it this way at all.

What I would do is make a call to RegisterWindowMessage in your
application. This will allow you to pass a string to the function, and get
a windows message id which is unique throughout the system.

You would store this in your app, and then override the WndProc method
to check against that message id. If you get it, you simply exit the
application (calling Application.Exit should do the trick).

Then, in your update program, you would call PostMessage, passing the
HWND_BROADCAST constant for the window handle. This will cause the message
to be sent to all top level windows. Other applications will ignore the
message, because they dont know how to interpret it (assuming that they play
nice and call RegisterWindowsMessage to create their message ids). Your
app, however, will know what to do.

You just have to call RegistrWindowMessage in your update app with the
same string to indicate the message to send.

Hope this helps.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Rune Jacobsen said:
Hey all,

Maybe someone knows this problem; I have a C# WinForms app that every now
and then has a new version that I deploy to my users using an installation
script written with the NSIS installer. To improve on this, I want the
installer to shut down any running instances of my application when it
does the installation.

To do this, I have implemented the following function to kill any
instances I find (yeah, I have the pinvoke for PostMessage and the other
functions right):

(Sorry if the posted code comes out wrong)

System.Diagnostics.Process[] myProcesses;
myProcesses = System.Diagnostics.Process.GetProcessesByName("MyApp");
foreach (System.Diagnostics.Process instance in myProcesses)
{
if( instance.MainWindowHandle == (System.IntPtr)0 )
{
IntPtr h = IntPtr.Zero;
int tid;
int pid;
do
{
pid = 0;
// get the window handle
h = FindWindowEx(IntPtr.Zero, h, null, null);
// get the process id (and thread id)
tid = GetWindowThreadProcessId(h, out pid);
if (pid == instance.Id)
{
PostMessage( h, 0x11, 0, 0 );
break;
}
} while( !h.Equals(IntPtr.Zero) );
}
else
PostMessage( instance.MainWindowHandle, 0x11, 0, 0 );
}

This is partially based on something I found on the web.

It fine if the Window of the application is open - then
instance.MainWindowHandle is ok, and the shutdown message works fine (I
used this because this is a systray based app, closing the Window does
nothing, but 0x11 is what Windows uses to shut down the app when the
system is going down, I figure I can use this for my own shutdown as
well). So that is no problem. If the user minimizes the application, the
window is hidden - in that case, it loops trough all the windows, and
sends the 0x11 message to any windows it finds that belongs to the found
process ID.

However, one thing that doesn't work, is if the main window of the
application is closed, and other windows are open - then MainWindowHandle
will return 0, AND the code above will not find any windows owned by the
process. Thus I can not post the message, and nothing will happen.

Having the main window of my app closed while other of it's windows are
open isn't an uncommon situation with this program, so my question is -
does anyone know what to do? Why is the window not "existing" and owned by
the correct process when another window has been opened?

Any insight will be highly appreciated!

Thanks,

Rune
 
N

Nick Hounsome

Rune Jacobsen said:
Hey all,

Maybe someone knows this problem; I have a C# WinForms app that every now
and then has a new version that I deploy to my users using an installation
script written with the NSIS installer. To improve on this, I want the
installer to shut down any running instances of my application when it
does the installation.

To do this, I have implemented the following function to kill any
instances I find (yeah, I have the pinvoke for PostMessage and the other
functions right):

(Sorry if the posted code comes out wrong)

System.Diagnostics.Process[] myProcesses;
myProcesses = System.Diagnostics.Process.GetProcessesByName("MyApp");
foreach (System.Diagnostics.Process instance in myProcesses)
{
if( instance.MainWindowHandle == (System.IntPtr)0 )
{
IntPtr h = IntPtr.Zero;
int tid;
int pid;
do
{
pid = 0;
// get the window handle
h = FindWindowEx(IntPtr.Zero, h, null, null);
// get the process id (and thread id)
tid = GetWindowThreadProcessId(h, out pid);
if (pid == instance.Id)
{
PostMessage( h, 0x11, 0, 0 );
break;
}
} while( !h.Equals(IntPtr.Zero) );
}
else
PostMessage( instance.MainWindowHandle, 0x11, 0, 0 );
}

This is partially based on something I found on the web.

It fine if the Window of the application is open - then
instance.MainWindowHandle is ok, and the shutdown message works fine (I
used this because this is a systray based app, closing the Window does
nothing, but 0x11 is what Windows uses to shut down the app when the
system is going down, I figure I can use this for my own shutdown as
well). So that is no problem. If the user minimizes the application, the
window is hidden - in that case, it loops trough all the windows, and
sends the 0x11 message to any windows it finds that belongs to the found
process ID.

However, one thing that doesn't work, is if the main window of the
application is closed, and other windows are open - then MainWindowHandle
will return 0, AND the code above will not find any windows owned by the
process. Thus I can not post the message, and nothing will happen.

Having the main window of my app closed while other of it's windows are
open isn't an uncommon situation with this program, so my question is -
does anyone know what to do? Why is the window not "existing" and owned by
the correct process when another window has been opened?

Any insight will be highly appreciated!

I have seen many examples of how to implement a single instance application
and they all use remoting to look for the running instance and tell it what
to do. Of course in this case they pass it a new file or some such but they
could just as easily tell it to shut down.

Can't remember the details because I don't use remoting much but it was v.
v. simple
 
R

Rune Jacobsen

Nicholas said:
Rune,

I wouldn't do it this way at all.

What I would do is make a call to RegisterWindowMessage in your
application. This will allow you to pass a string to the function, and get
a windows message id which is unique throughout the system.

[snip]
Hope this helps.

It did indeed! Thanks for very valuable input! The application now shuts
down no matter what kind of state it is in when the message comes!

You just earned yourself a "thank you" in the about box! :)

Rune
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top