我正在尝试在.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
};
Run Code Online (Sandbox Code Playgroud)
当我将服务作为SERVICE运行时,进程立即崩溃,错误代码为-1073741502.但是,当我在Windows服务中指定的同一用户运行服务但在控制台中以交互方式运行时,一切正常.只有在将服务作为SERVICE运行而不是直接在控制台中运行时才会发生这种情况.
任何帮助将非常感激.这已经很长一段时间了,这是最后的手段:(
Gyu*_*uri 14
看起来像使用new Process()用户名和密码和服务模式"不计算":)
从MSDN引用:
您可以将StartInfo属性中指定的参数更改为在进程上调用Start方法的时间.启动该过程后,更改StartInfo值不会影响或重新启动关联的进程.如果使用ProcessStartInfo .. ::.UserName和ProcessStartInfo .. ::.密码属性设置调用Start(ProcessStartInfo)方法,则调用非托管CreateProcessWithLogonW函数,即使CreateNoWindow属性值,也会在新窗口中启动该进程为true或WindowStyle属性值为Hidden.
此外,查看CreateProcessWithLogonW文档:
lpStartupInfo [in]
指向STARTUPINFO结构的指针.应用程序必须将指定用户帐户的权限添加到指定的窗口站和桌面,即使对于WinSta0\Default也是如此.
如果lpDesktop成员为NULL或空字符串,则新进程将继承其父进程的桌面和窗口站.应用程序必须将指定用户帐户的权限添加到继承的窗口站和桌面.
.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);
}
Run Code Online (Sandbox Code Playgroud)