Finding a running instance of my app

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Rune Jacobsen

    Finding a running instance of my app

    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.Diagnost ics.Process[] myProcesses;
    myProcesses = System.Diagnost ics.Process.Get ProcessesByName ("MyApp");
    foreach (System.Diagnos tics.Process instance in myProcesses)
    {
    if( instance.MainWi ndowHandle == (System.IntPtr) 0 )
    {
    IntPtr h = IntPtr.Zero;
    int tid;
    int pid;
    do
    {
    pid = 0;
    // get the window handle
    h = FindWindowEx(In tPtr.Zero, h, null, null);
    // get the process id (and thread id)
    tid = GetWindowThread ProcessId(h, out pid);
    if (pid == instance.Id)
    {
    PostMessage( h, 0x11, 0, 0 );
    break;
    }
    } while( !h.Equals(IntPt r.Zero) );
    }
    else
    PostMessage( instance.MainWi ndowHandle, 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.MainWi ndowHandle 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
    MainWindowHandl e 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
  • Nicholas Paldino [.NET/C# MVP]

    #2
    Re: Finding a running instance of my app

    Rune,

    I wouldn't do it this way at all.

    What I would do is make a call to RegisterWindowM essage 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.Exi t 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 RegisterWindows Message to create their message ids). Your
    app, however, will know what to do.

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

    Hope this helps.


    --
    - Nicholas Paldino [.NET/C# MVP]
    - mvp@spam.guard. caspershouse.co m

    "Rune Jacobsen" <rune.jacobsen@ no_spam.broadpa rk.no> wrote in message
    news:43be8f22$1 @news.broadpark .no...[color=blue]
    > 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.Diagnost ics.Process[] myProcesses;
    > myProcesses = System.Diagnost ics.Process.Get ProcessesByName ("MyApp");
    > foreach (System.Diagnos tics.Process instance in myProcesses)
    > {
    > if( instance.MainWi ndowHandle == (System.IntPtr) 0 )
    > {
    > IntPtr h = IntPtr.Zero;
    > int tid;
    > int pid;
    > do
    > {
    > pid = 0;
    > // get the window handle
    > h = FindWindowEx(In tPtr.Zero, h, null, null);
    > // get the process id (and thread id)
    > tid = GetWindowThread ProcessId(h, out pid);
    > if (pid == instance.Id)
    > {
    > PostMessage( h, 0x11, 0, 0 );
    > break;
    > }
    > } while( !h.Equals(IntPt r.Zero) );
    > }
    > else
    > PostMessage( instance.MainWi ndowHandle, 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.MainWi ndowHandle 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 MainWindowHandl e
    > 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[/color]


    Comment

    • Nick Hounsome

      #3
      Re: Finding a running instance of my app


      "Rune Jacobsen" <rune.jacobsen@ no_spam.broadpa rk.no> wrote in message
      news:43be8f22$1 @news.broadpark .no...[color=blue]
      > 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.Diagnost ics.Process[] myProcesses;
      > myProcesses = System.Diagnost ics.Process.Get ProcessesByName ("MyApp");
      > foreach (System.Diagnos tics.Process instance in myProcesses)
      > {
      > if( instance.MainWi ndowHandle == (System.IntPtr) 0 )
      > {
      > IntPtr h = IntPtr.Zero;
      > int tid;
      > int pid;
      > do
      > {
      > pid = 0;
      > // get the window handle
      > h = FindWindowEx(In tPtr.Zero, h, null, null);
      > // get the process id (and thread id)
      > tid = GetWindowThread ProcessId(h, out pid);
      > if (pid == instance.Id)
      > {
      > PostMessage( h, 0x11, 0, 0 );
      > break;
      > }
      > } while( !h.Equals(IntPt r.Zero) );
      > }
      > else
      > PostMessage( instance.MainWi ndowHandle, 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.MainWi ndowHandle 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 MainWindowHandl e
      > 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![/color]

      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



      Comment

      • Rune Jacobsen

        #4
        Re: Finding a running instance of my app

        Nicholas Paldino [.NET/C# MVP] wrote:[color=blue]
        > Rune,
        >
        > I wouldn't do it this way at all.
        >
        > What I would do is make a call to RegisterWindowM essage 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.
        >
        >[/color]

        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

        Comment

        Working...