c# - 使用来自 Windows 服务的凭据启动进程

标签 c# .net windows-services

我有一个作为 mydomain\userA 运行的 Windows 服务。我希望能够从该服务运行任意 .exes。通常,我使用 Process.Start() 并且它工作正常,但在某些情况下,我想以不同的用户身份运行可执行文件 (mydomain\userB)。

如果我更改用于启动进程的 ProcessStartInfo 以包含凭据,我会开始收到错误 - 要么是错误对话框显示“应用程序未能正确初始化 (0xc0000142)。单击确定终止应用程序。” ,或“访问被拒绝”Win32Exception。如果我从命令行运行进程启动代码而不是在服务中运行它,进程将使用正确的凭据开始(我已经通过将 ProcessStartInfo 设置为运行 whoami.exe 并捕获命令行输出来验证这一点).

我也尝试过使用 WindowsIdentity.Impersonate() 进行模拟,但这没有用——据我所知,模拟只影响当前线程,并且启动一个新进程会继承进程的安全描述符,而不是当前的线程。

我在一个隔离的测试域中运行它,因此 userA 和 userB 都是域管理员,并且都拥有域范围内的“作为服务登录”权限。

最佳答案

当您使用 ProcessStartInfo 启动新进程时,该进程将在与启动进程相同的窗口站和桌面中启动。如果您使用不同的凭据,那么用户通常没有足够的权限在该桌面上运行。 Failure to initialize 错误是user32.dll在新进程中尝试初始化失败导致的。

要解决这个问题,您必须首先检索与窗口站和桌面关联的安全描述符,并为您的用户向 DACL 添加适当的权限,然后在新凭据下启动您的进程。

编辑:关于如何执行此操作的详细描述和示例代码在这里有点长,所以我整理了一个 article带代码。

        //The following security adjustments are necessary to give the new 
        //process sufficient permission to run in the service's window station
        //and desktop. This uses classes from the AsproLock library also from 
        //Asprosys.
        IntPtr hWinSta = GetProcessWindowStation();
        WindowStationSecurity ws = new WindowStationSecurity(hWinSta,
          System.Security.AccessControl.AccessControlSections.Access);
        ws.AddAccessRule(new WindowStationAccessRule("LaunchProcessUser",
            WindowStationRights.AllAccess, System.Security.AccessControl.AccessControlType.Allow));
        ws.AcceptChanges();

        IntPtr hDesk = GetThreadDesktop(GetCurrentThreadId());
        DesktopSecurity ds = new DesktopSecurity(hDesk,
            System.Security.AccessControl.AccessControlSections.Access);
        ds.AddAccessRule(new DesktopAccessRule("LaunchProcessUser",
            DesktopRights.AllAccess, System.Security.AccessControl.AccessControlType.Allow));
        ds.AcceptChanges();

        EventLog.WriteEntry("Launching application.", EventLogEntryType.Information);

        using (Process process = Process.Start(psi))
        {
        }

关于c# - 使用来自 Windows 服务的凭据启动进程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/677874/

相关文章:

java - 从 Java 程序中终止 Windows session

c# - 如何安装.NET 3.5开发的Windows服务?

c# - 使用 Windows 兼容包创建 .net 核心 Windows 服务

c# - 更改模型类后删除和更新数据库?

javascript - 在c# mvc中将html代码作为javaScript中的字符串传递

c# - 我可以只输出数据表中值的第一个实例吗?

c# - 使用 LINQ 查询获取索引值的集合

c# - 内联表单无法正常工作

c# - 如果使用 Razor MVC3 在 div 标记内声明

c# - MEF 是否需要 .NET 4?