从.NET服务作为其他用户启动.NET应用程序时的权限问题?
我正在尝试在与.NET服务不同的用户下启动.NET应用程序。 我们的想法是在Windows中创建一个沙盒托管应用程序。 在服务中,我以编程方式在Windows中创建用户,为该用户创建文件夹,并将主机.exe从服务器下载到该文件夹中。 然后我使用System.Diagnostics.Process运行主机.exe。 这是该过程的StartInfo:
_process = new Process { StartInfo = { Arguments = " -debug", FileName = instanceDirectory + "host.exe", WorkingDirectory = instanceDirectory, UseShellExecute = false, RedirectStandardError = true, RedirectStandardOutput = true, RedirectStandardInput = true, UserName = Helpers.GetUserNameForInstance(_hostid), Password = _hostpass, Domain = "" }, EnableRaisingEvents = true };
当我将服务作为SERVICE运行时,进程立即崩溃,错误代码为-1073741502。 但是当我在Windows服务中指定的同一个用户运行服务但在控制台中以交互方式运行时,一切正常。 只有在将服务作为SERVICE运行而不是直接在控制台中运行时才会发生这种情况。
任何帮助将非常感激。 这已经很长一段时间了,这是最后的手段:(
似乎使用new Process()
与用户名和密码和服务模式“不计算”:)
从MSDN引用:
您可以将StartInfo属性中指定的参数更改为在进程上调用Start方法的时间。 启动该过程后,更改StartInfo值不会影响或重新启动关联的进程。 如果使用ProcessStartInfo .. ::。UserName和ProcessStartInfo .. ::。Password属性设置调用Start(ProcessStartInfo)方法,则调用非托管的CreateProcessWithLogonW函数,即使CreateNoWindow属性值,也会在新窗口中启动该进程为true或WindowStyle属性值为Hidden。
此外,查看CreateProcessWithLogonW文档:
lpStartupInfo [in]
指向STARTUPINFO结构的指针。 应用程序必须将指定用户帐户的权限添加到指定的窗口站和桌面,即使对于WinSta0 \ Default也是如此。
如果lpDesktop成员为NULL或空字符串,则新进程将inheritance其父进程的桌面和窗口工作站。 应用程序必须将指定用户帐户的权限添加到inheritance的窗口站和桌面。
.NET StartupInfo中没有lpDesktop,另一方面,SERVICE用户没有桌面,这可能会导致您的问题。
简而言之,尝试将LoadUserProfile
设置为true
以从注册表加载用户的信息,或者您可能需要设置工作目录等。
要进一步调查,您应该检查您的环境,并可能使用FileMon记录访问哪些文件。
我将尝试在新创建的用户的模拟上下文中创建进程,如下所示。
[DllImport("advapi32.DLL", SetLastError = true)] public static extern int LogonUser(string lpszUsername, string lpszDomain, string lpszPassword, int dwLogonType, int dwLogonProvider, out IntPtr phToken); [DllImport("kernel32.dll", CharSet = CharSet.Auto)] public extern static bool CloseHandle(IntPtr handle); [DllImport("advapi32.DLL")] public static extern bool ImpersonateLoggedOnUser(IntPtr hToken); static void Main() { IntPtr admin_token = new IntPtr(); WindowsIdentity wid_admin = null; WindowsImpersonationContext wic = null; LogonUser("username", "domain", "password", 9, 3, out admin_token); wid_admin = new WindowsIdentity(admin_token); wic = wid_admin.Impersonate(); _process = new Process { StartInfo = { Arguments = " -debug", FileName = instanceDirectory + "host.exe", WorkingDirectory = instanceDirectory, UseShellExecute = false, RedirectStandardError = true, RedirectStandardOutput = true, RedirectStandardInput = true, UserName = Helpers.GetUserNameForInstance(_hostid), Password = _hostpass, Domain = "" }, EnableRaisingEvents = true }; if (wic != null) wic.Undo(); CloseHandle(admin_token); }
服务器之间的双跳可能导致服务凭据被丢弃,可能设置Kerberos将解决此问题。
0xc0000142
(-1073741502)是STATUS_DLL_INIT_FAILED:
动态链接库[名称]的初始化失败。 该过程exception终止。
正如TenaciousImpy网站指出的那样,您需要将帐户权限授予窗口站和桌面。 但如果程序是交互式的,则还需要设置进程令牌的会话ID。