C # /. NET: Rileva se il programma è in esecuzione come un servizio o un'applicazione console [duplicato]

StackOverflow https://stackoverflow.com/questions/207896

  •  03-07-2019
  •  | 
  •  

Domanda

    

Questa domanda ha già una risposta qui:

    
            
  •              Sono in esecuzione come servizio                                      12 risposte                          
  •     
    

Ho un programma C # /. NET che può essere eseguito sia come applicazione console che come servizio. Attualmente gli offro un'opzione da riga di comando per iniziare come applicazione console, ma vorrei evitarlo.

È possibile rilevare a livello di codice se il mio programma è stato avviato come servizio?

Se fosse Win32 puro, potrei provare ad avviarlo come servizio con StartServiceCtrlDispatcher e tornare alla console se restituisse ERROR_FAILED_SERVICE_CONTROLLER_CONNECT, ma System.ServiceProcess.ServiceBase.Run () fa apparire un errore in caso di errore e poi ritorna senza errori segnalazione di un errore al programma.

Qualche idea?

È stato utile?

Soluzione

Rasmus, questa è la domanda precedente .

Dalle risposte sembra che il modo più popolare sia usare una semplice opzione da riga di comando o provare ad accedere all'oggetto Console in un blocco try catch (in un Servizio la Console non è collegata al processo e tenta di accedervi lancia un'eccezione).

In caso di problemi durante il test / debug del servizio, spostare il codice in un assembly DLL separato e creare un cablaggio di prova separato (winforms / console ecc.).

(Ho appena notato che Jonathan ha aggiunto la sua soluzione alla fine della domanda.)

Altri suggerimenti

Potrebbe voler provare la proprietà SessionId dell'oggetto Process. Nella mia esperienza, SessionId è impostato su 0 se il processo esegue un servizio.

[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr GetStdHandle(int nStdHandle);
const int STD_OUTPUT_HANDLE = -11;

IntPtr iStdOut = GetStdHandle(STD_OUTPUT_HANDLE);

if (iStdOut == IntPtr.Zero)

{    
    app.RunAsWindowsService = true;

}

// Run as Service
if (runAsWindowsService)                                
{
     // .....
     ServiceBase.Run(myService);
}
else 
{
    // Run as Console
    // Register Ctrl+C Handler...
}

Utilizzando la struttura ParentProcessUtilities da questa risposta sulla ricerca di un processo padre, puoi farlo:

static bool RunningAsService() {
    var p = ParentProcessUtilities.GetParentProcess();
    return ( p != null && p.ProcessName == "services" );
}

Nota che il nome del processo per il processo padre non include l'estensione "quot. .exe".

Non l'ho provato, ma è possibile che Process.GetCurrentProcess aiuterà: in modalità console il nome del processo sarebbe lo stesso dell'eseguibile, mentre mi aspetto (e ancora, per favore, controlla!) Che quando si esegue come servizio sarebbe diverso.

Non so se funzionerà, ma potresti provare a usare PInvoke con questo codice e verifica se il genitore è " services.exe " ;.

Ho finito col rilevare se ero in un'applicazione console controllando Console.IsErrorRedirected . Ha restituito " false " per le app della console e " true " per le app non console che ho testato. Avrei potuto anche usare IsOutputRedirected .

Immagino ci siano circostanze in cui queste non saranno accurate, ma questo ha funzionato bene per me.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top