Answers:
使用Mutex。上面使用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";
string appGuid = ((GuidAttribute)Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(GuidAttribute), true)[0]).Value;这将获取执行程序集的guid
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();
}
}
}
到目前为止,似乎已经提出了3种基本技术。
有什么需要注意的事项吗?
1-在program.cs中创建引用->
using System.Diagnostics;
2- void Main()输入第一行代码->
if (Process.GetProcessesByName(Process.GetCurrentProcess().ProcessName).Length >1)
return;
而已。
Mutex?有收获吗?
在为可执行文件创建项目时使用Visual Studio 2005或2008,在“应用程序”面板内的属性窗口上,有一个名为“制作单实例应用程序”的复选框,您可以激活该复选框以在单实例应用程序上转换应用程序。
这是我正在谈论的窗口的捕获:
这是一个Visual Studio 2008 Windows应用程序项目。
我在这里尝试了所有解决方案,但在我的C#.net 4.0项目中没有任何效果。希望在这里为某人提供对我有用的解决方案:
作为主类变量:
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
}
我只需要在某些条件下关闭其他位置,这对于我的目的来说效果很好
尝试多种解决方案后,我的问题。我最终在这里使用了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"
本文仅说明如何创建一个Windows应用程序,该应用程序可以控制其实例数量或仅运行单个实例。这是业务应用程序非常典型的需求。已经有很多其他可能的解决方案来控制此问题。
http://www.openwinforms.com/single_instance_application.html
这是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());
}
}
您必须使用System.Diagnostics.Process。
(注意:这是一个有趣的解决方案!它可以工作,但是使用了错误的GDI +设计来实现这一点。)
将图像与您的应用程序一起放入并在启动时加载。按住它,直到应用程序退出。用户将无法启动第二个实例。(当然,互斥锁解决方案要干净得多)
private static Bitmap randomName = new Bitmap("my_image.jpg");
Main()与WPF应该如何工作相反的方法。
[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!
}
与@Smink和@Imjustpondering相同的答案略有不同:
只需使用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);
}
这在纯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());
}
将应用程序限制为单个实例时,请务必考虑安全性:
全文:https : //blogs.msdn.microsoft.com/oldnewthing/20060620-13/?p=30813
我们正在使用具有固定名称的已命名互斥锁,以检测程序的另一个副本是否正在运行。但这也意味着攻击者可以首先创建互斥体,从而完全阻止我们的程序运行!如何防止这种拒绝服务攻击?
...
如果攻击者与程序正在(或将要在其中)运行在相同的安全上下文中,那么您将无能为力。无论您想出什么“秘密握手”来确定程序的另一个副本是否正在运行,攻击者都可以模仿它。由于它在正确的安全上下文中运行,因此它可以执行“真实”程序可以执行的任何操作。
...
显然,您无法保护自己免受以相同安全特权运行的攻击者的侵害,但仍可以保护自己免受以其他安全特权运行的非特权攻击者的攻击。
尝试在互斥锁上设置DACL,这是.NET方式:https : //msdn.microsoft.com/zh-cn/library/system.security.accesscontrol.mutexsecurity(v=vs.110).aspx
这些答案对我都不起作用,因为我需要使用monodevelop在Linux下工作。这对我很有用:
调用此方法并为其传递唯一ID
public static void PreventMultipleInstance(string applicationId)
{
// Under Windows this is:
// C:\Users\SomeUser\AppData\Local\Temp\
// Linux this is:
// /tmp/
var temporaryDirectory = Path.GetTempPath();
// Application ID (Make sure this guid is different accross your different applications!
var applicationGuid = applicationId + ".process-lock";
// file that will serve as our lock
var fileFulePath = Path.Combine(temporaryDirectory, applicationGuid);
try
{
// Prevents other processes from reading from or writing to this file
var _InstanceLock = new FileStream(fileFulePath, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None);
_InstanceLock.Lock(0, 0);
MonoApp.Logger.LogToDisk(LogType.Notification, "04ZH-EQP0", "Aquired Lock", fileFulePath);
// todo investigate why we need a reference to file stream. Without this GC releases the lock!
System.Timers.Timer t = new System.Timers.Timer()
{
Interval = 500000,
Enabled = true,
};
t.Elapsed += (a, b) =>
{
try
{
_InstanceLock.Lock(0, 0);
}
catch
{
MonoApp.Logger.Log(LogType.Error, "AOI7-QMCT", "Unable to lock file");
}
};
t.Start();
}
catch
{
// Terminate application because another instance with this ID is running
Environment.Exit(102534);
}
}