Es ist wirklich möglich. Das Hauptproblem, das Sie haben, ist, dass Windows als Terminalserver und eine Benutzersitzung als Remotesitzung angesehen werden sollte. Ihr Dienst sollte in der Lage sein, einen Prozess zu starten, der in der Remotesitzung ausgeführt wird.
Übrigens, wenn Sie einen Dienst schreiben, der unter Windows XP läuft und nicht zu einer Domäne hinzugefügt wird und der schnelle Benutzerwechsel aktiviert ist, können Sie die gleichen Probleme haben, einen Prozess auf dem zweiten (dritten) zu starten und so weiter) angemeldet Benutzer Desktop.
Ich hoffe, Sie haben ein Benutzer-Token, das Sie zum Beispiel in Bezug auf Identitätswechsel erhalten oder Sie haben eine dwSessionId
Sitzung. Wenn Sie es nicht haben, können Sie versuchen, verwenden einige WTS-Funktion (Remote Desktop Services API http://msdn.microsoft.com/en-us/library/aa383464.aspx, zum Beispiel WTSEnumerateProcesses
oder WTSGetActiveConsoleSessionId
) oder LSA-API, um die entsprechenden Benutzer-Session, um herauszufinden, (LsaEnumerateLogonSessions
siehe http://msdn.microsoft.com/en-us/library/aa378275.aspx und LsaGetLogonSessionData
siehe http://msdn.microsoft.com/en-us/library/aa378290.aspx) oder ProcessIdToSessionId
(siehe http://msdn.microsoft.com/en-us/library/aa382990.aspx).
Sie können GetTokenInformation
Funktion mit dem Parameter TokenSessionId
(siehe http://msdn.microsoft.com/en-us/library/aa446671.aspx) verwenden, um die Session-ID dwSessionId
der Benutzer-Sitzung zu erhalten, wenn Sie die Benutzer hClient
Token kennen.
BOOL bSuccess;
HANDLE hProcessToken = NULL, hNewProcessToken = NULL;
DWORD dwSessionId, cbReturnLength;
bSuccess = GetTokenInformation (hClient, TokenSessionId, &dwSessionId,
sizeof(DWORD), &cbReturnLength);
bSuccess = OpenProcessToken (GetCurrentProcess(), MAXIMUM_ALLOWED, &hProcessToken);
bSuccess = DuplicateTokenEx (hProcessToken, MAXIMUM_ALLOWED, NULL,
SecurityImpersonation,
TokenPrimary, &hNewProcessToken);
EnablePrivilege (SE_TCB_NAME);
bSuccess = SetTokenInformation (hNewProcessToken, TokenSessionId, &dwSessionId,
sizeof(DWORD));
bSuccess = CreateProcessAsUser (hNewProcessToken, NULL, szCommandToExecute, ...);
Dieser Code ist nur ein Schema. EnablePrivilege
ist eine einfache Funktion verwendet AdjustTokenPrivileges
zu aktivieren SE_TCB_NAME
Privileg (siehe http://msdn.microsoft.com/en-us/library/aa446619.aspx als Vorlage). Es ist wichtig, dass der Prozess, von dem aus Sie einen Prozess starten, über TCB-Berechtigungen verfügt. Wenn Ihr Service jedoch unter dem lokalen System ausgeführt wird, verfügen Sie über ausreichende Berechtigungen. Das folgende Codefragment funktioniert übrigens nicht nur mit dem lokalen Systemkonto, sondern auch mit dem Konto SE_TCB_NAME
, um die aktuelle Terminalserversitzung wechseln zu können.
Eine weitere Bemerkung. Im obigen Code starten wir einen neuen Prozess mit demselben Account wie der aktuelle Prozess (zB Lokales System). Sie ändern einen Code ändern, um ein anderes Konto zu verwenden, z. B. das Benutzer-Token hClient
. Es ist nur wichtig, eine primary token
zu haben. Wenn Sie ein Identitätswechsel-Token haben, können Sie es wie im obigen Code in das primäre Token konvertieren.
In der Struktur STARTUPINFO
in CreateProcessAsUser
verwendet werden, sollten Sie lpDesktop =
WinSta0 \ Default“verwenden.
Verlassen Sie sich auf Ihre Anforderungen könnte es auch CreateEnvironmentBlock
benötigt werden, um zu verwenden, um eine neue Umgebung Block zu erstellen, die Sie auf den neuen vorbei wird Prozess.
ich empfehle Sie auch How to ensure process window launched by Process.Start(ProcessStartInfo) has focus of all Forms? zu lesen, wo ich beschreiben, wie zu erzwingen, dass der Prozess im Vordergrund auf dem Anwender-Desktop gestartet.
Welche Benutzer-ses sion? –
Der lokale interaktive Benutzer ist das, worauf ich mich konzentriere. Ich bin hauptsächlich daran interessiert, die Workstation vom Dienst zu sperren, muss aber abhängig von bestimmten Bedingungen auch andere Programme ausführen. – Brad