![](/img/trans.png)
[英]Passing command line arguments to already running instance of my application
[英]Detecting if another instance of the application is already running
如果已經有實例運行,我的應用程序在加載時需要表現得略有不同。
我理解如何使用互斥鎖來防止其他實例加載,但這並不能解決我的問題。
例如:
有任何想法嗎? 值得慶幸的是,它不需要處理多個用戶帳戶或類似的東西。
(C#,桌面應用程序)
編輯:為了澄清,應用程序不需要限制為單個實例,只需執行一個稍微不同的啟動操作,如果還有另一個實例已經運行。 多個實例都很好(並且是預期的)。
這可能會做你想要的。 它具有很好的附加功能,可以使已經運行的實例前進。
編輯:更新代碼以自動確定應用程序標題。
using System;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
static void Main()
{
if (!EnsureSingleInstance())
{
return;
}
//...
}
static bool EnsureSingleInstance()
{
Process currentProcess = Process.GetCurrentProcess();
var runningProcess = (from process in Process.GetProcesses()
where
process.Id != currentProcess.Id &&
process.ProcessName.Equals(
currentProcess.ProcessName,
StringComparison.Ordinal)
select process).FirstOrDefault();
if (runningProcess != null)
{
ShowWindow(runningProcess.MainWindowHandle, SW_SHOWMAXIMIZED);
SetForegroundWindow(runningProcess.MainWindowHandle);
return false;
}
return true;
}
[DllImport("user32.dll", EntryPoint = "SetForegroundWindow")]
private static extern bool SetForegroundWindow(IntPtr hWnd);
[DllImport("user32.dll")]
private static extern Boolean ShowWindow(IntPtr hWnd, Int32 nCmdShow);
private const int SW_SHOWMAXIMIZED = 3;
嘗試使用信號量而不是互斥量
一個好的方法是使用Sandor解決方案,但使用WMI獲取進程列表,如下所述: C#:如何獲得運行進程的完整路徑? (傑夫的解決方案)。 這樣,您還可以檢查其他正在運行的實例是否與路徑和遠程終端會話ID匹配:
static bool EnsureSingleInstance()
{
Process currentProcess = Process.GetCurrentProcess();
var wmiQueryString = "SELECT ProcessId, ExecutablePath, CommandLine FROM Win32_Process";
using (var searcher = new ManagementObjectSearcher(wmiQueryString))
using (var results = searcher.Get())
{
var query = from p in Process.GetProcesses()
join mo in results.Cast<ManagementObject>()
on p.Id equals (int)(uint)mo["ProcessId"]
select new
{
Process = p,
Path = (string)mo["ExecutablePath"],
CommandLine = (string)mo["CommandLine"],
};
var runningProcess = (from process in query
where
process.Process.Id != currentProcess.Id &&
process.Process.ProcessName.Equals(
currentProcess.ProcessName,
StringComparison.Ordinal) &&
process.Path == currentProcess.MainModule.FileName &&
process.Process.SessionId == currentProcess.SessionId
select process).FirstOrDefault();
return runningProcess == null;
}
}
您可以在使用CreateMutex()
創建互斥鎖后檢查GetLastError()
CreateMutex()
嗎? 如果它返回ERROR_ALREADY_EXISTS
,那么應用程序的另一個正在運行的實例。
根據http://msdn.microsoft.com/en-us/library/ms682411%28VS.85%29.aspx ,
如果互斥鎖是一個已命名的互斥鎖,並且該對象在此函數調用之前存在,則返回值是現有對象的句柄,GetLastError返回ERROR_ALREADY_EXISTS,bInitialOwner被忽略,並且調用線程未被授予所有權。 但是,如果調用者具有有限的訪問權限,則該函數將失敗並顯示ERROR_ACCESS_DENIED,並且調用者應使用OpenMutex函數。
編輯:剛認識到這是一個C#/ .Net問題,抱歉。
在.Net中,使用返回createdNew標志的Mutex構造函數, http : //msdn.microsoft.com/en-us/library/bwe34f1k%28VS.80%29.aspx :
public Mutex (
bool initiallyOwned,
string name,
out bool createdNew
)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.