一尘不染

使用Windows服务中的凭据启动进程

c#

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

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

我还尝试使用WindowsIdentity.Impersonate()模拟,但这没有用-
据我了解,模拟仅会影响当前线程,而启动新进程将继承该进程的安全描述符,而不继承当前线程。

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


阅读 411

收藏
2020-05-19

共1个答案

一尘不染

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

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

编辑:关于如何执行此操作和示例代码的详细说明在这里有点长了,所以我整理了一篇代码文章

        //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))
        {
        }
2020-05-19