如何强制 C# .net 应用程序在 Windows 中仅运行一个实例? [复制]
Posted
技术标签:
【中文标题】如何强制 C# .net 应用程序在 Windows 中仅运行一个实例? [复制]【英文标题】:How to force C# .net app to run only one instance in Windows? [duplicate] 【发布时间】:2008-10-08 18:15:35 【问题描述】:可能重复:What is the correct way to create a single instance application?
如何强制 C# .net 应用在 Windows 中只运行一个实例?
【问题讨论】:
【参考方案1】:我更喜欢类似于以下的互斥锁解决方案。这样,如果它已经加载,它会重新关注应用程序
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;
【讨论】:
关于以这种方式使用 MainWindowHandle 属性的一点仅供参考(正如我刚刚发现的那样):“如果关联的进程没有主窗口,MainWindowHandle 值为零。对于已隐藏的进程,即在任务栏中不可见的进程,该值也为零。对于在通知区域中显示为图标的进程可能是这种情况,在任务栏的最右侧。” 好答案。我喜欢在接受答案上使用 SetForegroundWindow (如果您按照该链接加上下一个链接到的内容),它使用广播消息并强制窗口位于最顶层——这实际上不会聚焦窗口。这个答案应该是,因为在大多数情况下,新运行的进程有权将焦点传递给另一个进程。 SetForegroundWindow 不适合我。实际上,从来没有工作过。 @user1021726 "MyApplicationName" 应该是您独有的任何东西。我会建议一些有意义的东西,然后是 GUID。 如果您的应用程序可以最小化,您可能还需要调用ShowWindow( process.MainWindowHandle, SW_RESTORE )
来恢复它。 ***.com/questions/4566632/… 提供详细信息。 SW_RESTORE 为 9(来自msdn.microsoft.com/en-gb/library/windows/desktop/…)。【参考方案2】:
要在 .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());
【讨论】:
这是不正确的方法。我可以在两个实例中运行你的程序——一个作为二进制启动,第二个从 VS 启动。 好的,@greenoldman,但是从什么时候开始用户/客户“调试”您的应用程序,然后选择在其旁边运行第二个(二进制)。与我在这个网站上看到的许多基于 Mutex 的答案相比,这个答案相当不错。 我知道这是几年后的事了,但万一有人像我一样发现这个:如果用户不是管理员(至少在 Win7 中)Process.GetProcessesByName
将抛出异常。【参考方案3】:
这是我在我的应用程序中使用的:
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();
【讨论】:
【参考方案4】:单实例应用程序的另一种方法是检查它们的哈希和。 在弄乱了互斥锁(没有按我想要的那样工作)之后,我得到了它的工作方式:
[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 哈希相同,则不会打开两次。
有人对此有什么建议吗?我知道它已被回答,但也许有人正在寻找互斥锁替代品。
【讨论】:
以上是关于如何强制 C# .net 应用程序在 Windows 中仅运行一个实例? [复制]的主要内容,如果未能解决你的问题,请参考以下文章
当任何数学运算在 .net 4 中产生“NaN”时,如何强制 C# 编译器抛出异常?
C# .Net 4.0 应用程序中托管的 C++ ActiveX 控件中的 Xml.Serializer 非法强制转换异常
如何强制更新/防止在 Linux 上运行并由 nginx 反向代理服务器托管的 .NET Core Web 应用程序的 HTML 缓存