.net 确定同一进程是否有多个实例在运行?

.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

我解救了这个VB6样式化的代码段,打算进行重构/更新,但后来发现它并没有按预期工作

代码应该可以随时轻松确定是否有多个同一进程的实例在运行:

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注册表、远程/本地数据)