Come posso eseguire un programma EXE da un servizio di Windows utilizzando C #?

Come posso eseguire un programma EXE da un servizio di Windows utilizzando C #?

Questo è il mio codice:

 System.Diagnostics.Process.Start(@"E:\PROJECT XL\INI SQLLOADER\ConsoleApplication2\ConsoleApplication2\ConsoleApplication2\bin\Debug\ConsoleApplication2.exe"); 

Quando eseguo questo servizio, l’applicazione non si avvia.
Cosa c’è che non va nel mio codice?

Questo non funzionerà mai , almeno non sotto Windows Vista o successivi. Il problema chiave è che si sta tentando di eseguirlo da un servizio di Windows, anziché da un’applicazione Windows standard. Il codice che hai mostrato funzionerà perfettamente in un’applicazione Windows Form, WPF o Console, ma non funzionerà affatto in un servizio di Windows.

I servizi Windows non possono avviare applicazioni aggiuntive perché non sono in esecuzione nel contesto di un particolare utente. A differenza delle normali applicazioni Windows, i servizi vengono ora eseguiti in una sessione isolata e non è ansible interagire con un utente o il desktop. Ciò non lascia spazio all’esecuzione dell’applicazione.

Ulteriori informazioni sono disponibili nelle risposte a queste domande correlate:

  • Come può un servizio Windows avviare un processo quando viene generato un evento timer?
  • quale processo in Windows è specifico per l’utente?
  • servizio Windows (consente al servizio di interagire con il desktop)

La migliore soluzione al tuo problema, come probabilmente avrai capito, è creare un’applicazione Windows standard invece di un servizio. Questi sono progettati per essere eseguiti da un particolare utente e sono associati al desktop dell’utente. In questo modo, puoi eseguire applicazioni aggiuntive ogni volta che vuoi, usando il codice che hai già mostrato.

Un’altra ansible soluzione, supponendo che l’applicazione Console non richieda un’interfaccia o un output di alcun tipo, è quella di istruire il processo a non creare una finestra. Ciò impedirà a Windows di bloccare la creazione del processo, poiché non richiederà più la creazione di una finestra della console. È ansible trovare il codice pertinente in questa risposta a una domanda correlata.

Ho provato questo articolo Code Project , sta funzionando bene per me. Ho usato anche il codice. l’articolo è eccellente nella spiegazione con lo screenshot.

Sto aggiungendo la spiegazione necessaria a questo scenario

Hai appena avviato il tuo computer e stai per accedere. Quando si effettua l’accesso, il sistema assegna all’utente un ID sessione univoco. In Windows Vista, al primo utente che accede al computer viene assegnato un ID sessione di 1 dal sistema operativo. Al successivo Utente per l’accesso verrà assegnato un ID sessione di 2. E così via e così via. È ansible visualizzare l’ID sessione assegnato a ciascun utente connesso dalla scheda Utenti in Task Manager. inserisci la descrizione dell'immagine qui

Ma il tuo servizio Windows è portato sotto l’ID di sessione di 0. Questa sessione è isolata dalle altre sessioni. Ciò in definitiva impedisce al servizio di Windows di richiamare l’applicazione in esecuzione nella sessione utente come 1 o 2.

Per richiamare l’applicazione dal servizio Windows è necessario copiare il controllo da winlogon.exe che funge da utente registrato presente come mostrato nell’immagine sottostante. inserisci la descrizione dell'immagine qui

Codici importanti

 // obtain the process id of the winlogon process that // is running within the currently active session Process[] processes = Process.GetProcessesByName("winlogon"); foreach (Process p in processes) { if ((uint)p.SessionId == dwSessionId) { winlogonPid = (uint)p.Id; } } // obtain a handle to the winlogon process hProcess = OpenProcess(MAXIMUM_ALLOWED, false, winlogonPid); // obtain a handle to the access token of the winlogon process if (!OpenProcessToken(hProcess, TOKEN_DUPLICATE, ref hPToken)) { CloseHandle(hProcess); return false; } // Security attibute structure used in DuplicateTokenEx and CreateProcessAsUser // I would prefer to not have to use a security attribute variable and to just // simply pass null and inherit (by default) the security attributes // of the existing token. However, in C# structures are value types and therefore // cannot be assigned the null value. SECURITY_ATTRIBUTES sa = new SECURITY_ATTRIBUTES(); sa.Length = Marshal.SizeOf(sa); // copy the access token of the winlogon process; // the newly created token will be a primary token if (!DuplicateTokenEx(hPToken, MAXIMUM_ALLOWED, ref sa, (int)SECURITY_IMPERSONATION_LEVEL.SecurityIdentification, (int)TOKEN_TYPE.TokenPrimary, ref hUserTokenDup)) { CloseHandle(hProcess); CloseHandle(hPToken); return false; } STARTUPINFO si = new STARTUPINFO(); si.cb = (int)Marshal.SizeOf(si); // interactive window station parameter; basically this indicates // that the process created can display a GUI on the desktop si.lpDesktop = @"winsta0\default"; // flags that specify the priority and creation method of the process int dwCreationFlags = NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE; // create a new process in the current User's logon session bool result = CreateProcessAsUser(hUserTokenDup, // client's access token null, // file to execute applicationName, // command line ref sa, // pointer to process SECURITY_ATTRIBUTES ref sa, // pointer to thread SECURITY_ATTRIBUTES false, // handles are not inheritable dwCreationFlags, // creation flags IntPtr.Zero, // pointer to new environment block null, // name of current directory ref si, // pointer to STARTUPINFO structure out procInfo // receives information about new process ); 

In primo luogo, creeremo un servizio di Windows che viene eseguito con l’account di sistema. Questo servizio sarà responsabile della generazione di un processo interattivo all’interno della sessione utente attualmente triggers. Questo processo appena creato visualizzerà un’interfaccia utente e funzionerà con diritti di amministratore completi. Quando il primo utente accede al computer, questo servizio verrà avviato e verrà eseguito in Session0; tuttavia, il processo che genera questo servizio verrà eseguito sul desktop dell’utente attualmente connesso. Faremo riferimento a questo servizio come LoaderService.

Successivamente, il processo winlogon.exe è responsabile della gestione delle procedure di accesso e disconnessione dell’utente. Sappiamo che ogni utente che accede al computer avrà un ID sessione univoco e un processo winlogon.exe corrispondente associato alla sua sessione. Ora, abbiamo menzionato sopra, LoaderService viene eseguito sotto l’account di sistema. Abbiamo anche confermato che ogni processo winlogon.exe sul computer viene eseguito con l’account di sistema. Poiché l’account di sistema è il proprietario dei processi LoaderService e winlogon.exe, il nostro LoaderService può copiare il token di accesso (e l’ID sessione) del processo winlogon.exe e quindi chiamare la funzione API Win32 CreateProcessAsUser per avviare un processo nel Sessione attualmente triggers dell’utente connesso. Poiché l’ID sessione che si trova all’interno del token di accesso del processo winlogon.exe copiato è maggiore di 0, è ansible avviare un processo interattivo utilizzando quel token.

Prova questo. Subverting Vista UAC in entrambe le architetture a 32 e 64 bit

È ansible eseguire un file .exe da un servizio di Windows molto bene in Windows XP. L’ho fatto io stesso in passato.

Devi assicurarti di aver selezionato l’opzione “Permetti di interagire con il desktop” nelle proprietà del servizio di Windows. Se ciò non è fatto, non verrà eseguito.

Ho bisogno di controllare in Windows 7 o Vista in quanto queste versioni richiedono privilegi di sicurezza aggiuntivi in ​​modo che possa generare un errore, ma sono abbastanza sicuro che può essere raggiunto direttamente o indirettamente. Per XP sono certo come l’avevo fatto io stesso.

Penso che stai copiando il file .exe in una posizione diversa. Questo potrebbe essere il problema, credo. Quando copi l’exe, non stai copiando le sue dipendenze.

Quindi, ciò che puoi fare è mettere tutte le DLL dipendenti in GAC in modo che qualsiasi .net exe possa accedervi

Altrimenti, non copiare l’exe in una nuova posizione. Basta creare una variabile d’ambiente e chiamare l’exe nel tuo c #. Poiché il percorso è definito in variabili di ambiente, è ansible accedere a exe dal programma c #.

Aggiornare:

in precedenza ho avuto un qualche tipo di problema nel mio progetto c # .net 3.5 in cui stavo cercando di eseguire un file .exe dal codice c # .net e che exe non era altro che l’altro progetto exe (dove ho aggiunto alcune dll di supporto per il mio funzionalità) e quei metodi DLL che stavo usando nella mia applicazione exe. Alla fine ho risolto questo problema creando questa applicazione come progetto separato per la stessa soluzione e ho aggiunto l’output del progetto al mio progetto di implementazione. Secondo questo scenario ho risposto, se non è quello che vuole, mi dispiace molto.

è ansible utilizzare da Windows Task Scheduler per questo scopo, ci sono molte librerie come TaskScheduler che ti aiutano.

ad esempio, consideriamo di voler pianificare un’attività che verrà eseguita una volta cinque secondi dopo:

 using (var ts = new TaskService()) { var t = ts.Execute("notepad.exe") .Once() .Starting(DateTime.Now.AddSeconds(5)) .AsTask("myTask"); } 

notepad.exe verrà eseguito cinque secondi dopo.

per maggiori dettagli e maggiori informazioni vai su wiki

se sai quale class e metodo in quell’assembly hai bisogno puoi invocarlo tu stesso in questo modo:

  Assembly assembly = Assembly.LoadFrom("yourApp.exe"); Type[] types = assembly.GetTypes(); foreach (Type t in types) { if (t.Name == "YourClass") { MethodInfo method = t.GetMethod("YourMethod", BindingFlags.Public | BindingFlags.Instance); if (method != null) { ParameterInfo[] parameters = method.GetParameters(); object classInstance = Activator.CreateInstance(t, null); var result = method.Invoke(classInstance, parameters.Length == 0 ? null : parameters); break; } } } 

System.Diagnostics.Process.Start (“Nome Exe”);