代码之家  ›  专栏  ›  技术社区  ›  Andy

检测应用程序的另一个实例是否已在运行

  •  13
  • Andy  · 技术社区  · 16 年前

    • 实例1加载并获取互斥锁。
    • 实例2加载,无法获取互斥,知道还有另一个实例。到目前为止,还不错。
    • 实例3加载,得到互斥锁,却不知道实例2还在运行。

    (C#,桌面应用程序)

    5 回复  |  直到 16 年前
        1
  •  12
  •   Sandor Drieënhuizen    14 年前

    这可能正是你想要的。它还有一个很好的附加特性,就是将已经运行的实例向前推进。

    编辑: 已更新代码以自动确定应用程序标题。

    using System;
    using System.Diagnostics;
    using System.Linq;
    using System.Reflection;
    using System.Runtime.InteropServices;
    
    static void Main()
    {
        if (!EnsureSingleInstance())
        {
            return;
        }
    
        //...
    }
    
    static bool EnsureSingleInstance()
    {
        Process currentProcess = Process.GetCurrentProcess();
    
        var runningProcess = (from process in Process.GetProcesses()
                              where
                                process.Id != currentProcess.Id &&
                                process.ProcessName.Equals(
                                  currentProcess.ProcessName,
                                  StringComparison.Ordinal)
                              select process).FirstOrDefault();
    
        if (runningProcess != null)
        {
            ShowWindow(runningProcess.MainWindowHandle, SW_SHOWMAXIMIZED);
            SetForegroundWindow(runningProcess.MainWindowHandle);
    
            return false;
        }
    
        return true;
    }
    
    [DllImport("user32.dll", EntryPoint = "SetForegroundWindow")]
    private static extern bool SetForegroundWindow(IntPtr hWnd);
    
    [DllImport("user32.dll")]
    private static extern Boolean ShowWindow(IntPtr hWnd, Int32 nCmdShow);
    
    private const int SW_SHOWMAXIMIZED = 3;
    
        2
  •  2
  •   ChrisF    16 年前

    Scott Hanselman's blog

    他的例子激活了第一个实例,当第二个实例尝试时。

        3
  •  1
  •   Panagiotis Kanavos    16 年前

    尝试使用信号量而不是互斥量

        4
  •  0
  •   GBegen    16 年前

    GetLastError() CreateMutex() ? 如果它回来了 ERROR_ALREADY_EXISTS ,则会有另一个正在运行的应用程序实例。

    根据 http://msdn.microsoft.com/en-us/library/ms682411%28VS.85%29.aspx ,

    如果互斥体是命名互斥体 对象在此函数之前存在 现有对象GetLastError 返回错误“\”已存在“\”, 忽略binitilowner,并且 所有权。但是,如果调用方 有限访问权限,功能 将失败,错误为\u访问被拒绝,并且 功能。

    编辑:

    在.Net中,使用Mutex构造函数返回createdNew标志, http://msdn.microsoft.com/en-us/library/bwe34f1k%28VS.80%29.aspx :

    public Mutex (
        bool initiallyOwned,
        string name,
        out bool createdNew
    )
    
        5
  •  0
  •   Community Mohan Dere    9 年前

    C#: How to get the full path of running process? (杰夫的解决方案)。这样,您还可以通过路径和远程终端会话id检查其他正在运行的实例是否匹配:

        static bool EnsureSingleInstance()
        {
            Process currentProcess = Process.GetCurrentProcess();
    
            var wmiQueryString = "SELECT ProcessId, ExecutablePath, CommandLine FROM Win32_Process";
            using (var searcher = new ManagementObjectSearcher(wmiQueryString))
            using (var results = searcher.Get())
            {
                var query = from p in Process.GetProcesses()
                            join mo in results.Cast<ManagementObject>()
                            on p.Id equals (int)(uint)mo["ProcessId"]
                            select new
                            {
                                Process = p,
                                Path = (string)mo["ExecutablePath"],
                                CommandLine = (string)mo["CommandLine"],
                            };
    
                var runningProcess = (from process in query
                                      where
                                        process.Process.Id != currentProcess.Id &&
                                        process.Process.ProcessName.Equals(
                                          currentProcess.ProcessName,
                                          StringComparison.Ordinal) &&
                                          process.Path == currentProcess.MainModule.FileName &&
                                          process.Process.SessionId == currentProcess.SessionId
                                      select process).FirstOrDefault();
    
                return runningProcess == null;
            }
        }