Как я могу проверить запущенный процесс для каждой пользовательской сессии?
У меня есть приложение.NET, которое я позволяю запускать только одному процессу за раз, однако это приложение время от времени используется на коробках Citrix и, следовательно, может запускаться несколькими пользователями на одном компьютере.
Я хочу проверить и убедиться, что приложение выполняется только один раз за пользовательский сеанс, потому что сейчас, если пользователь A запускает приложение, пользователь B получает сообщение "Приложение уже используется", и не должен.
Это то, что я сейчас проверяю для запуска процесса:
Process[] p = Process.GetProcessesByName(Process.GetCurrentProcess().ProcessName);
if (p.Length > 1)
{
#if !DEBUG
allowedToOpen &= false;
errorMessage +=
string.Format("{0} is already running.{1}", Constants.AssemblyTitle, Environment.NewLine);
#endif
}
4 ответа
РЕДАКТИРОВАТЬ: Улучшен ответ в соответствии с этим непрерывным вопросом...
Вы можете использовать мьютекс для проверки, запущено ли уже приложение:
using( var mutex = new Mutex( false, AppGuid ) )
{
try
{
try
{
if( !mutex.WaitOne( 0, false ) )
{
MessageBox.Show( "Another instance is already running." );
return;
}
}
catch( AbandonedMutexException )
{
// Log the fact the mutex was abandoned in another process,
// it will still get aquired
}
Application.Run(new Form1());
}
finally
{
mutex.ReleaseMutex();
}
}
Важным является AppGuid
- вы можете сделать это зависит от пользователя.
Может быть, вам нравится читать эту статью: неправильно понятый мьютекс
Как уже сказал танаскиус, вы можете использовать Mutex.
На сервере, на котором запущены службы терминалов, именованный системный мьютекс может иметь два уровня видимости. Если его имя начинается с префикса "Global\", мьютекс виден во всех сеансах терминального сервера. Если его имя начинается с префикса "Local\", мьютекс виден только в сеансе сервера терминалов, где он был создан.
Источник: MSDN, Mutex Class
Просто констатирую очевидное - хотя Mutex
Обычно считается лучшим решением, вы можете решить проблему с одним экземпляром на сеанс без Mutex
- просто проверить SessionId
также.
private static bool ApplicationIsAlreadyRunning()
{
var currentProcess = Process.GetCurrentProcess();
var processes = Process.GetProcessesByName(currentProcess.ProcessName);
// test if there's another process running in current session.
var intTotalRunningInCurrentSession = processes.Count(prc => prc.SessionId == currentProcess.SessionId);
return intTotalRunningInCurrentSession > 1;
}
Если Form1 запускает не фоновые потоки, и эта Form1 завершается, у вас есть проблема: мьютекс освобождается, но процесс все еще там. Что-то в этом роде лучше ИМХО:
static class Program {
private static Mutex mutex;
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main() {
bool createdNew = true;
mutex = new Mutex(true, @"Global\Test", out createdNew);
if (createdNew) {
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
else {
MessageBox.Show(
"Application is already running",
"Error",
MessageBoxButtons.OK,
MessageBoxIcon.Error
);
}
}
}
Мьютекс не будет освобожден, пока основной домен приложения все еще работает. И это будет происходить до тех пор, пока приложение работает.