2017-05-09 2 views
1

Ich muss eine Befehlszeilenanwendung von einem Windows-Dienst ausführen und als einen anderen Windows-Benutzer ausführen (indem Sie domain\user und password bereitstellen).Wie kann CreateProcessWithLogonW von einer Dienstanwendung verwendet werden?

wickelte ich den Windows-API CreateProcessWithLogonW() in meiner eigenen RunAppAsAnotherWindowsUser() Funktion auf diese Weise:

function CreateProcessWithLogonW(
    lpUsername, 
    lpDomain, 
    lpPassword: PWideChar; 
    dwLogonFlags: DWORD; 
    lpApplicationName: PWideChar; 
    lpCommandLine: PWideChar; 
    dwCreationFlags: DWORD; 
    lpEnvironment: Pointer; 
    lpCurrentDirectory: PWideChar; 
    lpStartupInfo: PStartupInfoW; 
    lpProcessInformation: PProcessInformation 
): BOOL; stdcall; external 'advapi32.dll'; 

function RunAppAsAnotherWindowsUser(const User, Domain, PW, Application, CmdLineParams: WideString): LongWord;  

const 
    LOGON_WITH_PROFILE = $00000001; 

implementation 

function RunAppAsAnotherWindowsUser(const User, Domain, PW, Application, CmdLineParams: WideString): LongWord; 
var 
    si   : TStartupInfoW; 
    pif   : TProcessInformation; 
begin 
    ZeroMemory(@si, sizeof(si)); 
    si.cb := sizeof(si); 
    si.dwFlags := STARTF_USESHOWWINDOW; 
    si.wShowWindow := 1; 

    SetLastError(0); 
    CreateProcessWithLogonW(PWideChar(User), PWideChar(Domain), PWideChar(PW), 
    LOGON_WITH_PROFILE, nil, PWideChar(Application+' '+CmdLineParams), 
    CREATE_DEFAULT_ERROR_MODE, nil, nil, @si, @pif); 
    Result := GetLastError; 
end; 

Die oben war adapted from here.

Wenn ich RunAppAsAnotherWindowsUser() von einer Win32 VCL-Anwendung verwende, die ich zum Testen erstellt habe, funktioniert es gut. Wenn ich es von einem Windows-Dienst aus anrufe, funktioniert es nicht.

Ich lese this page als advised here, aber in meinem Fall habe ich keinen interaktiven Prozess, da meine Befehlszeilenanwendung nur Datenbankabfragen und schreibt in eine temporäre Datei.

Ich habe versucht, den Dienst sowohl als lokales System als als Domänenadministrator auszuführen, aber das Verhalten ist das gleiche.

Der Dienst ist eine IntraWeb-Anwendung (VCL für das Web), die als Dienst erstellt wird. Die gleiche Anwendung wie exe funktioniert gut. Ich schreibe das nur, um den Kontext zu erklären, in dem ich arbeite.

Könnten Sie mir bitte helfen, das Problem zu lokalisieren?

+3

Was ist das eigentliche Problem, das Sie mit ihm haben werden? Erhalten Sie einen Fehlercode? Wenn ja, welcher? Bitte sei spezifischer? –

+3

Dienste werden in einer isolierten Sitzung ausgeführt. Sie sollten den Prozess in der Konsole oder in einer Benutzersitzung starten. – Remko

+0

Ich habe versucht, Prozess als ein Benutzer (in der Tat als der PC-Administrator), löst dies einen Teil des Problems tatsächlich GetLastError (siehe Code oben) ist 0 (also keine Fehler), während es 5 (zu antworten zu @RemyLebeau) vorher. Wie auch immer, die exe, die ich mit RunAppAsAnotherWindowsUser ausführe, kann keine Datei schreiben, selbst wenn ich allen Benutzern im dedizierten Ordner vollen Zugriff gewähre. Wie auch immer, es ist jetzt nur eine Angelegenheit oder eine Erlaubnis. Das Ausführen des Servers als Benutzer war ein wichtiger Fortschritt, jetzt muss ich mit Windows-Ordner-Berechtigungen kämpfen (die wirklich nicht so offensichtlich sind). – LaBracca

Antwort

1

Von einem Dienst sollten Sie den Prozess in der Sitzung des Benutzers starten (auf einem physischen PC in der Regel die Konsolensitzung). Dies ist der Fall, da Windows Vista:

Dienste haben immer in Sitzung 0 Bevor Windows Vista läuft, die ersten Benutzer auch 0. Nun zu Sitzung zugewiesen anmelden wurde, Sitzung 0 ist ausschließlich für Dienste reserviert und andere Anwendungen nicht verbunden mit einer interaktiven Benutzersitzung. (Der erste angemeldete Benutzer ist mit Sitzung 1 verbunden, der zweite Benutzer, der sich anmeldet, ist mit Sitzung 2 verbunden usw.) Sitzung 0 unterstützt keine Prozesse, die mit dem Benutzer interagieren.

Siehe here für ein sehr einfaches Beispiel auf meinem Blog mit Jedi Apilib.

Von diesem Blog:

uses JwaWinbase, JwaWtsApi32;  

var hToken: THandle; 
    si: _STARTUPINFOA; 
    pi: _PROCESS_INFORMATION; 
var Ret: Cardinal; 
    sTitle: string; 
    sMsg: string; 
begin 
    ZeroMemory(@si, SizeOf(si)); 
    si.cb := SizeOf(si); 
    si.lpDesktop := nil;  

    if WTSQueryUserToken(WtsGetActiveConsoleSessionID, hToken) then 
    begin 
    if CreateProcessAsUser(hToken, nil, 'notepad.exe', nil, nil, False, 
     0, nil, nil, si, pi) then 
    begin 
     // Do some stuff 
    end; 
    end; 
end; 
+0

Hallo, aber da ich CreateProcessWithLogonW und nicht CreateProcessAsUser verwenden muss, wie kann ich tun, da CreateProcessWithLogonW Token nicht als Parameter hat? – LaBracca

+1

Erhalte ein Token mit 'LogonUser' (https://msdn.microsoft.com/de-us/library/windows/desktop/aa378184 (v = vs.85) .aspx) dann ändern sessionid mit 'SetTokenInformation' (https://msdn.microsoft.com/en-us/library/windows/desktop /aa379591(v=vs.85).aspx). Übergeben Sie das Token an 'CreateProcessAsUser'. Es muss natürlich ein angemeldeter Benutzer vorhanden sein, in der Servicesitzung können Sie keine interaktiven Prozesse starten. – Remko

+0

Warum müssen Sie CreateProcessWithLogon aufrufen? Können Sie sich nicht als Benutzer ausgeben und den erforderlichen Code im Kontext des Benutzers ausführen? – Remko

Verwandte Themen