Как проверить, запущено ли приложение С# Windows?
Я знаю, что я могу проверить имя процесса, но имя может быть изменено, если exe изменится.
Есть ли способ иметь хэш-ключ или что-то уникальное для моего приложения?
Как проверить, запущено ли приложение С# Windows?
Я знаю, что я могу проверить имя процесса, но имя может быть изменено, если exe изменится.
Есть ли способ иметь хэш-ключ или что-то уникальное для моего приложения?
public partial class App : System.Windows.Application
{
public bool IsProcessOpen(string name)
{
foreach (Process clsProcess in Process.GetProcesses())
{
if (clsProcess.ProcessName.Contains(name))
{
return true;
}
}
return false;
}
protected override void OnStartup(StartupEventArgs e)
{
// Get Reference to the current Process
Process thisProc = Process.GetCurrentProcess();
if (IsProcessOpen("name of application.exe") == false)
{
//System.Windows.MessageBox.Show("Application not open!");
//System.Windows.Application.Current.Shutdown();
}
else
{
// Check how many total processes have the same name as the current one
if (Process.GetProcessesByName(thisProc.ProcessName).Length > 1)
{
// If ther is more than one, than it is already running.
System.Windows.MessageBox.Show("Application is already running.");
System.Windows.Application.Current.Shutdown();
return;
}
base.OnStartup(e);
}
}
Рекомендуемый способ - использовать Mutex. Вы можете проверить образец здесь: http://www.codeproject.com/KB/cs/singleinstance.aspx
В частности, код:
///
/// check if given exe alread running or not
///
/// returns true if already running
private static bool IsAlreadyRunning()
{
string strLoc = Assembly.GetExecutingAssembly().Location;
FileSystemInfo fileInfo = new FileInfo(strLoc);
string sExeName = fileInfo.Name;
bool bCreatedNew;
Mutex mutex = new Mutex(true, "Global\\"+sExeName, out bCreatedNew);
if (bCreatedNew)
mutex.ReleaseMutex();
return !bCreatedNew;
}
В моем приложении WPF я определил глобальный идентификатор приложения и использую семафор для его обработки.
public partial class App : Application
{
private const string AppId = "c1d3cdb1-51ad-4c3a-bdb2-686f7dd10155";
//Passing name associates this sempahore system wide with this name
private readonly Semaphore instancesAllowed = new Semaphore(1, 1, AppId);
private bool WasRunning { set; get; }
private void OnExit(object sender, ExitEventArgs e)
{
//Decrement the count if app was running
if (this.WasRunning)
{
this.instancesAllowed.Release();
}
}
private void OnStartup(object sender, StartupEventArgs e)
{
//See if application is already running on the system
if (this.instancesAllowed.WaitOne(1000))
{
new MainWindow().Show();
this.WasRunning = true;
return;
}
//Display
MessageBox.Show("An instance is already running");
//Exit out otherwise
this.Shutdown();
}
}
вам нужен способ сказать, что "я бегу" из приложения,
1) откройте службу ping для WCF 2) записывать в реестр/файл при запуске и удалять при завершении работы 3) создать Mutex
... Я предпочитаю часть WCF, потому что вы не можете правильно очистить файл/реестр, и у Mutex есть свои проблемы
Мутекс и Семафор не работали в моем случае. Ответ , предложенный abramlimpin, сработал для меня после того, как я внес небольшие изменения.
Вот так я наконец заработал. Сначала я создал несколько вспомогательных функций:
public static class Ext
{
private static string AssemblyFileName(this Assembly myAssembly)
{
string strLoc = myAssembly.Location;
FileSystemInfo fileInfo = new FileInfo(strLoc);
string sExeName = fileInfo.Name;
return sExeName;
}
private static int HowManyTimesIsProcessRunning(string name)
{
int count = 0;
name = name.ToLowerInvariant().Trim().Replace(".exe", "");
foreach (Process clsProcess in Process.GetProcesses())
{
var processName = clsProcess.ProcessName.ToLowerInvariant().Trim();
// System.Diagnostics.Debug.WriteLine(processName);
if (processName.Contains(name))
{
count++;
};
};
return count;
}
public static int HowManyTimesIsAssemblyRunning(this Assembly myAssembly)
{
var fileName = AssemblyFileName(myAssembly);
return HowManyTimesIsProcessRunning(fileName);
}
}
Затем я добавил в метод main следующее:
[STAThread]
static void Main()
{
const string appName = "Name of your app";
// Check number of instances running:
// If more than 1 instance, cancel this one.
// Additionally, if it is the 2nd invocation, show a message and exit.
var numberOfAppInstances = Assembly.GetExecutingAssembly().HowManyTimesIsAssemblyRunning();
if (numberOfAppInstances == 2)
{
MessageBox.Show("The application is already running!
+"\nClick OK to close this dialog, then switch to the application by using WIN + TAB keys.",
appName, MessageBoxButtons.OK, MessageBoxIcon.Warning);
};
if (numberOfAppInstances >= 2)
{
return;
};
}
Если вы вызываете приложение в 3-й, 4-й... раз, оно больше не отображает предупреждение и просто сразу же закрывается.
Checkout: Что такое хороший шаблон для использования Глобального Mutex в С#?
// unique id for global mutex - Global prefix means it is global to the machine
const string mutex_id = "Global\\{B1E7934A-F688-417f-8FCB-65C3985E9E27}";
static void Main(string[] args)
{
using (var mutex = new Mutex(false, mutex_id))
{
// edited by Jeremy Wiebe to add example of setting up security for multi-user usage
// edited by 'Marc' to work also on localized systems (don't use just "Everyone")
var allowEveryoneRule = new MutexAccessRule(new SecurityIdentifier(WellKnownSidType.WorldSid, null), MutexRights.FullControl, AccessControlType.Allow);
var securitySettings = new MutexSecurity();
securitySettings.AddAccessRule(allowEveryoneRule);
mutex.SetAccessControl(securitySettings);
//edited by acidzombie24
var hasHandle = false;
try
{
try
{
// note, you may want to time out here instead of waiting forever
//edited by acidzombie24
//mutex.WaitOne(Timeout.Infinite, false);
hasHandle = mutex.WaitOne(5000, false);
if (hasHandle == false) return;//another instance exist
}
catch (AbandonedMutexException)
{
// Log the fact the mutex was abandoned in another process, it will still get aquired
}
// Perform your work here.
}
finally
{
//edit by acidzombie24, added if statemnet
if (hasHandle)
mutex.ReleaseMutex();
}
}
}
Я действительно упрощен, как я полагаю, для каждого исполняемого exe файла вы могли бы создать/открыть файл на диске в известном месте (c:\temp) со специальным именем "yourapp.lock", а затем просто подсчитайте, сколько из них есть.
Более сложным способом было бы открыть некоторые межпроцессные коммуникации или сокеты, поэтому в списке процессов вы могли бы опросить каждый процесс, чтобы узнать, было ли это ваше приложение.
Введите руководство в свои данные сборки. Добавьте это руководство в реестр. Введите ключ reg, в котором приложение прочитает его собственное имя и добавит его в качестве значения.
Другой наблюдатель задач читает ключ реестра и знает имя приложения.
Вы можете просто использовать переменные и один файл для проверки запуска вашей программы. при открытии файл содержит значение, а при закрытии программы меняет это значение на другое.