I get exit code "1", when run a process on IIS - c#

I want to call an .exe that is on my Windows machine. I publish the site to a folder inside "C:\inetpub\wwwroot" and can call the API from outside. Problem is when I run the code from VS on IIS Express the exit code of the process is 0 and the exe is executed successfully, but when I call the Action Result from outside and it runs on the IIS the status code is 1 and there is obviously a problem with this process calling: Here is my code:
public async Task<ActionResult> url2img(string url)
{
Process proc = new Process();
proc.StartInfo.FileName = #"C:\Program Files\wkhtmltopdf\bin\wkhtmltoimage.exe";
proc.StartInfo.Arguments = $"--encoding utf-8 \"{url}\" {FilePath}";
proc.Start();
proc.WaitForExit();
object oJSON = new { procStatusCode = proc.ExitCode };
proc.Close();
return Json(oJSON, JsonRequestBehavior.AllowGet);
}
I found this thread, and read the proposed answer by the OP, but I cannot find "load windows profile" in my IIS and also I am not sure if this is the same issue as his? Any help?

I ran the sample and ExitCode is no longer valid after calling Close(). Hence the invalid operation.

I think, your iis user does not have privileges. may be you want to examine this link:Foo.cmd won't output lines in process (on website)

I had to set the Identity of the DefaultAppPool to LocalSystem

Related

Running command from ASP.NET App Pool Identity

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.

psexec via Process gives different exitcode than psexec via cmd

I'm currently working on an application that checks whether a APP with a certain name exist on an IIS server. I use PsExec to execute this command.
While I was testing this through the command line, I noticed that when an APP does not exist the appcmd exits with ExitCode 1. Likewise it exits with 0 when an APP does exist.
I wanted to use this behavior too so I don't need to do output redirection. I only care about whether the APP exists or not. PsExec uses the exitcode of the command it calls as its own exitcode. I tried this with the command line and checked the result with echo %errorlevel% and it works just fine.
But I run into a problem with the following code.
Process process = new Process();
process.StartInfo.FileName = #"psexec";
string appcmd = #"C:\windows\system32\inetsrv\appcmd";
process.StartInfo.Arguments = String.Format(#"{0} -u {1} -p {2} -S {3} LIST APP ""{4}""",
ip, username, password, appcmd, appname);
process.Start();
process.WaitForExit();
Console.WriteLine(process.ExitCode);
This executes just fine. But it does not return the exitcode that PsExec (should?) gives. It always returns 0. So now I can't use the trick I found earlier to check whether an APP exists or not.
I there a known solution for this? Is there a similar solution? Or should I go with output redirection?
Not really a solution to the problem. But because web applications in IIS must have a unique name, creating an application that already exists will result in an error but nothing will have changed.
This means that it works perfectly fine if I always try to create a new APP. If it doesn't exist it will be made, if it already exists nothing will happen.

Running bat file on IIS server

I'm trying to run a .bat file on a windows server 2008 R2 64bit with IIS version 6.1 SP1.
On my local machine everything goes well but on server nothing happens, except for a process that gets created (cms.exe *32).
From my search the main problem is permissions. I read in several places that IIS for default blocks access to batch files for security reasons. I do understand the problem but in my case there would be no security issue so i would like to still run my file.
The solutions i found passed by implementing impersonation which means:
Change web.config
-> identity impersonate="true"
Change IIS Site Authentication
-> ASP.NET Impersonation Enabled
Give permissions to the file and folders
Even tried a different version of step 1
-> identity impersonate="true" userName=**********
Give permissions to the IIS User:
set allow service to interact with desktop on the IIS Admin Service
To call the batch i use the following code in C#:
private void StartPervasive(string npu)
{
try
{
ProcessStartInfo startInfo = new ProcessStartInfo(ConfigurationManager.AppSettings.Get("PervasivePath"));
//startInfo.UseShellExecute = true;
//startInfo.WorkingDirectory = ConfigurationManager.AppSettings.Get("PervasiveWorkingPath");
//startInfo.WindowStyle = ProcessWindowStyle.Normal;
//startInfo.RedirectStandardInput = true;
//startInfo.RedirectStandardError = true;
//startInfo.RedirectStandardOutput = true;
//startInfo.FileName = ConfigurationManager.AppSettings.Get("PervasivePath");
startInfo.Arguments = npu;
Process myProcess = Process.Start(startInfo);
//StreamReader sr = File.OpenText(ConfigurationManager.AppSettings.Get("PervasivePath"));
//StreamWriter sw = myProcess.StandardInput;
//while (sr.Peek() != -1)
//{
// string readed = sr.ReadLine();
// readed = readed.Replace("%1", npu);
// sw.WriteLine(readed + Environment.NewLine);
//}
//myProcess.WaitForExit();
//myProcess.Close();
}
catch (Exception ex)
{
throw ex;
}
}
It should also be of note that i tried to execute other files including .exe files but with no results.
Would appreciate any advice, help and or corrections to the steps described.
This may not be what your looking for, but may help. I would suggest you create a Scheduled Task on the Server to run the BAT file, you can set the User Permissions and then schedule when you wish to run it.
Hope this helps.
Below is a link to another Stackoverflow article that appears to have a very detailed response to the same problem.
IIS7 does not start my Exe file...

How to start the bat-file at Asp.net web server side?

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.

Can I stop an IIS?

In a .NET windows application to to modify a remote machine config file that is used by an ASP.NET application. However, I keep getting the error:
System.IO.IOException: The process cannot access the file '[file name]' because it is being used by another process.
Now, this may not be the problem, but I'm figuring that if I can stop the IIS, then I can modify the machine config file (without getting the exception), and then I can restart the IIS using this code:
Process proc = new Process();
proc.EnableRaisingEvents = false;
proc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
proc.StartInfo.FileName = "iisreset";
proc.StartInfo.Arguments = serverName;
try
{
proc.Start();
proc.WaitForExit();
...
1) Is there a way to stop the IIS without restarting it, and 2) Doe this approach to changing the server.config file even make sense?
(note, I am modifying the file with regular expressions search and replace; is this a problem?)
You should be able to do something like this. I don't have windows, so I can't check the exact name of the service, but I think it is "IISADMIN" or "w3svc". Remember this should be the service name and not the display name you see in the service control panel.
ServiceController controller = new ServiceController();
controller.MachineName = "."; // or the remote machine name
controller.ServiceName = "IISADMIN"; // or "w3svc"
string status = controller.Status.ToString();
// Stop the service
controller.Stop();
// Start the service
controller.Start();
You can also use
net stop w3svc
or
net stop IISADMIN
from the commandline or in your process in your code
Strange. A .config file should not be locked exclusively.
But to answer your question, you can also use the net command for this:
net stop w3svc
to stop the www service, and
net start w3svc
to start it again.
You can also do this programmatically as described by #monkeyp
Note that I would advice against this and first try to determine (and resolve) the cause of the lock as described by #RichardOD.
Using System.Diagnostics;
//to stop ISS
ProcessStartInfo startInfo = new ProcessStartInfo("iisreset.exe", " /stop");
System.Diagnostics.Process.Start(startInfo);
//to start ISS
ProcessStartInfo stopInfo = new ProcessStartInfo("iisreset.exe", " /start");
System.Diagnostics.Process.Start(stopInfo);
You can use the IISRESET /STOP command.
If you type IISRESET /? you will get a list of other available options.
[Edit: Pass the "/STOP" switch as the arguments property on the process' startinfo object.]
Should be "iisreset /STOP" to stop the services, then "iisreset /START" to restart them.
Use a tool like wholockme or unlocker to find the root cause of the locking.
Update- another option is to use Process Explorer (thanks fretje)- this is a good option as lots of developers have this utility on their PC.
You can often just recycle or stop/start the Application Pool IIS is running, rather than restarting IIS altogether.

Categories

Resources