I am running an executable process from my ASP.NET application when a user clicks a button. This process creates several files and serves them up to the end-user. I can't really see what the process is or isn't doing, but it didn't work until I specified the admin user as the application pool identity on the server. I am using IIS7.
using (var proc = new Process())
{
proc.StartInfo.FileName = Server.MapPath("~/Testing/Demo/MyExe.exe");
proc.StartInfo.Arguments = String.Format("\"{0}\"", commandFilePath);
proc.StartInfo.UseShellExecute = true;
proc.Start();
proc.WaitForExit();
}
I'm assuming that this is generally a bad thing to do. Can you give me insight into what needs to be done in order to enable this for the normal ApplicationPoolIdentity account?
Thanks!
First of all, why you need the Shell to execute it ? Isn't a console application - do you open any window ?
Second you need to redirect the input and the output.
And final, what you need to do, is to place on the directory that your script runs, permission for the user under witch your pool is run. And remove the Admin from your pool.
proc.StartInfo.UseShellExecute = false;
proc.StartInfo.CreateNoWindow = false;
proc.StartInfo.RedirectStandardError = true;
proc.StartInfo.RedirectStandardOutput = true;
proc.StartInfo.RedirectStandardInput = true;
proc.Start();
proc.StandardInput.Flush();
proc.StandardInput.Close();
proc.WaitForExit();
proc.Close();
So for example, if you add your pool to run under the UserA, then go to your directory that your program runs and add permission for the UserA to been able to execute programs on that directory. If your program also use other directories to read and write, also add permission to the UserA for that ones.
I can't really see what the process is or isn't doing
You can take a look if you use on the server the Process Explorer and see if its runs, if its close, if its stop but stay there.
It is likely a file/execution permissions issue.
Try granting execute permissions to the ApplicationPoolIdentity to ~/Testing/Dema/MyExe.exe and read permissions to commandFilePath. You mentioned that your process creates files. You will need to grant either modify or full control permissions to the ApplicationPoolIdentity on the folder where the files will be created. Here is a matrixed list of permissions.
See assign permissions to ApplicationPoolIdentity account for information on granting permissions.
The security event log should capture permission denied errors. Check there to see if you have access permission issues. The System and application logs might also contain information on the problem.
Process Explorer can also show File Access requests. Here is a technet article on troubleshooting with Process Explorer.
Whenever you run any process from an ASP.NET page, it runs under the security context of the worker process, the privilege of your app pool account. It is not like you normally running the MyExe.exe, in that case it will run using logged in account. It is because of this, your code worked when you gave Admin account to app pool.
There are many ways to solve this issue.
One of the easiest would be to change your app pool identity to Network Service and add the Network Service to permissions of the folders in which the MyExe.exe will be accessing files form.
Hope it helps.
Thank you all for your help. All I needed to do was set the StartInfo.WorkingDirectory to somewhere that I was able to write.
using (var proc = new Process())
{
proc.StartInfo.FileName = Server.MapPath("~/Testing/Demo/MyEXE.exe");
proc.StartInfo.Arguments = String.Format("\"{0}\"", commandFile);
proc.StartInfo.WorkingDirectory = savePath;
proc.Start();
proc.WaitForExit();
}
This causes the temp files to be written to a non-system folder and thus does not need any elevated permissions for the application pool.
Related
I'm using Pdf2Text in an ASP.NET web app. The web interface allows PDF files to be uploaded and converted to text. To convert to text, I use the C# function below, which relies on running the Pdf2Text program via the Process library.
void ExtractOCR(string input, string output)
{
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.CreateNoWindow = true;
startInfo.UseShellExecute = true;
startInfo.FileName = Server.MapPath("ocr/Pdf2Text.exe");
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
startInfo.Arguments = input + " " + output;
Process exeProcess;
using (exeProcess = Process.Start(startInfo))
{
exeProcess.WaitForExit();
}
}
I've double-checked that the input and output paths are all valid. However, when I run the web app, I get the following error.
I've tried the Just-In-Time debugger but it won't even run for some reason. The Pdf2Text is a precompiled file, I don't have it's source code. I believe this is the file's download site, but not 100% sure. I've checked online to find solutions to similar errors but none has worked.
Thank you #GraDea for suggesting to look into the pool's permissions into the web app directory, this was the solution.
The web app was located at a custom location (not the default ASP server directory of inetpub\wwwroot). After the suggestion, I tried adding the pool user to the web app's custom location, but that didn't seem to work. Next, I moved the web app to the inetpub\wwwroot location and added the pool user to the folder, restarted the site via IIS and everything is now back to normal.
For future reference to anyone, easiest fix to a similar problem is to make sure your web app is in the default IIS server directory, and that your site pool's username is added to the application folder's security permissions. I've not tried the fix for a custom location because it's not so important for me, but I'm guessing it will most likely also involve adding the necessary IIS default pool users (e.g. IIS_IUSRS) and the site pool's user.
I have developed a c# application to download a zip file from a site, when manually run the app, it does its job normally and exits, But when i schedule it to run automatically using task scheduler in Windows, it throws web client exception error. Please help me regarding this
The part of code for downloading the file is
WebClient wc = new WebClient();
wc.DownloadFile(<site>, "feed.zip");
System.Diagnostics.ProcessStartInfo pinfo = new System.Diagnostics.ProcessStartInfo("extract.bat");
System.Diagnostics.Process process = new Process();
pinfo.CreateNoWindow = true;
pinfo.WorkingDirectory = Directory.GetCurrentDirectory();
process.StartInfo = pinfo;
process.Start();
process.WaitForExit();
The batch file extracts the zip file.
I see these possible problems:
If you run your application Directory.GetCurrentDirectory() could result in a different path. Directory.GetCurrentDirectory() will be set to your bin-folder, but in your production environment, it can point every, depending how your process is executed (for example: if you create a shortcut on your desktop, you can also modify the Start in-folder.
If your current directory is configured wrong, the application would also not be able to find extract.bat.
While you are debugging you have some rights on your outputfolder. But when your application is executed as a batch process, it runs under a different account. Does this account have to rights to write to your output folder?
The website your are accessing might require a valid account. You possibly have a valid account. But the account your application is running from in production, might not be valid account for that website.
You are possibly behind a proxy. Perhaps you need to configure some extra settings for getting past that proxy. In your account, these settings are configured inside Internet Explorer. Perhaps the production account does not have these settings configured.
I need to call a console application to load data into another desktop application on the remote server that located within the corporate domain.
Users will enter the web page and upload data to asp.net web server, which after transformation should call that console application. Users are located remotely and do not have any other access except the web server.
I decided to lower the security web application context and let the asp.net working process to start the console application on the current IIS 6.0 web server
What I have done:
I changed the security account for the application pool for Local System;
I added ASPNET Account and IIS_WPG IIS Process Account to Administrators group;
I added “Allow service to interact with desctop” for “IIS Admin Service” and “World Wide Web Publishing Service” processes and restarted the machine;
I tried to start BAT-file at server side through the test page code-behind, but failed:
protected void btnStart_Click(object sender, EventArgs e)
{
Process process = new Process();
process.StartInfo.FileName = #”C:\run.bat”;
process.StartInfo.UseShellExecute = false;
process.Start();
process.WaitForExit();
}
The error was access denied.
Please help me to find any workable idea how to start the bat-file at web server side.
Thanks
Try setting UseShellExecute to true instead of false. After all, batch files run in a shell - so you need a shell to execute it. (Another option is to run cmd.exe and pass the name of the batch file in as an argument, e.g. "cmd.exe /k c:\run.bat")
You might also want to try creating a simple .NET app which just (say) creates a file with a timestamp in. That way you can test the "can I start another process" bit separately from the "can I get the batch file to work" bit.
Put that particular batch file in your application itself.
string str_Path = Server.MapPath(".") + "\\run.bat";
ProcessStartInfo processInfo = new ProcessStartInfo(str_Path);
processInfo.UseShellExecute = false;
Process batchProcess = new Process();
batchProcess.StartInfo = processInfo;
batchProcess.Start();
Take a look at this example: Run Interactive Command Shell or Batch Files From ASP.NET
It uses little different approach. They suggest running cmd.exe and executing command line by line.
Is it possible to require administrator rights for one single method?
Something like this:
[RequireAdminRightsForThisMethod()]
private void TheMethod(){
// Do something
}
You can add a PrincipalPermission attribute to your method to demand administrative privileges for its execution:
[PrincipalPermission(SecurityAction.Demand, Role = #"BUILTIN\Administrators")]
public void MyMethod()
{
}
This is described in more detail in the following article:
Security Principles and Local Admin Rights in C# .Net
If you are looking for a way to elevate an already existing process I doubt that this is possible as administrator privileges are given on process-level to a process upon startup (see this related question). You would have to run your application "as administrator" to get the desired behavior.
However, there are some tricks that might allow you to do what you want, but be warned that this might open up severe security risks. See the following thread in the MSDN forums:
Launching MyElevatedCom Server without prompting Administrator credentialls from Standard User
Update (from comment)
It seems that if an update requires elevation your application update is best done by a separate process (either another executable, or your application called with a command line switch). For that separate process you can request elevation as follows:
var psi = new ProcessStartInfo();
psi.FileName = "path to update.exe";
psi.Arguments = "arguments for update.exe";
psi.Verb = "runas";
var process = new Process();
process.StartInfo = psi;
process.Start();
process.WaitForExit();
A method can require administrative privileges to run, but it's not possible to automatically elevate to Admin when executing a method.
I'm trying to install a service using InstallUtil.exe but invoked through Process.Start. Here's the code:
ProcessStartInfo startInfo = new ProcessStartInfo (m_strInstallUtil, strExePath);
System.Diagnostics.Process.Start (startInfo);
where m_strInstallUtil is the fully qualified path and exe to "InstallUtil.exe" and strExePath is the fully qualified path/name to my service.
Running the command line syntax from an elevated command prompt works; running from my app (using the above code) does not. I assume I'm dealing with some process elevation issue, so how would I run my process in an elevated state? Do I need to look at ShellExecute for this?
This is all on Windows Vista. I am running the process in the VS2008 debugger elevated to admin privilege.
I also tried setting startInfo.Verb = "runas"; but it didn't seem to solve the problem.
You can indicate the new process should be started with elevated permissions by setting the Verb property of your startInfo object to 'runas', as follows:
startInfo.Verb = "runas";
This will cause Windows to behave as if the process has been started from Explorer with the "Run as Administrator" menu command.
This does mean the UAC prompt will come up and will need to be acknowledged by the user: if this is undesirable (for example because it would happen in the middle of a lengthy process), you'll need to run your entire host process with elevated permissions by Create and Embed an Application Manifest (UAC) to require the 'highestAvailable' execution level: this will cause the UAC prompt to appear as soon as your app is started, and cause all child processes to run with elevated permissions without additional prompting.
Edit: I see you just edited your question to state that "runas" didn't work for you. That's really strange, as it should (and does for me in several production apps). Requiring the parent process to run with elevated rights by embedding the manifest should definitely work, though.
This code puts the above all together and restarts the current wpf app with admin privs:
if (IsAdministrator() == false)
{
// Restart program and run as admin
var exeName = System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName;
ProcessStartInfo startInfo = new ProcessStartInfo(exeName);
startInfo.Verb = "runas";
System.Diagnostics.Process.Start(startInfo);
Application.Current.Shutdown();
return;
}
private static bool IsAdministrator()
{
WindowsIdentity identity = WindowsIdentity.GetCurrent();
WindowsPrincipal principal = new WindowsPrincipal(identity);
return principal.IsInRole(WindowsBuiltInRole.Administrator);
}
// To run as admin, alter exe manifest file after building.
// Or create shortcut with "as admin" checked.
// Or ShellExecute(C# Process.Start) can elevate - use verb "runas".
// Or an elevate vbs script can launch programs as admin.
// (does not work: "runas /user:admin" from cmd-line prompts for admin pass)
Update: The app manifest way is preferred:
Right click project in visual studio, add, new application manifest file, change the file so you have requireAdministrator set as shown in the above.
A problem with the original way: If you put the restart code in app.xaml.cs OnStartup, it still may start the main window briefly even though Shutdown was called. My main window blew up if app.xaml.cs init was not run and in certain race conditions it would do this.
According to the article Chris Corio: Teach Your Apps To Play Nicely With Windows Vista User Account Control, MSDN Magazine, Jan. 2007, only ShellExecute checks the embedded manifest and prompts the user for elevation if needed, while CreateProcess and other APIs don't. Hope it helps.
See also: same article as .chm.
[PrincipalPermission(SecurityAction.Demand, Role = #"BUILTIN\Administrators")]
This will do it without UAC - no need to start a new process. If the running user is member of Admin group as for my case.
i know this is a very old post, but i just wanted to share my solution:
System.Diagnostics.ProcessStartInfo StartInfo = new System.Diagnostics.ProcessStartInfo
{
UseShellExecute = true, //<- for elevation
Verb = "runas", //<- for elevation
WorkingDirectory = Environment.CurrentDirectory,
FileName = "EDHM_UI_Patcher.exe",
Arguments = #"\D -FF"
};
System.Diagnostics.Process p = System.Diagnostics.Process.Start(StartInfo);
NOTE: If VisualStudio is already running Elevated then the UAC dialog won't show up, to test it run the exe from the bin folder.
You should use Impersonation to elevate the state.
WindowsIdentity identity = new WindowsIdentity(accessToken);
WindowsImpersonationContext context = identity.Impersonate();
Don't forget to undo the impersonated context when you are done.