I'm trying to start a .NET application under a different user from a .NET service. The idea is to create a sandboxed hosting application in windows. In the service, I programatically created the user in windows, create a folder for that user, and download the host .exe from a server into that folder. I then I run the host .exe using System.Diagnostics.Process. Here is the StartInfo for the process:
_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
};
When I run the service as a SERVICE, the process crashes instantly with an error code of -1073741502. but when I run the service as the same user specified in the windows service but interactively in the console, everything works fine. This only happens whenever running the service as a SERVICE and not directly in the console.
Any help would be MUCH appreciated. This has been a headache for a long time now and this is a last resort :(
It seems like using the new Process()
with a username and password and the Service mode "doesn't compute" :)
Quote from MSDN:
You can change the parameters
specified in the StartInfo property up
to the time that you call the Start
method on the process. After you start
the process, changing the StartInfo
values does not affect or restart the
associated process. If you call the
Start(ProcessStartInfo) method with
the ProcessStartInfo..::.UserName and
ProcessStartInfo..::.Password
properties set, the unmanaged
CreateProcessWithLogonW function is
called, which starts the process in a
new window even if the CreateNoWindow
property value is true or the
WindowStyle property value is Hidden.
Furthermore, looking at the CreateProcessWithLogonW documentation:
lpStartupInfo [in]
A pointer to a STARTUPINFO structure. The application must add
permission for the specified user
account to the specified window
station and desktop, even for
WinSta0\Default.
If the lpDesktop member is NULL or an empty string, the new process
inherits the desktop and window
station of its parent process. The
application must add permission for
the specified user account to the
inherited window station and desktop.
There is no lpDesktop in the .NET StartupInfo, on the other hand the SERVICE user has no desktop, which could cause your problem.
Long story short, try to set the LoadUserProfile
to true
to load the user's information from the registry, or maybe you need to set the working directory, etc.
To further investigate, your should check your environment and maybe log which files are accessed using FileMon.
I would try to create the process under the impersonated context of the newly created user as below.
[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);
}
A double hop between servers may cause the service credentials to get dropped, maybe setting up Kerberos would solve this issue.
http://neverknewthat.wordpress.com/2009/05/14/kerberos/
0xc0000142
(-1073741502) is STATUS_DLL_INIT_FAILED:
Initialization of the dynamic link library [name] failed. The process is terminating abnormally.
As the website TenaciousImpy gave pointed out, you need to give the account permissions to the window station and desktop. But if the program is interactive, you need to set the session ID of the process token as well.