gpt4 book ai didi

windows - CreateProcessAsUser 在 "change user"时不起作用

转载 作者:可可西里 更新时间:2023-11-01 12:27:34 26 4
gpt4 key购买 nike

首先,我要感谢为这个站点工作的所有人员,他们对开发人员非常有用。这是我3天来第一次开发受阻。我在 Internet 上搜索了解决方案,但没有找到解决此问题的任何方法。

因此,我开发了一项服务,当用户登录时,该服务必须在 vista/seven/xp 上执行外部程序。此服务的一些特点:

  • 自动
  • 没有互动。
  • 检测登录用户的 session ID

以交互式用户身份运行外部 GUI 应用程序:

  1. 为确保打开用户 session ,我列出了所有“explorer.exe”进程,使用 msdn 函数 ProcessIdToSessionId 提取它们的 Pid 和 SessionID
  2. 如果登录用户的 SessionID 与这个“explorer.exe”进程的 session ID 相同,我确信“好”桌面正在运行,所以现在我可以执行外部程序。 (我说“好”桌面是因为,如您所知,系统上可以打开多个用户 session )
  3. 之后,我使用此函数运行应用程序:

    function RunInteractive(prog_filename: String; sessionID: Cardinal): boolean;
    var hToken: THandle;
    si: _STARTUPINFOA;
    pi: _PROCESS_INFORMATION;
    begin
    ZeroMemory(@si, SizeOf(si));
    si.cb := SizeOf(si);
    SI.lpDesktop := nil;
    if WTSQueryUserToken(sessionID, hToken)
    then begin
    if CreateProcessAsUser(hToken, nil, PChar(prog_filename), nil, nil, False, 0, nil, PChar(ExtractFilePath(prog_filename)), si, pi)
    then result := true
    else result := false;
    end
    else Begin
    result := false;
    End;
    CloseHandle(hToken);
    end;

此代码在大多数情况下都可以,除了一种情况:当我更改用户时。让我用 2 个简单的用户(Domain\user1 和 Domain\user2)来解释它:

  1. 为了干净起见,我安装了服务并重新启动了系统
  2. 我打开与 user1 的 session :外部程序已执行,我可以看到它的形式
  3. 关闭 session 并打开与 user2 的 session :外部程序已执行,我可以看到它的形式。

如果我这样做 X 次,结果总是一样的,非常好......但是如果我这样做:

  1. 我重新安装服务并重启系统
  2. 我打开与 user1 的 session :外部程序已执行,我可以看到它的形式
  3. 这一次,我没有关闭 session ,而是更改用户为user2:外部程序已执行,但我看不到表单并发生错误:系统错误代码 5:访问被拒绝。

出了点问题,但我找不到解决方案。感谢您的回答...

最佳答案

不需要枚举正在运行的explorer.exe进程,可以使用WTSGetActiveConsoleSessionId()相反,然后将该 SessionId 传递给 WTSQueryUserToken() .注意 WTSQueryUserToken()返回模拟 token ,但 CreateProcessAsUser()需要主 token ,所以使用 DuplicateTokenEx()对于该转换。

您还应该使用 CreateEnvironmentBlock()因此生成的进程具有适合正在使用的用户帐户的适当环境。

最后,设置 STARTUPINFO.lpDesktop字段到 'WinSta0\Default'而不是 nil因此生成的 UI 可以正确显示。

我已经使用这种方法好几年了,没有遇到任何问题。例如:

function CreateEnvironmentBlock(var lpEnvironment: Pointer; hToken: THandle; bInherit: BOOL): BOOL; stdcall; external 'userenv.dll'
function DestroyEnvironmentBlock(lpEnvironment: Pointer): BOOL; stdcall; external 'userenv.dll';

function RunInteractive(prog_filename: String): Boolean;
var
hUserToken, hToken: THandle;
si: _STARTUPINFOA;
pi: _PROCESS_INFORMATION;
SessionId: DWORD;
Env: Pointer;
begin
Result := False;

ZeroMemory(@si, SizeOf(si));
si.cb := SizeOf(si);
si.lpDesktop := 'WinSta0\Default';

SessionId := WTSGetActiveConsoleSessionId;
if SessionId = $FFFFFFFF then Exit;

if not WTSQueryUserToken(SessionID, hToken) then Exit;
try
if not DuplicateTokenEx(hToken, MAXIMUM_ALLOWED, nil, SecurityIdentification, TokenPrimary, hUserToken) then Exit;
finally
CloseHandle(hToken);
end;

try
if not CreateEnvironmentBlock(Env, hUserToken, False) then Exit;
try
Result := CreateProcessAsUser(hUserToken, nil, PChar(prog_filename), nil, nil, False, CREATE_UNICODE_ENVIRONMENT, Env, PChar(ExtractFilePath(prog_filename)), si, pi);
if Result then
begin
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
end;
finally
DestroyEnvironmentBlock(Env);
end;
finally
CloseHandle(hUserToken);
end;
end;

关于windows - CreateProcessAsUser 在 "change user"时不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8081429/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com