在.NET中阻止给定应用程序的多个实例?
在.NET中,防止多个应用程序同时运行的最佳方法是什么? 如果没有“最好”的技术,每个解决scheme都要考虑哪些问题?
使用互斥。 上面使用GetProcessByName的例子之一有许多警告。 这里有一个关于这个问题的好文章:
http://odetocode.com/Blogs/scott/archive/2004/08/20/401.aspx
[STAThread] static void Main() { using(Mutex mutex = new Mutex(false, "Global\\" + appGuid)) { if(!mutex.WaitOne(0, false)) { MessageBox.Show("Instance already running"); return; } Application.Run(new Form1()); } } private static string appGuid = "c0a76b5a-12ab-45c5-b9d9-d693faa6e7b9";
if (Process.GetProcessesByName(Process.GetCurrentProcess().ProcessName).Length > 1) { AppLog.Write("Application XXXX already running. Only one instance of this application is allowed", AppLog.LogMessageType.Warn); return; }
这是您需要确保只有一个实例正在运行的代码。 这是使用命名互斥体的方法。
public class Program { static System.Threading.Mutex singleton = new Mutex(true, "My App Name"); static void Main(string[] args) { if (!singleton.WaitOne(TimeSpan.Zero, true)) { //there is already another instance running! Application.Exit(); } } }
Hanselman有一篇关于使用Microsoft.VisualBasic程序集的WinFormsApplicationBase类的文章 。
这听起来像迄今为止已经提出了3种基本技术。
- 从Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase类派生,并将IsSingleInstance属性设置为true。 (我相信这里的一个警告是,这将无法与WPF应用程序,是吗?)
- 使用一个已命名的互斥体并检查它是否已经创build。
- 获取正在运行的进程的列表并比较进程的名称。 (这要求您的进程名称相对于给定用户计算机上运行的任何其他进程是唯一的)。
任何警告我错过了?
我尝试了所有的解决scheme,并没有在我的C#.net 4.0项目工作。 希望能帮助这里的人解决scheme,为我工作:
作为主要的类variables:
private static string appGuid = "WRITE AN UNIQUE GUID HERE"; private static Mutex mutex;
当你需要检查应用程序是否已经在运行时:
bool mutexCreated; mutex = new Mutex(true, "Global\\" + appGuid, out mutexCreated); if (mutexCreated) mutex.ReleaseMutex(); if (!mutexCreated) { //App is already running, close this! Environment.Exit(0); //i used this because its a console app }
我只需要在一些条件下closures其他的一些事情,这对我的目的很有效
使用VB.NET! 不完全是 ;)
使用Microsoft.VisualBasic.ApplicationServices;
VB.Net的WindowsFormsApplicationBase为您提供了一个“SingleInstace”属性,它确定了其他实例,并只让一个实例运行。
当您为可执行文件创build项目时,使用Visual Studio 2005或2008,在“应用程序”面板的属性窗口中,有一个名为“Make single instance application”的checkbox,您可以激活该checkbox以将应用程序转换为单个实例应用程序。
这里是我正在谈论的窗口的捕获: 这是一个Visual Studio 2008 Windows应用程序项目。
本文简单地解释了如何创build一个Windows应用程序来控制其实例的数量或者只运行一个实例。 这是一个非常典型的商业应用需求。 已经有很多其他可能的解决scheme来控制这一点。
http://www.openwinforms.com/single_instance_application.html
1 – 在program.cs – >中创build一个引用
using System.Diagnostics;
2 – 放入void Main()
作为第一行代码 – >
if (Process.GetProcessesByName(Process.GetCurrentProcess().ProcessName).Length >1) return;
而已。
这是VB.Net的代码
Private Shared Sub Main() Using mutex As New Mutex(False, appGuid) If Not mutex.WaitOne(0, False) Then MessageBox.Show("Instance already running", "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error) Return End If Application.Run(New Form1()) End Using End Sub
这是C#的代码
private static void Main() { using (Mutex mutex = new Mutex(false, appGuid)) { if (!mutex.WaitOne(0, false)) { MessageBox.Show("Instance already running", "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } Application.Run(new Form1()); } }
在尝试了多个解决scheme后,我的问题 我结束了在这里使用WPF的例子: http : //www.c-sharpcorner.com/UploadFile/f9f215/how-to-restrict-the-application-to-just-one-instance/
public partial class App : Application { private static Mutex _mutex = null; protected override void OnStartup(StartupEventArgs e) { const string appName = "MyAppName"; bool createdNew; _mutex = new Mutex(true, appName, out createdNew); if (!createdNew) { //app is already running! Exiting the application Application.Current.Shutdown(); } } }
在App.xaml中:
x:Class="*YourNameSpace*.App" StartupUri="MainWindow.xaml" Startup="App_Startup"
简单地使用StreamWriter
,这个怎么样?
System.IO.File.StreamWriter OpenFlag = null; //globally
和
try { OpenFlag = new StreamWriter(Path.GetTempPath() + "OpenedIfRunning"); } catch (System.IO.IOException) //file in use { Environment.Exit(0); }
你必须使用System.Diagnostics.Process。
退房: http : //www.devx.com/tips/Tip/20044
通常使用一个已命名的Mutex(使用新的Mutex(“您的应用程序名称”,true)并检查返回值),但也有一些Microsoft.VisualBasic.dll支持类可以为您做 。
(注意:这是一个有趣的解决scheme!它的工作原理,但使用不良的GDI +devise来实现这一点。)
将图像与您的应用程序并启动时加载它。 坚持下去,直到应用程序退出。 用户将无法启动第二个实例。 (当然互斥解决scheme更清洁)
private static Bitmap randomName = new Bitmap("my_image.jpg");
这在纯C#中为我工作。 try / catch是在循环中列表中的某个进程可能会退出的时候。
using System.Diagnostics; .... [STAThread] static void Main() { ... int procCount = 0; foreach (Process pp in Process.GetProcesses()) { try { if (String.Compare(pp.MainModule.FileName, Application.ExecutablePath, true) == 0) { procCount++; if(procCount > 1) { Application.Exit(); return; } } } catch { } } Application.Run(new Form1()); }
[STAThread] static void Main() // args are OK here, of course { bool ok; m = new System.Threading.Mutex(true, "YourNameHere", out ok); if (! ok) { MessageBox.Show("Another instance is already running."); return; } Application.Run(new Form1()); // or whatever was there GC.KeepAlive(m); // important! }
来自: 确保.NET应用程序的单个实例
和: 单实例应用程序互斥
与@Smink和@Imjusthedering相同的答案有一个转折:
Jon Skeet关于C#的常见问题 ,了解GC.KeepAlive的重要性
确保在将应用程序限制为单个实例时考虑安全性:
完整文章: https : //blogs.msdn.microsoft.com/oldnewthing/20060620-13/?p = 30813
我们正在使用一个具有固定名称的命名互斥体,以检测程序的另一个副本是否正在运行。 但这也意味着攻击者可以先创build互斥锁,从而阻止我们的程序运行! 我怎样才能防止这种types的拒绝服务攻击?
…
如果攻击者运行在与你的程序运行在同一个安全上下文中,那么你就无能为力了。 无论您提出什么“秘密握手”来确定您的程序的另一个副本是否正在运行,攻击者可以模仿它。 由于它运行在正确的安全环境中,因此它可以执行“真实”程序可以执行的任何操作。
…
很明显,您无法保护自己免受攻击者的攻击,但是您仍然可以保护自己免受无特权攻击者的其他安全特权的攻击。
尝试在互斥体上设置DACL,这里是.NET方法: https : //msdn.microsoft.com/en-us/library/system.security.accesscontrol.mutexsecurity(v=vs.110).aspx