2

I know how to make sure that I run only one instance of an application at a time: How to check if another instance of the application is running

But... How can I make sure that when a second instance is started, the first instance will be closed (instead of just exiting the 2nd one which is usually done). And preferably waiting for it to be fully closed.

If more than 2 instances are started simultaneously then only the last one should be allowed to 'live'.

I got it (thanks you all the answers). My solution below:

        #region Kill other running processes of this application
        List<Process> processes = Process.GetProcessesByName(Process.GetCurrentProcess().ProcessName).ToList();
        if (processes.Count > 1)
        {
            processes.Sort((x, y) => DateTime.Compare(x.StartTime, y.StartTime));
            for (int i = 0; i < processes.Count - 1; i++)
            {
                processes[i].CloseMainWindow();
                processes[i].WaitForExit();
            }
        }
        #endregion

        Console.WriteLine(string.Format("{0}:{1}", DateTime.Now.Minute, DateTime.Now.Second));
        Console.ReadLine();
Community
  • 1
  • 1
Napoleon
  • 1,072
  • 5
  • 17
  • 31
  • 1
    find the other instance process id and kill it maybe? – mihail Nov 12 '12 at 16:21
  • 3
    This is not really an answer, but I would not do what you are trying to do. For example, if there is unsaved stuff in your first instance and you open a second one, you may lose data when you close it. When dealing with Singleton, when there is a opened instance, preferred bahaviour is to avoid another instance and not close instance 1 and open instance 2 – Steven Nov 12 '12 at 16:21
  • Get process by name when second instance is started and kill all proceses with that name – swiftgp Nov 12 '12 at 16:22
  • Why the last one? Wouldn't that mean you could potentially lose data? Why not focus/activate the original? Your response here may inform our answers. – Joel Coehoorn Nov 12 '12 at 16:22
  • Why not just have a container that does the instantiaion of the object you want, and remembers all the objects it has created, and whenever a new oject is created, it terminates the old objects... and verifies they clean up after themselves... – Paul Nov 12 '12 at 16:22
  • Isn't this a duplicate (or near duplicate) of http://stackoverflow.com/questions/917883/c-sharp-how-to-single-instance-application-that-accepts-new-parameters or possibly http://stackoverflow.com/questions/19147/what-is-the-correct-way-to-create-a-single-instance-application? – David Nov 12 '12 at 16:38
  • No it's not a duplicate of those questions. I want the first ones killed because if a new instance was started it means that something went wrong with the previous instances. And they do not always show up in the taskmanager because the application is designed for the G19 Keyboard. Sometimes it runs on the keyboard somehow and Windows thinks that it closed it (which it did not). And if I just kill the second instance only for example then I'm still stuck with some frozen/half closed applet. – Napoleon Nov 12 '12 at 17:04

3 Answers3

2

You can use WindowsFormsApplicationBase class of Microsoft.VisualBasic.dll.

StartupNextInstance event is raised in first app when another instance is created. In this event you can kill current process.

 Process.GetCurrentProcess().Kill();

This will make sure that new instance is alive, and previous instances are closed.

Tilak
  • 30,108
  • 19
  • 83
  • 131
  • The answer is flagged C#. What is the visual basic reference here? We all know that these items has been implemented in many libraries over the internet or the one you mentioned. But the question here is about the implementation of that logic, not using it. However your answer seems to be not enough for the logic. – Rikki Nov 12 '12 at 16:44
  • Who voted -1? Clarify your reasoning. @Mohammad Goundarzi -> Microsoft.VisualBasic.dll denotes the library is provided by Visual Basic team, it does not says it is usable only in VB. It is .NET library (used extensively in C# as well), and uses remoting as underlying interprocess communication between processes. – Tilak Nov 12 '12 at 17:00
  • @Mohammad Goundarzi -> To me question seems retaining only last instance, and closing all the previous one. Precisely the same thing I have specified. Nothing more nothing less. How can you jugde the answer is not sufficient enough? Have you tried, or something is not clear? This is of course from the internet, but something tried and tested (By MSFT team, and also by me for my projects) – Tilak Nov 12 '12 at 17:09
  • The answer is simply that the questioner didn't ask for any library of implemented solution. However as I already mentioned, you are not clear enough for me as a dummy!, so how your answer could be so enough for the others who don't know enough and asking for a help? By the way, if I was wrong in voting you down, don't worry cause it will be voted up automatically by the others who see your answer. Cheers – Rikki Nov 12 '12 at 17:12
  • Sir I'm not in the position to judge you. I just did vote. People vote here. It's the reason why we all are here together. So if it's wrong somebody else will see and vote you up. There is nothing to be angry about. By the way I asked the questioner himself to take a look at your answer and vote up if it's useful for him. Cheers – Rikki Nov 12 '12 at 17:17
  • I am not angry mate. Cheers :). – Tilak Nov 12 '12 at 17:35
  • Thank you man, for just respecting my vote, no matter I was wrong or right. ;) Cheers – Rikki Nov 12 '12 at 17:48
  • I'm not a fan of using VB libraries when it's not necessary. But there's nothing wrong with it of course. I read it's description on MSDN and yes it could work. – Napoleon Nov 13 '12 at 13:01
  • 1
    There is a difference between VB libraries, and libraries by Visual Basic team. The library is .NET library and not visual basic library (will not work on VB6/VBA) – Tilak Nov 14 '12 at 04:32
1

There's probably a better way to do this involving other inter-communication between processes and events, but here's a basic method that requires no research(at least on my part)

When a process starts, make a file(maybe with a timestamp) to signal if it's started.

Have the original process check the file periodically, and stop it if it sees a newer timestamp

1

I think you are a little bit confused about the logic yourself. By the way here are some items you should use to do such a thing:

1- System.Diagnostics.Process.WaitForExit

With calling this method for a specific process instance, you can wait until the process is exited completely after you called the "Kill" or "Shutdown" method. It will close the main window in the process if it's a windows app. For the applications which have some confirmation boxes for exiting, it will wait until user confirm or cancel the dialog box (Like when your windows is shutting down while your applications are already open).

2- System.Diagnostics.Process.ExitCode

If you want to access the result of the exist message you send to a process, you should call the value of this property after calling "WaitForExit" function. I guess you can use this property to find out if the first process exited or not and with what reason from the second process.

3- public static int Main

Because you need to access the exit code from the outside of the process you should change the return value of "Main" method to int. This way you can return a value in the first process and access it in the second process through the "ExitCode" property. If returning a value in the "Main" function is difficult in your situation, you can pass the exit code by calling the 4th item.

4- System.Windows.Application.Shutdown (Exit in .NET < 4)

Calling this method does the exact thing as returning the value in the "Main" function.

5- System.Diagnostics.Process.GetProcessesByName

After all by calling this static method you can get all the processes by specified name.

Hope it helps. I just tried to explain everything as simple as possible. These all are the tools you can use to implement the logic. The rest would be so simple if you know these abilities that .NET provided for you.

After all, as I've already forgot to say, if you are interested in doing the right thing, in my opinion and as my experience says, there is a technology that has been made just for these kind of logics.

6- .NET Interprocess Communications or IPC (a sample on code) (introduction on codeguru)

IPC is based on the .NET remoting (the most interesting discussion in .NET in my personal opinion) BUT regardless of what the name says, it's not only for remote communications. The remoting has many sections and on of those is the Inter-Process-Communication (IPC). It's the hard, but the best way if you ask me.

Cheers

Rikki
  • 3,338
  • 1
  • 22
  • 34
  • Thanks. That really helped me out. Just one question. In my solution I have "processes.Count - 1" in the for-loop. But for some reason it doesn't kill the current process (which is good). But I don't understand why. Shouldn't it be "processes.Count - 2"? – Napoleon Nov 12 '12 at 17:01
  • Happy to hear that it was useful. By using **processes.Count - 1** or simply say **someArray.Count - 1** you are referring to the last item of the array and you must be sure that the array has at least one item stored in it. Simply -2 refers to **the one before the last item** that causes you checking some other constraints to prevent raising unhandled exceptions. Try to analyse everything as simple as they are in the real world. Hope it helps. Cheers. – Rikki Nov 12 '12 at 17:05
  • Sorry it's ofcourse because I used the < operator. An extra "-1" would skip 2 in total. That's why. – Napoleon Nov 12 '12 at 17:11
  • I don't see the code but what you mentioned is exactly right. @Napoleon may I ask you a favor? Please take a look at the answer of Tilak, see if it's useful vote him up. I did vote the answer down cause I had my reasons and I think he's got angry about it. Thank you body. ;) – Rikki Nov 12 '12 at 17:15