【发布时间】:2008-10-08 18:15:35
【问题描述】:
可能重复:
What is the correct way to create a single instance application?
如何强制 C# .net 应用在 Windows 中只运行一个实例?
【问题讨论】:
可能重复:
What is the correct way to create a single instance application?
如何强制 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;
}
}
}
}
}
【讨论】:
ShowWindow( process.MainWindowHandle, SW_RESTORE ) 来恢复它。 stackoverflow.com/questions/4566632/… 提供详细信息。 SW_RESTORE 为 9(来自msdn.microsoft.com/en-gb/library/windows/desktop/…)。
要在 .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());
}
【讨论】:
Process.GetProcessesByName 将抛出异常。
这是我在我的应用程序中使用的:
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();
}
【讨论】:
单实例应用程序的另一种方法是检查它们的哈希和。 在弄乱了互斥锁(没有按我想要的那样工作)之后,我得到了它的工作方式:
[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 哈希相同,则不会打开两次。
有人对此有什么建议吗?我知道它已被回答,但也许有人正在寻找互斥锁替代品。
【讨论】: