2

I've been searching and experimenting all morning with this one and I'm stumped. I have an aspx page running in IIS and calling the following c# function. I'm trying to have it run a cmd file and return the output from the cmd file. I've experimented with the five different options in the code below:

protected String RunMyCmdFileAndGetResponse() {
    Process proc = new Process ();
    proc.StartInfo.FileName = @"c:\Windows\System32\cmd.exe";
//  proc.StartInfo.Arguments = @"/c echo hello";                    <== 1
//  proc.StartInfo.Arguments = @"/c c:\mypath\myfile_badname.cmd";  <== 2
//  proc.StartInfo.Arguments = @"/c type c:\mypath\myfile.cmd";     <== 3
    proc.StartInfo.Arguments = @"/c c:\mypath\myfile.cmd";      //  <== 4
//  proc.StartInfo.Arguments = @"/c call c:\mypath\myfile.cmd";     <== 5
    proc.StartInfo.UseShellExecute = false;
    proc.StartInfo.RedirectStandardOutput = true;
    proc.StartInfo.RedirectStandardError = true;
    proc.StartInfo.CreateNoWindow = true;

    proc.Start();
    string response = proc.StandardOutput.ReadToEnd();
    response += proc.StandardError.ReadToEnd();
    proc.WaitForExit();
    return response;
}

Cmd file c:\mypath\myfile.cmd contents are:

@echo test line 1 > c:\mypath\myfilelog.txt
@echo test line 2

This cmd file works as expected when run manually, producing myfilelog.txt and returning test line 2. When executed with the c# code:

  • Option 1 works - returns 'hello' response as expected.
  • Option 2 fails as expected, indicating myfile_badname.cmd is not recognized as a valid command
  • Option 3 works as expected - it returns the contents of myfile.cmd as the response - this confirms I am able to find and read the file.
  • Option 4 does not work - as near as I can figure, it should. It does not hang up, but also does not return any response at all, and does not execute the cmd file (no myfilelog.txt produced).
  • Option 5 - same results as option 4.

Note - I've also tried modifying myfile.cmd to remove line 1 (creating the log file) and only leave line 2 to echo a response. Just in case it's a permission issue creating the log file. Same result.

Any help would be appreciated!

Updated to add solution:

The answer from @MaxOvrdrv got me thinking a different way. There does indeed appear to be some kind of limitation when running Process.Start within an IIS context with UseShellExecute = false - if the primary argument is an executable file (cmd file, script file, etc), it will not run it. I tried passing SomeExample.cmd to cmd.exe, and SomeExample.js to cscript.exe.

However... I was able to trick it with a level of indirection, such that the executable file name is no longer the first argument, and it works just fine that way.

To run a cmd file:

string theResponse = RunMyCmdAndGetResponse(@"c:\somepath\mycmd.cmd");

protected String RunMyCmdAndGetResponse(string cmdPath) {
    Process proc = new Process ();
    proc.StartInfo.FileName = @"c:\Windows\System32\cmd.exe";
    proc.StartInfo.Arguments = "/c cmd /c " + cmdPath;
    proc.StartInfo.UseShellExecute = false;
    proc.StartInfo.RedirectStandardOutput = true;
    proc.StartInfo.RedirectStandardError = true;
    proc.StartInfo.CreateNoWindow = true;

    proc.Start();
    proc.WaitForExit();
    string response = proc.StandardOutput.ReadToEnd();
    response += proc.StandardError.ReadToEnd();
    return response;
}

To run a script file:

string theResponse = RunMyScriptAndGetResponse(@"c:\somepath\myscript.js");

protected String RunMyScriptAndGetResponse(string scriptPath) {
    Process proc = new Process ();
    proc.StartInfo.FileName = @"c:\Windows\System32\cmd.exe";
    proc.StartInfo.Arguments = "/c cscript //nologo " + scriptPath;
    proc.StartInfo.UseShellExecute = false;
    proc.StartInfo.RedirectStandardOutput = true;
    proc.StartInfo.RedirectStandardError = true;
    proc.StartInfo.CreateNoWindow = true;

    proc.Start();
    proc.WaitForExit();
    string response = proc.StandardOutput.ReadToEnd();
    response += proc.StandardError.ReadToEnd();
    return response;
}
grumpyhoser
  • 108
  • 3
  • 6
  • have you tried this? http://stackoverflow.com/questions/5519328/executing-batch-file-in-c-sharp – MaxOvrdrv Feb 18 '15 at 18:22
  • Sorry i just noticed something... see my answer below. – MaxOvrdrv Feb 18 '15 at 18:29
  • Yes, I looked at those examples this morning. The only functional difference that I see between the top answer there and my example above is that they call WaitForExit before reading StandardOutput and StandardError, whereas I was calling WaitForExit after. i just tried making that change in my example and retested - no joy! – grumpyhoser Feb 18 '15 at 18:33
  • yeah i just noticed that you are trying to do this under an ASPX / AppPool context... that simply will not work. even cmd.exe is considered a UI application and needs a proper User Context to run. – MaxOvrdrv Feb 18 '15 at 18:34
  • Should you also set `StartInfo.RedirectStandardInput` to true? – Laurent Bourgault-Roy Feb 18 '15 at 18:51

2 Answers2

1

Running a batch file or any process per say from an ASPX page is futile as IIS does not run under a true Windows User Context. Because of this, regardless of how many settings and rights you give to the user that the AppPool is running under or whatever type of config changes you make, it simply will never work. I ran into the same problem quite a while back and basically it's impossible.

See my previous questions (and comments), along with accepted answer for possible "conceptual" solution to your current problem, here:

Process.Start won't work

Community
  • 1
  • 1
MaxOvrdrv
  • 1,780
  • 17
  • 32
  • Dang. I also tried to run a test with cscript.exe passing it a js script file and it wouldn't do anything with that either, so it's not exe.cmd specific. I find it interesting that 'some' things do appear to run successfully in this context: - my original option 1 works with cmd.exe. I can also supply the cmd file directly as the Filename with UseShellExecute = true, as @Derek mentions, and that does work also, although I cannot get a response doing it that way. I suppose I could run it Derek's way, have the cmd write the response to a file, then read the file in c#, but that's just ugly! – grumpyhoser Feb 18 '15 at 18:50
  • 1
    Yeah I know... there was some weird things that worked and didn't work for me too! It is indeed ugly... I had to do some pretty funky stuff to get my process to work as well... I had to write something to a text file and have a windows service running in the background pick that up (that the file had changed) and then fire up the app from the windows service instead under my own account and wake up the PC and all sorts of weird things just to be able to fire my process off from a web page... it does suck. – MaxOvrdrv Feb 18 '15 at 19:35
  • Thanks for the help - your input led me to a solution! Updated my original question with the solution. – grumpyhoser Feb 18 '15 at 19:52
  • Awesome! :) Glad it helped in some way :) – MaxOvrdrv Feb 18 '15 at 20:01
  • 1
    I could be wrong, but I think maybe my 'RunMyCmdAndGetResponse' solution above could run your exe file as well, as you were attempting in the link you posted. You would just pass it the path to your exe file instead of a path to a cmd file. Assuming of course that your exe file has no UI components, etc. – grumpyhoser Feb 19 '15 at 13:18
0

What about not using "cmd"?

Process proc = new Process ();
proc.StartInfo.FileName = @"c:\mypath\myfile.cmd";
Derek
  • 7,615
  • 5
  • 33
  • 58
  • That works if UseShellExecute is true, but I need UseShellExecute = false to get the response from the cmd file. – grumpyhoser Feb 18 '15 at 18:35