Introduction
For many applications, it is necessary to ensure that only one instance of the program is running at a time. Data management applications which transfer data to an archive folder should not run twice at the same time. Especially in the deleting of files, the behaviour of the application cannot be determined for each case if a second instance is running.
In a data management application I implemented, lots of result files of an industrial test system were to be transferred, depending on the content, to several folders. Some of them were to be deleted and others to be updated. For this, the application has to go through the working folders. All these activities have to be registered in a log file. This application runs for some minutes. I had to ensure that nothing incalculable happens if a user starts the application for a second time. For this, I was looking for a very short and simple solution.
In this article, the possibilities of C# .NET are discussed, including a little experiment. After that, a very simple method for universal use is presented.
Background
The namespace System.Diagnostics.Process
provides all the information which is necessary for this. The process names and process identifiers of all processes are available from GetProcesses()
. Here, only the process name and the process identifier are necessary.
We need GetCurrentProcess().Id
to get the process ID number, and GetCurrentProcess().ProcessName
to get the process name of our own process. For user started processes, the process name is usually the same as the filename of the exe file from which the process is started. The process ID and name of our own processes are to be found out from the list of all processes.
An experiment with a small example code
The sample program below is for doing an experiment to show the context. It is implemented as a console application to keep it as simple as possible. This console application lists all process names and their process IDs. For this, a process array is set up and filled with all process information of the system. A foreach
loop is used to go through the list of process identifiers and process names. The namespace GetCurrentProcess
is used to get the information of the process to compare.
using System;
namespace InstanzenAuflisten
{
class Class1
{
[STAThread]
static void Main(string[] args)
{
string strRemark;
Console.WriteLine("all processes of the system");
Console.WriteLine();
System.Diagnostics.Process[] myProcesses =
System.Diagnostics.Process.GetProcesses();
foreach(System.Diagnostics.Process p in myProcesses)
{
if(p.Id == System.Diagnostics.Process.GetCurrentProcess().Id)
strRemark = " < = my application";
else
strRemark = "";
if(p.ProcessName ==
System.Diagnostics.Process.GetCurrentProcess().ProcessName &&
p.Id != System.Diagnostics.Process.GetCurrentProcess().Id)
{
strRemark = " <= another instance of my application";
}
Console.WriteLine("{0} {1} {2}",p.ProcessName,p.Id,strRemark);
}
Console.WriteLine();
Console.ReadLine();
}
}
}
The running process has the same process identifier and the same process name like the compared process. This case is marked here as " < = my application"
and marks our process itself. If a process is found which has the same process name as the compared process but another process ID, then another instance of our program in the system is found. This case is marked with " <= another instance of my application"
.
To do the experiment, the exe file (InstanzenAuflisten.exe) of the source code below has to be started twice. The listing of the application started at first shows the list of running processes. Only one line is marked as “my application”. This is the process with the same name and identifier as the current process, my "own" process.
To keep the applications running for a longer time, a ConsoleReadline
command is inserted to keep the application open until the Enter key is pressed.
Now, the application has to be started for a second time without pressing the Enter key in the first application. The listing shows here another process identifier (because it is another process) with the same name as “my application”, but the first started application is also to be seen, marked with "another instance …".
The first started application shows a console output like this:
all processes of the system |
|
wmiprvse | 320 |
wmiprvse | 4064 |
... |
smss | 816 |
ltmoh | 2420 |
InstanzenAuflisten | 4024 | < = my application |
svchost | 1348 |
iexplore | 384 |
svchost | 1132 |
FrameworkService | 596 |
... |
System | 4 |
notepad | 1072 |
awhost32 | 536 |
Idle | 0 |
|
In the second screen, the first started application is to be seen as “another instance” with its process identifier we know from the first listing. Both listings are shortened a little here.
all processes of the system |
|
wmiprvse | 320 |
nipalsm | 2136 |
... |
UpdaterUI | 2584 |
svchost | 1396 |
InstanzenAuflisten | 1120 | < = my application |
explorer | 404 |
almxptray | 2436 |
naPrdMgr | 388 |
... |
smss | 816 |
ltmoh | 2420 |
InstanzenAuflisten | 4024 | <= another instance of my application |
svchost | 1348 |
iexplore | 384 |
svchost | 1132 |
FrameworkService | 596 |
... |
System | 4 |
notepad | 1072 |
awhost32 | 536 |
|
With this knowledge, it is simple to build a universal testing method for additional instances like it's shown below, named as OnlyInstance()
.
The code for universal use
The source code of the universal test method:
static bool OnlyInstance()
{
Process[] myProcesses = Process.GetProcesses();
bool bOnly = true;
foreach(Process p in myProcesses)
{
if(p.ProcessName == Process.GetCurrentProcess().ProcessName
&& p.Id != Process.GetCurrentProcess().Id)
{
bOnly = false;
break;
}
}
return bOnly;
}
Using the code
This method can be used to test for additional instances of an application in the following way:
if(OnlyInstance())
{
...
}
else
{
...
}
This is a very simple and short method to take care about additional instances of a running application.
My name is Holger Lippmann. I'm a graduate of the University of Jena with a degree in physics of 1973. I have been working since 1977 in several companies as a programmer and software developer in different technologies, most of the time in assembler on several microprocessors(Zilog, Intel, Motorola, PIC of Microchip).
From 1995 till 2000 I was working in other projects, most in physics and sensorics. Programming stayed in the background this time.
Since 2000 I'm working again in Windows programming, till 2004 mainly in VB and now, especially for industrial test systems in telecommunications industries, in C#.NET and, outside of Windows, in assembler and C for specific microcontroller systems.