草庐IT

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

coder 2023-11-09 原文

首先,我要感谢为这个站点工作的所有人员,他们对开发人员非常有用。这是我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/

有关windows - CreateProcessAsUser 在 "change user"时不起作用的更多相关文章

  1. ruby - 在 Ruby 程序执行时阻止 Windows 7 PC 进入休眠状态 - 2

    我需要在客户计算机上运行Ruby应用程序。通常需要几天才能完成(复制大备份文件)。问题是如果启用sleep,它会中断应用程序。否则,计算机将持续运行数周,直到我下次访问为止。有什么方法可以防止执行期间休眠并让Windows在执行后休眠吗?欢迎任何疯狂的想法;-) 最佳答案 Here建议使用SetThreadExecutionStateWinAPI函数,使应用程序能够通知系统它正在使用中,从而防止系统在应用程序运行时进入休眠状态或关闭显示。像这样的东西:require'Win32API'ES_AWAYMODE_REQUIRED=0x0

  2. ruby-on-rails - rails : "missing partial" when calling 'render' in RSpec test - 2

    我正在尝试测试是否存在表单。我是Rails新手。我的new.html.erb_spec.rb文件的内容是:require'spec_helper'describe"messages/new.html.erb"doit"shouldrendertheform"dorender'/messages/new.html.erb'reponse.shouldhave_form_putting_to(@message)with_submit_buttonendendView本身,new.html.erb,有代码:当我运行rspec时,它失败了:1)messages/new.html.erbshou

  3. ruby-on-rails - 由于 "wkhtmltopdf",PDFKIT 显然无法正常工作 - 2

    我在从html页面生成PDF时遇到问题。我正在使用PDFkit。在安装它的过程中,我注意到我需要wkhtmltopdf。所以我也安装了它。我做了PDFkit的文档所说的一切......现在我在尝试加载PDF时遇到了这个错误。这里是错误:commandfailed:"/usr/local/bin/wkhtmltopdf""--margin-right""0.75in""--page-size""Letter""--margin-top""0.75in""--margin-bottom""0.75in""--encoding""UTF-8""--margin-left""0.75in""-

  4. ruby - 检查 "command"的输出应该包含 NilClass 的意外崩溃 - 2

    为了将Cucumber用于命令行脚本,我按照提供的说明安装了arubagem。它在我的Gemfile中,我可以验证是否安装了正确的版本并且我已经包含了require'aruba/cucumber'在'features/env.rb'中为了确保它能正常工作,我写了以下场景:@announceScenario:Testingcucumber/arubaGivenablankslateThentheoutputfrom"ls-la"shouldcontain"drw"假设事情应该失败。它确实失败了,但失败的原因是错误的:@announceScenario:Testingcucumber/ar

  5. ruby-on-rails - 如果 Object::try 被发送到一个 nil 对象,为什么它会起作用? - 2

    如果您尝试在Ruby中的nil对象上调用方法,则会出现NoMethodError异常并显示消息:"undefinedmethod‘...’fornil:NilClass"然而,有一个tryRails中的方法,如果它被发送到一个nil对象,它只返回nil:require'rubygems'require'active_support/all'nil.try(:nonexisting_method)#noNoMethodErrorexceptionanymore那么try如何在内部工作以防止该异常? 最佳答案 像Ruby中的所有其他对象

  6. ruby-on-rails - 迷你测试错误 : "NameError: uninitialized constant" - 2

    我遵循MichaelHartl的“RubyonRails教程:学习Web开发”,并创建了检查用户名和电子邮件长度有效性的测试(名称最多50个字符,电子邮件最多255个字符)。test/helpers/application_helper_test.rb的内容是:require'test_helper'classApplicationHelperTest在运行bundleexecraketest时,所有测试都通过了,但我看到以下消息在最后被标记为错误:ERROR["test_full_title_helper",ApplicationHelperTest,1.820016791]test

  7. ruby-on-rails - 相关表上的范围为 "WHERE ... LIKE" - 2

    我正在尝试从Postgresql表(table1)中获取数据,该表由另一个相关表(property)的字段(table2)过滤。在纯SQL中,我会这样编写查询:SELECT*FROMtable1JOINtable2USING(table2_id)WHEREtable2.propertyLIKE'query%'这工作正常:scope:my_scope,->(query){includes(:table2).where("table2.property":query)}但我真正需要的是使用LIKE运算符进行过滤,而不是严格相等。然而,这是行不通的:scope:my_scope,->(que

  8. 使用 ACL 调用 upload_file 时出现 Ruby S3 "Access Denied"错误 - 2

    我正在尝试编写一个将文件上传到AWS并公开该文件的Ruby脚本。我做了以下事情:s3=Aws::S3::Resource.new(credentials:Aws::Credentials.new(KEY,SECRET),region:'us-west-2')obj=s3.bucket('stg-db').object('key')obj.upload_file(filename)这似乎工作正常,除了该文件不是公开可用的,而且我无法获得它的公共(public)URL。但是当我登录到S3时,我可以正常查看我的文件。为了使其公开可用,我将最后一行更改为obj.upload_file(file

  9. ruby - 安装 Ruby 时遇到问题(无法下载资源 "readline--patch") - 2

    当我尝试安装Ruby时遇到此错误。我试过查看this和this但无济于事➜~brewinstallrubyWarning:YouareusingOSX10.12.Wedonotprovidesupportforthispre-releaseversion.Youmayencounterbuildfailuresorotherbreakages.Pleasecreatepull-requestsinsteadoffilingissues.==>Installingdependenciesforruby:readline,libyaml,makedepend==>Installingrub

  10. ruby - 在 Windows 机器上使用 Ruby 进行开发是否会适得其反? - 2

    这似乎非常适得其反,因为太多的gem会在window上破裂。我一直在处理很多mysql和ruby​​-mysqlgem问题(gem本身发生段错误,一个名为UnixSocket的类显然在Windows机器上不能正常工作,等等)。我只是在浪费时间吗?我应该转向不同的脚本语言吗? 最佳答案 我在Windows上使用Ruby的经验很少,但是当我开始使用Ruby时,我是在Windows上,我的总体印象是它不是Windows原生系统。因此,在主要使用Windows多年之后,开始使用Ruby促使我切换回原来的系统Unix,这次是Linux。Rub

随机推荐