.net 确定同一进程是否有多个实例在运行?
我解救了这个VB6样式化的代码段,打算进行重构/更新,但后来发现它并没有按预期工作 代码应该可以随时轻松确定是否有多个同一进程的实例在运行:.net 确定同一进程是否有多个实例在运行?,.net,vb.net,process,mutex,multiple-instances,.net,Vb.net,Process,Mutex,Multiple Instances,我解救了这个VB6样式化的代码段,打算进行重构/更新,但后来发现它并没有按预期工作 代码应该可以随时轻松确定是否有多个同一进程的实例在运行: Public Declare Function CreateMutexA Lib "Kernel32.dll" ( ByVal lpSecurityAttributes As Integer, ByVal bInitialOwner As Boolean, ByVal lpName As String) As
Public Declare Function CreateMutexA Lib "Kernel32.dll" (
ByVal lpSecurityAttributes As Integer,
ByVal bInitialOwner As Boolean,
ByVal lpName As String) As Integer
Public Declare Function GetLastError Lib "Kernel32.dll" () As Integer
Public Function My_Application_Is_Already_Running() As Boolean
' Attempt to create defualt mutex owned by process
CreateMutexA(0, True, Process.GetCurrentProcess().MainModule.ModuleName.ToString)
Return (GetLastError() = 183) ' 183 = ERROR_ALREADY_EXISTS
End Function
如果我只有一个实例在运行,那么它将返回False
,如果我启动同一进程的两个实例,那么函数将按预期返回True
,问题是当其中一个实例关闭/消失时,函数仍然返回True
我如何修复上面的代码或使用适当的方法来执行此操作
我的目的是要有一个合适的助手函数,可以在任何时候从任何应用程序中安全地调用,不要硬编码一个信号量/互斥算法,该算法只适用于特定环境下的一个特定项目等。。。函数应该是一个抽象,以避免除了调用函数以获得结果以外的任何操作,就像上面的函数(错误地)所做的那样
更新 我试过这个:
Public NotInheritable Class AppUtil
Private Shared created As Boolean = False
Private Shared waitHandle As New EventWaitHandle(initialState:=False,
mode:=EventResetMode.ManualReset,
name:="AppUtil#IsRunningAnyOtherInstance",
createdNew:=created)
Public Shared Function IsRunningAnyOtherInstance() As Boolean
Return Not created
End Function
End Class
在窗体中按钮的事件处理程序中,我有以下调用:
MsgBox(AppUtil.IsRunningAnyOtherInstance)
编译解决方案后,我启动应用程序的两个实例,第一个实例返回False,而较新的实例返回True。两者都应返回True,因为有2个实例打开,而当关闭其中一个窗体时,应返回False(因为只有一个实例打开)
注:考虑到AppUtil类不可实例化。现在要容易得多 这会将名为“svchost”的进程数返回到控制台-您可以计算出重置值eh?:0) 请注意,您搜索的名称没有扩展名。此外,它还返回来自所有用户的所有进程的结果
Console.WriteLine(Process.getProcessByName(“svchost”).Count)实现这一点的方法有很多,在
C#
中,您可以使用互斥锁、信号量
甚至Windows事件
,例如:
private static EventWaitHandle _handle;
bool created ;
_handle = new EventWaitHandle (false, EventResetMode.ManualReset, "my program#startup", out created) ;
if (created)
{
StartApp();
}
else
{
Exit();
}
更多信息
另一种方法是:
string procName = Process.GetCurrentProcess().ProcessName;
if (Process.GetProcessesByName(procName).Length == 1)
{
// do whatever //
}
我认为最简单的方法是使用互斥类:
bool isFirstInstance = false;
Mutex mutex = new Mutex(true, "MyUniqueAppKeyOrGuid", out isFirstInstance);
第一个实例将变量isFirstInstance
设置为true
-所有下一个实例将其设置为false
如果您想要一个单实例vb应用程序,您可以打开项目属性、应用程序选项卡,并选中“生成单实例应用程序”复选框。快速测试后,它似乎像预期的那样工作。您确定没有其他实例正在运行吗?请记住,关闭(程序窗口)并不一定意味着进程终止。如果要跟踪打开的窗口,必须使用不同的方法。@JerryM感谢您的评论,我知道项目设置中的“生成单实例应用程序”选项,但上面的功能是将其包含在帮助程序dll中,然后,调用helper函数的进程应该确定是否有多个实例正在运行,仅此而已。@varocabas也感谢您的评论,好久不见了。我确信没有其他实例正在运行,我将解释如何重现错误(至少在我这边):1。使用表单创建一个项目,以便从按钮或任何位置调用函数。2.编译项目,然后运行已编译程序集的两个实例。3.在form1中,调用函数(它将返回True),在form2中调用函数(它将返回True),关闭任何窗体/进程,然后在另一个窗体上重新调用函数,它仍然返回True。(是的,同样的事情。我停顿了很长时间,但已经存在了几个月)这很奇怪,因为我模拟了您的条件(有一个按钮和一个MessageBox
)不起作用。之前,我从主窗体的Load
事件调用函数/MessageBox
,这样它就起作用了!主要区别是,在第二种情况下,最后一次检查时必须关闭两个打开的窗口;这(=关闭所有打开的窗口)是避免这种奇怪行为的方法。现在有点晚了;明天将重新审视它(如果还没有解决方案的话)。感谢您的回答,但请考虑到一个可执行文件可以被复制,然后重命名,这样同一个应用程序的多个具有不同文件名的实例就可以运行,在这种情况下,您公开的解决方案将不会像互斥锁那样有效。@ElektroStudios由于您没有选择任何答案,我继续进行了一些测试。David是Approach是最好的一个(我正要写我自己的答案,但它太类似于这个)。问题是David正在硬编码可执行文件的名称,什么不是必需的(为什么不在运行时获取名称?)。PS:我昨天没有评论它(已经有点累了),但现在回想一下互斥体和应用程序没有关闭所有窗口的问题(我记得几年前有一群人使用互斥体处理所有事情,但这是有问题的)@ElektroStudios我不确定我是否理解你的观点。但进程名基本上就是文件名。正如所说的,这种方法非常有效:它将跟踪使用相同名称执行的所有文件(=识别进程/应用程序的唯一方法;除非依赖GUI/注册表使事情过于复杂)。例如:您有file.exe,将其复制三次并执行三个副本,此方法将知道它。现在,如果您将其中一个副本的名称更改为file2.exe,此方法将不会检测到它(但也不会检测到计算机中的任何其他内容)@ElektroStudios如前所述,有许多方法可以实现这一点,但您必须自己处理。例如:强制识别应用程序以连接到识别源(例如,Windows注册表、远程/本地数据)