Reputation: 3954
I have an ASP.NET MVC4 website where I'm trying to execute a process on the server. The code is as follows:
ProcessStartInfo startInfo = new ProcessStartInfo()
{
FileName = ExeLocation,
Arguments = string.Format("\"{0}\"{1}", ScriptLocation, Arguments),
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true,
WorkingDirectory = AppDir,
CreateNoWindow = true,
UserName = ExeUsername,
Password = ExePassword,
Domain = ExeDomain
};
using (Process process = Process.Start(startInfo))
{
using (StreamReader reader = process.StandardOutput)
{
output = reader.ReadToEnd();
}
using (StreamReader reader = process.StandardError)
{
error = reader.ReadToEnd();
}
process.WaitForExit();
if (process.ExitCode != 0)
{
throw new Exception(string.IsNullOrEmpty(output) ? error : output);
}
}
This works fine on my local machine in Visual Studio, but when I deployed to my server (W2K12) I get the following error:
Access is denied
at System.Diagnostics.Process.StartWithCreateProcess(ProcessStartInfo startInfo)
I have the account referenced by ExeUsername
in both the Administrators and IIS_IUSRS groups on the server.
The application pool is running as a different account (hence the need to assign a specific account to run the process) which is also a member of Administrators and IIS_IUSRS on the server.
When I log into the server and run a command prompt as ExeUsername
, I am able to execute the process, so the issue must be related to executing from IIS.
What else could be blocking this access?
Upvotes: 5
Views: 2631
Reputation: 192
Maybe using this helps you.
ProcessStartInfo startInfo = new ProcessStartInfo()
{
//...
UseShellExecute = true,
Verb = "runas"
};
If you get an error you can check this also.
Upvotes: 0
Reputation: 3952
I'd try a different approach. Firstly impersonate a custom user (the one that has permission to run a command) and then start a process within the context of impersonated user:
SafeAccessTokenHandle safeAccessTokenHandle;
bool returnValue = LogonUser(ExeUsername, ExeDomain, ExePassword,
LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT,
out safeAccessTokenHandle);
if (false == returnValue)
{
int ret = Marshal.GetLastWin32Error();
throw new System.ComponentModel.Win32Exception(ret);
}
WindowsIdentity.RunImpersonated(safeAccessTokenHandle, () =>
{
var startInfo = new ProcessStartInfo()
{
FileName = ExeLocation,
Arguments = string.Format("\"{0}\"{1}", ScriptLocation, Arguments),
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true,
WorkingDirectory = AppDir,
CreateNoWindow = true,
UserName = ExeUsername,
Password = ExePassword,
Domain = ExeDomain
};
using (Process process = Process.Start(startInfo))
{
using (StreamReader reader = process.StandardOutput)
{
output = reader.ReadToEnd();
}
using (StreamReader reader = process.StandardError)
{
error = reader.ReadToEnd();
}
process.WaitForExit();
if (process.ExitCode != 0)
{
throw new Exception(string.IsNullOrEmpty(output) ? error : output);
}
}
);
And the LogonUser method looks like this:
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern bool LogonUser(String lpszUsername, String lpszDomain,
String lpszPassword, int dwLogonType, int dwLogonProvider,
out SafeAccessTokenHandle phToken);
More info about impersonating in .NET is here: https://learn.microsoft.com/en-gb/dotnet/api/system.security.principal.windowsidentity.runimpersonated?view=netframework-4.7.2
Upvotes: 0
Reputation: 1350
If you have domain be careful use domain\username for username
and also access to folder of deployment.
Upvotes: 1