扫一扫
分享文章到微信
扫一扫
关注官方公众号
至顶头条
进程匹配
对于每一个应用程序运行实例都会包含该实例的一个或多个进程,而且在程序运行过程中可能会动态的创建或销毁进程,或者访问其他现有进程进行通信。不难发现,在程序最先初始化的那一刻只有一个进程运行,而且应用程序进程生命周期最大进程名称集合是不变的。因此,在应用程序初始化的时候,可以根据进程关键信息检查系统进程列表是否存在同当前初始化进程匹配的进程来确定是否已经运行进程实例。
逻辑处理步骤如下,
1.初始化应用程序,启动程序初始化进程;
2.访问系统进程列表,根据初始化进程关键信息进行匹配查找;
3.没有找到匹配进程(这一步是不会发生的,因为当前初始化进程也在列表中,不过还要看获取进程列表的实现代码怎么写),继续初始化进程,程序初始化完成运行。
4.找到第一个匹配进程,判断找到的进程ID是否同初始化进程ID相同;
5.如果第一个匹配进程ID同初始化进程ID相同,则为当前初始化进程,继续查找;
6.没有找到第二个匹配进程,表明当前运行的是首个实例,继续初始化进程,程序初始化完成运行。
7.找到第二个,表明已有一个实例在运行,停止当前程序初始化,提示已有应用程序运行。
8.如果找到第一个匹配进程ID不同,表明已有一个实例在运行,停止当前程序初始化,提示已有应用程序运行。
可见上面的逻辑实现中用于进程匹配的信息是关键,选择不当功能就无法实现。在这个实例中使用了应用程序完全文件名称作为关键信息。
在代码中首先需要引用下面命名空间,以调用WinAPI函数。
接下来调用两个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);
}
对上面的方法创建一个重载版本,使调用代码更加简洁,
public static bool HandleRunningInstance()
{
Process p = GetRunningInstance();
if (p != null)
{
HandleRunningInstance(p);
return true;
}
return false;
}
上面的方法实现获取已经运行的进程实例的句柄,并获取其焦点显示到前台,这个很有用,在其他实现方式中也可以用到。
在Main函数中调用下面代码实现单一应用程序实例,
简洁的调用为,
可见,在上面的实现过程中,由于关键信息采用应用程序的完整文件名,因此在文件名称或路径名称修改后,以上实现就会失效。
Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1721592
如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。
现场直击|2021世界人工智能大会
直击5G创新地带,就在2021MWC上海
5G已至 转型当时——服务提供商如何把握转型的绝佳时机
寻找自己的Flag
华为开发者大会2020(Cloud)- 科技行者