Domanda

Ho scritto un piccolo servizio (semplice Win32) e vorrei sapere se è possibile eseguire più istanze di esso quando più utenti sono connessi.

Sostanzialmente, supponiamo che abbiamo UserA e UserB per UserA il servizio accederà come " domain \ UserA " e per UserB il servizio accederà come " dominio \ UserB " - ovviamente viene dallo stesso eseguibile. Posso cambiare l'accesso in modo dinamico usando la funzione ChangeServiceConfig (), ma sembra cambiarlo a livello di sistema, mentre vorrei che ogni utente avesse la propria copia del servizio in esecuzione solo per lui.

Grazie in anticipo per eventuali suggerimenti.

È stato utile?

Soluzione

I servizi Win32 sono progettati per essere a livello di sistema e iniziare a essere eseguiti prima che qualsiasi utente abbia effettuato l'accesso. Se si desidera eseguire qualcosa su una base per utente, è probabilmente meglio progettarlo come un'applicazione normale ed eseguirlo da il gruppo di avvio dell'utente.

Altri suggerimenti

È forse possibile che il servizio crei processi figlio che poi adottano le credenziali dell'utente (o che vengano avviate con loro)? In questo modo sei ancora limitato a una singola istanza del servizio, ma è comunque in grado di fare i suoi lavori per utente. IIRC esegue il servizio Utilità di pianificazione di Windows.

L'intero concetto di un servizio è che viene avviato prima che qualsiasi utente abbia effettuato l'accesso. quindi anche se ciò fosse possibile, non saresti in grado di scegliere tra userA e userB all'avvio del servizio perché nessuno di essi è ancora connesso.


Una possibile direzione sarebbe che il servizio funzionasse come SISTEMA E ogni pochi minuti controlla se c'è un utente che ha effettuato l'accesso, se è impersonato quell'utente e fa queste cose.

Sì, sembra vicino (sto rispondendo al commento di Greg, ma i commenti sono troppo brevi per adattarsi alla mia risposta).

Non conosco in anticipo l'elenco degli utenti, ma esiste un'applicazione di controllo della GUI che verrebbe utilizzata per inserire coppie nome utente / password per ciascun utente. Pertanto, l'utente A accede, esegue l'applicazione, immette le sue credenziali e il servizio lo utilizza. Allo stesso tempo (dopo che l'utenteA si è disconnesso, ma il servizio è ancora in esecuzione con le credenziali dell'utenteA) userB accede, utilizza l'app e un'altra copia del servizio inizia a essere eseguita come utenteB connesso. Pertanto, contemporaneamente sono in esecuzione i servizi userA e userB.

È possibile?

Probabilmente stai cercando di impersonare gli utenti. Scopri alcuni riferimenti che ho trovato con una rapida ricerca su Google qui:

Sembra che tu abbia effettivamente due requisiti diversi e contrastanti, in termini di tempistica e identità.

  1. Esegui come ciascun utente connesso
  2. Esegui automaticamente anche se nessun utente ha effettuato l'accesso.

Non c'è modo di farlo in modo banale, invece considera di racchiudere il tuo programma in un servizio; il programma verrà eseguito normalmente all'avvio per ciascun utente (tramite la cartella di avvio o il taskcheduler) e inoltre creerà un servizio per eseguire la tua app come utente di sistema (o qualsiasi altro utente definito).
Dal momento che hai anche bisogno (menzionalo nei commenti) dell'app per continuare a funzionare come utente finale anche dopo che si è disconnesso, puoi fare in modo che il servizio gestisca questo processo per te.

TUTTAVIA questa potrebbe non essere la migliore idea, poiché l'utente ha ancora effettuato l'accesso in modo efficace. Ciò può avere numerosi effetti collaterali, tra cui sicurezza, prestazioni (troppi utenti hanno effettuato l'accesso contemporaneamente ...), ecc.

È possibile creare un'applicazione di servizio e un'applicazione non di servizio (normale) e farle comunicare tramite IPC (file mappato, pipe, MailSolts ... lo chiami).

In questo modo risolvi tutti i problemi.

NOTA: la stessa applicazione può comportarsi diversamente: quando avviata come processo e quando avviata da un utente, ma alla fine è la stessa cosa, hai ancora 2 applicazioni (non importa se hai solo un eseguibile).

È possibile eseguire con account diversi. In effetti, questo è comune. Vedi svchost.exe, che implementa un sacco di servizi OS.

Non capisco come determini quali account. In una grande azienda, sono installati molti PC in modo che tutti gli oltre 100.000 dipendenti possano utilizzarlo. Non si desidera eseguire il servizio come utenti che hanno effettuato l'accesso, né è possibile eseguirlo per tutti i 100.000 utenti. Quindi, per quali account, devo chiedere?

Un processo di Windows può essere eseguito solo con i privilegi di un singolo utente alla volta. Questo vale per servizi e altri processi. Con sufficienti privilegi è possibile " cambiare " tra utenti diversi utilizzando la rappresentazione. Il modello più comune per ciò che si sta tentando di fare è disporre di un'istanza di un servizio privilegiato che si registra per accedere / disconnettersi dagli eventi e crea processi figlio di conseguenza, ognuno dei quali rappresenta l'utente registrato. Il modello semplificherà anche l'interfaccia utente man mano che ciascun processo viene eseguito sul desktop di ciascun utente separato, come se si trattasse di un'applicazione normale.

Se mantieni il codice del servizio privilegiato il più semplice possibile, questo modello ha l'ulteriore vantaggio di ridurre al minimo la superficie di attacco del tuo codice. Se un utente rileva un problema di sicurezza su "in esecuzione come utente" lato del servizio non è un problema, mentre i problemi di sicurezza nei servizi privilegiati potrebbero portare all'escalation dei privilegi. Infatti, prima che i servizi privilegiati di Vista che implementano un ciclo di elaborazione dei messaggi di Windows siano vulnerabili a un tipo di attacco chiamato Attacchi frantumati , di cui dovresti essere a conoscenza dato ciò che stai cercando di fare.

Vuoi che funzioni sempre, quindi vuoi un servizio.

Volete qualcosa che tenga traccia di ciascun utente, quindi volete un'applicazione che viene eseguita nella sessione dell'utente e che comunica con il servizio (usando named pipe o DCOM o qualunque cosa si adatti alle vostre esigenze).

Non sono necessarie più istanze del servizio. Dalla descrizione del tuo problema sembra che ciò di cui hai bisogno sia un servizio in grado di impersonare gli utenti ed eseguire lavori per loro conto.

Puoi farlo implementando un oggetto COM ospitato in un servizio. L'applicazione client (eseguita dall'utente finale) chiamerà CoCreateInstanceEx sul CLSID. Ciò causerebbe la creazione di una nuova istanza dell'oggetto COM nel servizio. Quindi l'applicazione può utilizzare un metodo su una delle tue interfacce per passare le credenziali utente raccolte all'oggetto COM (anche se sarei diffidente nel raccogliere le credenziali e invece vedrei se posso passare il token utente). L'oggetto COM in esecuzione nel contesto del servizio può quindi chiamare LogonUser () per accedere all'utente e impersonarlo, in modo che possa fare qualsiasi cosa per suo conto (come trovare la cartella appdata locale dell'utente :-)). Altre risposte hanno buoni collegamenti per impersonare gli utenti usando credenziali o token.

Se ti senti a tuo agio con COM, ti suggerirei di creare i tuoi oggetti come multithread (che vivono nell'MTA), in modo che la loro esecuzione non sia serializzata da COM. In caso contrario, il modello a thread singolo predefinito sarebbe abbastanza buono per te.

La procedura guidata ATL di Visual Studio può generare lo scheletro di un oggetto COM che vive in un servizio. Puoi anche leggere sull'implementazione del servizio Windows con ATL qui: http : //msdn.microsoft.com/en-us/library/74y2334x (VS.80) aspx

Se non conosci affatto COM, puoi utilizzare altri canali di comunicazione per passare le credenziali al tuo servizio.

In ogni caso, una volta che il servizio avrà le credenziali, tutto il lavoro per conto dell'utente dovrà essere eseguito su un thread in background, in modo da non bloccare l'applicazione in esecuzione come utente.

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