Domanda

Sono in esecuzione di un processo dall'interno di un servizio di Windows utilizzando

ProcessStartInfo processStartInfo = new ....
Process.Start(processStartInfo);

Il problema è che, se corro il servizio sotto l'account di sistema locale, funziona bene, ma non mostra la finestra dei programmi. Ho provato a mettere le credenziali dell'utente in proprietà del servizio, ma poi 'Consenti al servizio di interagire con il desktop' casella di controllo diventa disable.

ho davvero bisogno di eseguire l'applicazione chiamando dal servizio, e ho davvero bisogno di vedere la finestra dell'applicazione.

Help me please.

UPD. Beh, si utilizza sovraccaricato versione di Process.Start quello che prende il nome utente, password e dominio - tirerà il programma sul desktop. Ma ora si comincia l'applicazione in uno credenziali, ma mostra che presenti sul desktop di un utente differente. Come mai?

UPD2: Ho un'idea! Posso usare psexec.exe da Sysinternals Suite. Ma il problema è che ho bisogno di iniziare quella cosa in silenzio "come amministratore". E io non so come. Voglio dire, anche se siete già avere diritti di amministratore, a volte devi dire manualmente "Esegui come amministratore", conferma UAC e solo dopo che si è pronti ad andare. Io non so come in silenzio eseguire qualcosa senza portare UAC cosa ....

UPD3: Caro Signore. Ho quella cosa! Infine.

Ok. In principio il problema era effettivamente in sessione 0 isolamento cosa. Così ho bisogno di costruire un'applicazione centrale che può essere avviato dal servizio e poi, l'app a sua volta supponiamo di iniziare la mia domanda tramite RPC e portarlo a un desktop. Invece di costruire mezzo strato app ho deciso di utilizzare lo strumento psexec (in ogni caso funziona esattamente il modo in cui ho bisogno - tramite RPC). E quando ho cercato di utilizzare tale strumento in account di sistema locale non ha funzionato per qualche ragione. E poi mi sono reso conto - il motivo è finestra popup EULA maledetto che MS ha messo in ogni singolo pstool, ed era impossibile fare clic sul pulsante per finestra di dialogo di conferma sotto l'account di sistema locale. Quindi la soluzione è quella di creare una chiave nel Registro di sistema HKU.DEFAULT \ Software \ Sysinternals \ PsExec con valore DWORD EulaAccepted = 1

Evviva, ora funziona! MA! Ora ho bisogno di portare il programma a schermo dell'utente attualmente connesso. Per farlo Mi serve l'id di sessione!

Quindi la domanda è: come arrivare attualmente connesso id di sessione dell'utente? E cosa succede se non c'è nessuno registrato ancora? Cosa ID di sessione che sarebbe?

UPD4: Questo è tutto! Ho ottenuto che uno!

[DllImport ( "Kernel32.dll", EntryPoint = "WTSGetActiveConsoleSessionID")]  public static extern int WTSGetActiveConsoleSessionID ();

Grazie ragazzi!

È stato utile?

Soluzione

Una soluzione sarebbe quella di avere un terzo atto processo come un intermediario, e dirgli di lanciare applicazioni tramite RPC / named pipe.

Processi:

  • servizio di Windows
  • applicazione Intermediario
  • L'applicazione che si desidera eseguire

Lo spessore crea un endpoint di comunicazione (named pipe, WCF endpoint) e ascolti su di esso. Quando si riceve un messaggio di andare avanti, si lancia l'applicazione che si desidera eseguire.

Poi, quando il servizio di Windows vuole lanciare un app, si trova e si apre l'endpoint (named pipe, WCF endpoint), e invia il messaggio a lanciare l'applicazione. Quindi l'applicazione intermediario si occupa del business processo di lancio, e non ha alcuna delle limitazioni che il servizio Windows ha.

Fare avviare questo processo intermediario con l'accesso, e si sta bene ad andare.

Questo è simile al modo in cui il lavoro di agente di test / regolatore di Microsoft quando è necessario eseguire test che interagiscono con il desktop.

Altri suggerimenti

È possibile ottenere l'id di sessione attiva console utilizzando WTSGetActiveConsoleSessionID (dal terminal services API). È possibile utilizzarla solo per WinXP / Win2K3 o superiore, ma che dovrebbe andare bene, come si può codificare 0 per l'id di sessione su Win2K o precedente. Ecco la firma PInvoke per esso:

[DllImport("Kernel32.dll", SetLastError = true)]
[return:MarshalAs(UnmanagedType.U4)]
public static extern int WTSGetActiveConsoleSessionId ( );

Per quanto riguarda il lancio di un processo in sessione dell'utente, è possibile fare riferimento alla risposta che ho dato qui . Si tratta fondamentalmente callling quattro API; WTSGEtConsoleSessionId, WTSQueryUserToken, DuplicateTokenEx, poi CreateProcessAsUser, e funzionerà su qualsiasi macchina in esecuzione WinXP / Win2K3 o superiore.

Questo può essere fatto senza un processo intermedio, ma richiede più di 500 linee di codice per fare. In sostanza, si vuole lanciare il secondo processo come l'attuale utente connesso. Per Vista / 7, l'utente avrà il proprio processo winlogon, mentre per XP, avranno un processo di explorer. È necessario per ottenere il token primario, blocco di ambiente, attributi di sicurezza e attributi di sicurezza filo di quel processo in esecuzione quindi chiamare la funzione API CreateProcessAsUser Windows con tutte le informazioni, facendo in modo di selezionare la stazione finestra corretta così (di solito "WinSta0 \ Default "). Questo è tutto fattibile, ma si potrebbe avere un tempo migliore con l'altro suggerimento di un secondo processo e IPC.

Se si sta tentando questo su qualsiasi cosa più recente di Windows XP questo non funzionerà. Questo è causa di una nuova funzionalità introdotta in Vista / Windows 7 chiamato sessione 0 isolamento. http://msdn.microsoft.com/en-us/library/bb756986. aspx non sarà in grado di ottenere un'applicazione lanciata da un servizio di presentarsi sul desktop degli utenti.

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