I can not call Process.Start("DocToPDF.exe", "file.docx file.pdf") successfully from IIS.
I have tried allowing desktop interaction from IIS Admin Service;
I have tried granting full control permissions to DefaultAppPool for the directory containing the DocToPDF.exe
None of this worked. The DocToPDF.exe exits with code: 1 (I write the exit code to a file...). When I run the website in debug mode (F5) the program exits with code: 0 and everything is ok. It works perfectly well in debug mode. My guess is it has something to do with IIS permissions or something like that because as I said it works well when launching the application from visual studio.
Here is the method that I am using:
public byte[] DocToPdf(MemoryStream ms)
{
string fileName = Guid.NewGuid().ToString();
string path = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + "\\" + fileName + ".docx";
string newPath = path.Replace("docx", "pdf");
FileStream fs = new FileStream(path.ToString(), FileMode.OpenOrCreate);
fs.Write(ms.ToArray(), 0, ms.ToArray().Length);
fs.Close();
Process p = new Process();
p.StartInfo.UseShellExecute = false;
p.StartInfo.FileName = #"C:\Utils\OfficeToPDF.exe";
p.StartInfo.Arguments = path + " " + newPath;
p.Start();
p.WaitForExit();
System.IO.File.WriteAllText(#"C:\Utils\exitcode.txt", p.ExitCode.ToString());
var bytes = System.IO.File.ReadAllBytes(newPath);
System.IO.File.Delete(path);
System.IO.File.Delete(newPath);
return bytes;
}
It is almost always a horrible idea to call any process from an IIS web site/application.
IIS and its worker processes run in session 0. The session isolation can lead to issues if the extra executable requires to be run in a user session. (It is very likely that you hit this, as if the executable attempts to use printing drivers it will hit problems under session 0.)
IIS worker processes are running under application pool identities (without user profile loading if you don't change pool settings). That kind of identities can also lead to failures as the executable might require a normal user account.
There are far too many executable fail to run under IIS, so yours is not something new or uncommon.
Meanwhile, when you hit F5 in Visual Studio, your app is running under ASP.NET Development Server, or IIS Express by default, and that's in your user session. Anything works there can break when switching to IIS. So don't be surprise how little you understand about IIS/Windows. Every experts were beginners.
Typical workaround is to find an alternative way that either supported or recommended by Microsoft or a third party vendor. Note that free and open source things are usually developed or tested without such session 0 case in mind, and they can lead to more issues than you thought.
Related
I have an ASP.NET application that is already deployed in an Azure virtual machine. The situation is as follows:
This application, OCREngine, is deployed on the server along with other 3rd party applications. OCREngine is executed on the server by using a service reference to the web service. It runs fine most of the time. But there is one exception: one of the branches of execution won't run the program it needs to run. Both of the branches have to run a program (both are being run in the same way), but one works and the other one doesn't.
This one works: CleanJPEG.exe
proc = new System.Diagnostics.Process();
proc.StartInfo.FileName = "CleanJPEG.exe";
proc.StartInfo.Arguments = "\"" + tempPages + "Color Info.JPEG\"";
proc.StartInfo.UseShellExecute = false;
proc.StartInfo.CreateNoWindow = true;
proc.Start();
And this one doesn't: cpctool.exe
proc = new System.Diagnostics.Process();
proc.StartInfo.FileName = "cpctool.exe";
proc.StartInfo.Arguments = "\"" + file + "\" -o \"" + tempPages + "page.tiff\"";
proc.StartInfo.UseShellExecute = false;
proc.StartInfo.CreateNoWindow = true;
proc.Start();
They are both in the same folder, which has full permissions for the AppPool and so does %TEMP%.
If I run the application from the server, everything works fine. But when I run it through the web service, an instance of cpctool.exe gets created (can be seen on Background processes in the task manager) but it doesn't do it's job. And thus the execution of OCREngine never finishes.
This last part is what made me think it was a problem with permissions, but I don't know what else to give permissions to.
I run Folder Changes View on cpctool.exe and it showed access to the folder where the files are stored and one file being saved in %TEMP% (which, funny enough, doesn't appear when running Folder Changes View on the server).
Can anyone think of any special folder that needs permission that I might be forgetting?
You are completely correct to concentrrate on the permissions as that is usually the issue.
If an EXE process starts and does nothing, then it's probably only made for interactive use, and is prompting for something.
Looking at this page it says:
The FIRST TIME the CPCTool.exe runs the user is prompted to read/accept a User Agreement from Cartesian – this agreement MUST be accepted or the converter will not work.
I reckon that's what it's doing. Try logging in as the application pool user, start the program and accept the agreement.
I am trying to run an antivirus scan on an uploaded file in an ASP.Net web app. We are using Sophos so have access to their command line API sav32cli. In the code I use:
Process proc = new Process();
proc.StartInfo.FileName = #"C:\Program Files (x86)\Sophos\Sophos Anti-Virus\sav32cli.exe";
proc.StartInfo.Arguments = #"-remove -nc " + SavedFile;
proc.StartInfo.Verb = "runas";
proc.Start();
proc.WaitForExit();
int exitCode = proc.ExitCode;
When stepping through the code, when attached to the w3wp process on dev server, the code just jumps from one line to the next seemingly doing nothing at all. When running from code on dev server, it performs as expected scanning file and deleting if it is seen as a virus.
The server is running IIS 8.0, and the app built in .Net Framework 4. I have changed the machine config to allow the process to run as SYSTEM account, in accordance to these instructions. https://support.microsoft.com/en-us/kb/317012#%2Fen-us%2Fkb%2F317012
<processModel userName="SYSTEM" password="AutoGenerate" />
Is there something I'm missing? What is the best practice for this kind of implementation?
EDIT: When called, the Process returns an ExitCode of 2 (Error stopped execution), rather than the expected 0 (Scan worked, no viruses), or 3 (Scan worked, viruses found).
EDIT 2: As per comment below I changed the code to:
Process proc = new Process();
proc.StartInfo.FileName = #"C:\Program Files (x86)\Sophos\Sophos Anti-Virus\sav32cli.exe";
proc.StartInfo.Arguments = #"-remove -nc " + SavedFile;
proc.StartInfo.RedirectStandardOutput = true;
proc.StartInfo.UseShellExecute = false;
proc.Start();
StringBuilder output = new StringBuilder();
while (!proc.StandardOutput.EndOfStream)
{
string line = proc.StandardOutput.ReadLine();
output.AppendLine(line);
}
proc.WaitForExit();
int exitCode = proc.ExitCode;
ASPxMemo2.Text = exitCode.ToString() + Environment.NewLine + output.ToString();
output is always empty when run over IIS, but is populated correctly when running from code.
EDIT 3: Instead of looking at StandardOutput we looked at StandardError and it revealed this error:
Error initialising detection engine [0xa0040200]
(Possible insufficient user Admin rights.)
For the time being we are going to move to another method of virus checking, but would still like to know a possible solution if anyone has it.
You will need to make sure that the application pool that is running your .NET application inside IIS has execute permissions to your file
"C:\Program Files (x86)\Sophos\Sophos Anti-Virus\sav32cli.exe"
You may also need to add this permission to the folder location where the file to be scanned is uploaded (c:\temp) for example
You may also need to have administrator privileges to run the anti virus scan since IIS8 does not run as an administrator. When you are debugging visual studio uses your current logged in windows user(unless you use runas) so this will explain why it would work when debugging.
Have you tried running your web process in elevated trust?
Configuring .NET Trust Levels in IIS 7
<system.web>
<securityPolicy>
<trustLevel name="Full" policyFile="internal"/>
</securityPolicy>
</system.web>
ASP.NET Trust Levels and Policy Files
Most likely the permissions are not configured correctly on the content being scanned (the uploads folder) or the worker process user doesn't have the full permissions it needs to use Sophos. You know the executable itself is accessible by the worker process because you are getting exit codes and error messages that are specific to Sophos.
Because your process will delete files that are perceived as threats you need to grant the user running the process modify or full control permissions on the folders that store the uploaded files.
By default you could use the IIS_IUSRS group for ApplicationPoolIdentity processes, but you can verify (and modify) the user in IIS Manager > App Pools > Advanced.
This answer has more details
Here are some ideas:
Create the process using a different user with elevated privileges on the folder, see for reference start-a-net-process-as-a-different-user
If the previous suggestion fails, login one time on the server using the credentials used in point 1. It will configure registry entries connected to the user profile, some programs requires it.
Develop a simple .net service running on the server and monitoring the upload folder. The service has more probability running the Sophos scan succesfully. Here is a reference on service creation using .net.
The service may also talk to your web page using DB/file system/ etc.. so the operation may seem synchronous.
These are my 4 cents :-)
I made new project (ASP.NET MVC Web Application) using Visual Studio Web 2013 Express Edition. Loading index page, redirects and everything works fine, except that in some part of my code I need to create Process and execute it, wait for it to finish, parse output of that external application and show that output to the user. However I get nothing. While debugging the code line by line:
ProcessStartInfo info = new ProcessStartInfo();
info.FileName = Tool;
info.Arguments = filename + " " + avArray;
info.CreateNoWindow = true;
info.UseShellExecute = false;
info.RedirectStandardOutput = true;
Process p = new Process();
p.StartInfo = info;
p.Start();
p.WaitForExit();
Process exits immediately, someone would say it is pretty fast program, but application needs at least 5 seconds (sometimes 20 seconds) to complete.
What I think is happening is that process is not created in the first place, as my IIS settings or whatever other settings are not allowing me to run this EXE. What do I do to change this?
I've been trying to this for the past 2 weeks, I've read probably every post about it, and tried every solution suggested. I am choosing to write on this post since it is the most recent.
First of all, I am using VS2013, testing on IIS Express, and then on IIS 8.5., the webpages version is 3, and the target framework 4.5. And I am assuming that (as with my case) the goal is to launch the process on the server.
What I learned:
Using IIS Express should allow you to run the process without problems. You can try to allow it to launch the window, or start your process through the shell just to be sure that it is actually launching (a shell window should popup and close). If this happens, verify that you are giving the correct path to to your program, etc. So far so good.
Going into the IIS 8.5 is a totally different matter. Theoretically, the bad way of doing it should be preatty straight-forward: you create an app-pool for that server, give it a high privileged account (local system or network system, for instance); go to AdministrativeTools->Services->IIS, LogOn tab, and allow interaction with the desktop. You should be able to do the same as in IISExpress, but in my case is just the same as with a low privilege account.
I actually started by trying just to use impersonation, but also was not able to launch the process with IIS8.5. EDIT: I retried this again today, and the api won't even run if I enable impersonation.
I've spent more time than I would like with this, any input on why I can't get this to work properly with IIS8.5 (#clzola: IIS Express should do the job) is very welcome.
We have a .exe which we need to execute at the time an order is placed on a website. When
we test this locally it works fine using IIS Express. When we move it to IIS, it fails. We assume this is a permissions error as if we set the App Pool to run as the administrator then the script works again. The question we have is how do we execute the .exe as the administrator whilst the App Pool is ApplicationIdentity? We are using the following code:
var process = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = executablePath,
Arguments = argumentList,
Domain = domain,
UserName = userName,
Password = securePassword,
UseShellExecute = false,
LoadUserProfile = true
}
};
process.Start();
process.WaitForExit();
process.Close();
The .exe is trying to write to the Users AppData folder which is why it fails. It is a 3rd party app so we cannot change the source code.
EDIT: Just to clarify also, when we specify the username and password in procmon it still appears to run from ISUR.
We fixed this by enabling User profile on IIS AppPool and setting permission for the IIS user on the folder it was trying to write to.
We sue ProcMon to find where the program was failing and the folder it was trying towrite to was C:\Windows\System32\config\systemprofile
i dont remember actually, but one of them is working 100% ( i had this issue before)
just let me know ehich one of them is the correct one.
How to execute EXE file on Windows 2008 using ASP.NET and IIS7? I have tried to run code below but it seems do not work. The code is executed without any error but I do not see Notepad in Processes list. Everything works fine if I use ASP.NET developer server but not with IIS7.
string enginePath = "notepad";
var password = new System.Security.SecureString();
foreach (char character in ConfigurationManager.AppSettings["Credentials"])
password.AppendChar(character);
var p = new Process
{
StartInfo =
{
FileName = enginePath,
UseShellExecute = false,
}
};
p.StartInfo.UserName = "Administrator";
p.StartInfo.Password = password;
p.Start();
In response to security concerns Microsoft has continually increased the isolation of the IIS process such that you can not (or I have not found a work around which will allow you to...) invoke anything outside the IIS application domain directly. You can build a Windows service which can use WCF channels to cross that boundary indirectly. That service (configured to be allowed to interact with the desktop) can in turn launch your Notepad.exe.
It is a bit of a kludge to make it happen and I will certainly be interested to see if someone else has a better answer.
I have removed lines below and it suddenly started working. I can't explain how it is possible to run exe under IIS7 account but it is working.
p.StartInfo.UserName = "Administrator";
p.StartInfo.Password = password;