如何强制C#.net应用程序在Windows中仅运行一个实例?

如何强制C#.net应用程序在Windows中仅运行一个实例?,c#,.net,windows,winforms,C#,.net,Windows,Winforms,可能重复: 如何强制C#.net应用程序在Windows中仅运行一个实例?我更喜欢类似于以下内容的互斥解决方案。通过这种方式,如果应用程序已经加载,它将重新关注应用程序 using System.Threading; [DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] static extern bool SetForegroundWindow(IntPtr hWnd); /// <summary>

可能重复:


如何强制C#.net应用程序在Windows中仅运行一个实例?

我更喜欢类似于以下内容的互斥解决方案。通过这种方式,如果应用程序已经加载,它将重新关注应用程序

using System.Threading;

[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool SetForegroundWindow(IntPtr hWnd);

/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
   bool createdNew = true;
   using (Mutex mutex = new Mutex(true, "MyApplicationName", out createdNew))
   {
      if (createdNew)
      {
         Application.EnableVisualStyles();
         Application.SetCompatibleTextRenderingDefault(false);
         Application.Run(new MainForm());
      }
      else
      {
         Process current = Process.GetCurrentProcess();
         foreach (Process process in Process.GetProcessesByName(current.ProcessName))
         {
            if (process.Id != current.Id)
            {
               SetForegroundWindow(process.MainWindowHandle);
               break;
            }
         }
      }
   }
}
使用系统线程;
[DllImport(“user32.dll”)]
[返回:Marshallas(UnmanagedType.Bool)]
静态外部bool setforegroundindow(IntPtr hWnd);
/// 
///应用程序的主要入口点。
/// 
[状态线程]
静态void Main()
{
bool createdNew=true;
使用(Mutex Mutex=new Mutex(true,“MyApplicationName”,out createdNew))
{
如果(createdNew)
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
运行(新的MainForm());
}
其他的
{
Process current=Process.GetCurrentProcess();
foreach(Process.getProcessByName(current.ProcessName))中的进程
{
if(process.Id!=current.Id)
{
SetForegroundWindow(process.MainWindowHandle);
打破
}
}
}
}
}

这是我在应用程序中使用的:

static void Main()
{
  bool mutexCreated = false;
  System.Threading.Mutex mutex = new System.Threading.Mutex( true, @"Local\slimCODE.slimKEYS.exe", out mutexCreated );

  if( !mutexCreated )
  {
    if( MessageBox.Show(
      "slimKEYS is already running. Hotkeys cannot be shared between different instances. Are you sure you wish to run this second instance?",
      "slimKEYS already running",
      MessageBoxButtons.YesNo,
      MessageBoxIcon.Question ) != DialogResult.Yes )
    {
      mutex.Close();
      return;
    }
  }

  // The usual stuff with Application.Run()

  mutex.Close();
}

要强制在.net(C#)中只运行一个安装的程序,请在program.cs文件中使用以下代码:

public static Process PriorProcess()
    // Returns a System.Diagnostics.Process pointing to
    // a pre-existing process with the same name as the
    // current one, if any; or null if the current process
    // is unique.
    {
        Process curr = Process.GetCurrentProcess();
        Process[] procs = Process.GetProcessesByName(curr.ProcessName);
        foreach (Process p in procs)
        {
            if ((p.Id != curr.Id) &&
                (p.MainModule.FileName == curr.MainModule.FileName))
                return p;
        }
        return null;
    }
以下是:

[STAThread]
    static void Main()
    {
        if (PriorProcess() != null)
        {

            MessageBox.Show("Another instance of the app is already running.");
            return;
        }
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Form());
    }

另一种方法是检查应用程序的散列和。 在使用互斥锁后(没有按照我想要的方式工作),我的工作方式如下:

    [DllImport("user32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    static extern bool SetForegroundWindow(IntPtr hWnd);

    public Main()
    {
        InitializeComponent();

        Process current = Process.GetCurrentProcess();
        string currentmd5 = md5hash(current.MainModule.FileName);
        Process[] processlist = Process.GetProcesses();
        foreach (Process process in processlist)
        {
            if (process.Id != current.Id)
            {
                try
                {
                    if (currentmd5 == md5hash(process.MainModule.FileName))
                    {
                        SetForegroundWindow(process.MainWindowHandle);
                        Environment.Exit(0);
                    }
                }
                catch (/* your exception */) { /* your exception goes here */ }
            }
        }
    }

    private string md5hash(string file)
    {
        string check;
        using (FileStream FileCheck = File.OpenRead(file))
        {
            MD5 md5 = new MD5CryptoServiceProvider();
            byte[] md5Hash = md5.ComputeHash(FileCheck);
            check = BitConverter.ToString(md5Hash).Replace("-", "").ToLower();
        }

        return check;
    }
它只按进程id检查md5和

如果找到此应用程序的实例,它将聚焦正在运行的应用程序并退出自身

您可以重命名它或对文件执行您想要的操作。如果md5哈希相同,它不会打开两次


有人可以提出建议吗?我知道答案是肯定的,但可能有人正在寻找互斥的替代方案。

请参考一下以这种方式使用MainWindowHandle属性(正如我刚刚发现的):如果关联的进程没有主窗口,则MainWindowHandle值为零。对于已隐藏的进程(即任务栏中不可见的进程),该值也为零。这可能是在任务栏最右边的通知区域中出现图标的过程。“好答案。我喜欢SeaFrimeBaseWindows在接受答案上的使用(如果您遵循该链接,下一个链接指向什么)它使用广播消息并强制窗口位于最顶端——这实际上不会聚焦窗口。这个答案应该是正确的,因为在大多数情况下,新运行的进程有权将焦点传递给另一个进程。SetForeGroundIndow对我不起作用。实际上从未起作用。@user1021726“MyApplicationName“应该是你所独有的。我建议使用有意义的GUID。如果可以最小化应用程序,您可能还需要调用
ShowWindow(process.MainWindowHandle,SW\u RESTORE)
来还原它。提供详细信息。SW_还原为9(从)。这是不正确的方式。我可以在两个实例中运行你的程序——一个是以二进制方式启动的,第二个是从VS.Ok、@greenoldman开始的,但是从什么时候开始,用户/客户“调试”你的应用程序,然后选择在它旁边运行第二个(二进制)。这个答案与我在这个网站上看到的许多基于互斥的安防器相比是相当好的。我知道这是多年以后的事,但是如果有人发现我这样做:如果用户不是管理员(至少在WI7)中,代码>进程。GETPyresteByNAME< /C++ >将引发异常。