2009-04-22 35 views
8

Possiedo un'applicazione .NET che consente solo di eseguire un singolo processo alla volta, tuttavia tale app viene utilizzata di volta in volta sui box Citrix e, in quanto tale, può essere eseguita da più utenti sullo stesso computer.Come posso verificare un processo in esecuzione per sessione utente?

Voglio verificare che l'applicazione sia in esecuzione una sola volta per sessione utente, perché ora se l'utente A sta eseguendo l'app, l'utente B riceve il messaggio "App già in uso" e non dovrebbe.

Questo è quello che ho adesso che i controlli per il processo in esecuzione:

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 
      } 

risposta

6

EDIT: Migliorata la risposta in base alla this cw question ...

È possibile utilizzare un mutex per controllare la wether applicazione funziona già:

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(); 
    } 
} 

Importante è la AppGuid - si potrebbe fare dipende dall'utente.

forse ti piace leggere questo articolo: the misunderstood mutex

+0

funziona per me. Grazie! – Russ

3

Come tanascius già dicono, è possibile utilizzare il mutex.

Su un server che esegue Servizi terminal, un mutex di sistema denominato può avere due livelli di visibilità. Se il suo nome inizia con il prefisso "Global \", il mutex è visibile in tutte le sessioni del server terminal. Se il suo nome inizia con il prefisso "Local \", il mutex è visibile solo nella sessione del server terminal in cui è stato creato.

Fonte: msdn, Mutex Class

0

Se Form1 lancia le discussioni non di fondo, e che Form1 esce, hai un problema: il mutex viene rilasciato, ma il processo è ancora lì. Qualcosa sulla falsariga di sotto è migliore IMHO:

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 
      ); 
     } 
    } 
} 

il mutex non sarà rilasciato fino a quando il dominio di applicazione principale è ancora alto. E questo sarà in giro finché l'applicazione è in esecuzione.

0

Solo affermando l'ovvio - sebbene sia in genere considerato una soluzione migliore, è comunque possibile risolvere il problema di singola istanza per sessione senza Mutex - basta testare anche lo 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; 
    } 

Source (no Linq)

Problemi correlati