.Net应用程序唯一运行实例

逻辑处理步骤如下, 
1.初始化应用程序,启动程序初始化进程; 
2.访问系统进程列表,根据初始化进程关键信息进行匹配查找; 
3.没有找到匹配进程(这一步是不会发生的,因为当前初始化进程也在列表中,不过还要看获取进程列表的实现代码怎么写),继续初始化进程,程序初始化完成运行。 
4.找到第一个匹配进程,判断找到的进程ID是否同初始化进程ID相同; 
5.如果第一个匹配进程ID同初始化进程ID相同,则为当前初始化进程,继续查找; 
6.没有找到第二个匹配进程,表明当前运行的是首个实例,继续初始化进程,程序初始化完成运行。 
7.找到第二个,表明已有一个实例在运行,停止当前程序初始化,提示已有应用程序运行。 
8.如果找到第一个匹配进程ID不同,表明已有一个实例在运行,停止当前程序初始化,提示已有应用程序运行。 

可见上面的逻辑实现中用于进程匹配的信息是关键,选择不当功能就无法实现。在这个实例中笔者使用了应用程序完全文件名称作为关键信息。
在代码中首先需要引用下面命名空间,以调用WinAPI函数。 
using System.Runtime.InteropServices; 
把实现唯一运行实例功能的类名取为SingleInstance,在类前面加static关键字为C# 2.0新增的语言特征。 
public static class SingleInstance {} 
使用GetRunningInstance静态方法获取应用程序进程实例,如果没有匹配进程,返回Null值, 
public static Process GetRunningInstance() 

        Process currentProcess = Process.GetCurrentProcess(); //获取当前进程 
        //获取当前运行程序完全限定名 
        string currentFileName = currentProcess.MainModule.FileName; 
        //获取进程名为ProcessName的Process数组。 
        Process[] processes = Process.GetProcessesByName(currentProcess.ProcessName); 
        //遍历有相同进程名称正在运行的进程 
        foreach (Process process in processes) 
        
                if (process.MainModule.FileName == currentFileName) 
                
                        if (process.Id != currentProcess.Id) //根据进程ID排除当前进程 
                                return process;//返回已运行的进程实例 
                
        
        return null


接下来调用两个WinAPI,其功能将在包装方法中描述, 
[DllImport("User32.dll")] 
private static extern bool ShowWindowAsync(IntPtr hWnd, int cmdShow); 
[DllImport("User32.dll")] 
private static extern bool SetForegroundWindow(IntPtr hWnd); 

定义类成员辅助变量, 
private const int WS_SHOWNORMAL = 1; 

以上的方法声明为私有,对其进一步包装,HandleRunningInstance静态方法为获取应用程序句柄,设置应用程序为前台运行,并返回bool值。 
public static bool HandleRunningInstance(Process instance) 

        //确保窗口没有被最小化或最大化 
        ShowWindowAsync(instance.MainWindowHandle, WS_SHOWNORMAL); 
        //设置为foreground window 
        return SetForegroundWindow(instance.MainWindowHandle); 

原文地址:https://www.cnblogs.com/wangfei1511/p/3638697.html