1

I'm attempting to execute a command in command prompt in C# code on a .aspx page. The code doesn't throw any errors, however, the command doesn't execute because a new file isn't generated.

I don't see any issues with the command itself because if I copy the command from debug view and paste it into command prompt, it executes fine.

Any ideas why my code doesn't generate the ResultadoCheckMac_100939.txt?

code:

        string cmd = ejecutable_CheckMac + " " + archivo_temporal + " > " + archivo_resultado;
        System.Diagnostics.Debugger.Log(0, null, "cmd: " + cmd);

        System.Diagnostics.Debugger.Log(0, null, "Start cmd execution.");
        System.Diagnostics.Process process = new System.Diagnostics.Process();
        System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
        startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
        startInfo.FileName = "cmd.exe";
        startInfo.Arguments = cmd;
        startInfo.CreateNoWindow = true; 
        startInfo.UseShellExecute = false;
        process.StartInfo = startInfo;
        process.Start();
        System.Diagnostics.Debugger.Log(0, null, "Cmd execution finished.");

debug view output:

00000014    0.00096980  [136] cmd: C:\inetpub\wwwroot\cgi-bin\tbk_check_mac.exe C:\inetpub\wwwroot\cgi-bin\log\DatosParaCheckMac_100939.txt > C:\inetpub\wwwroot\cgi-bin\log\ResultadoCheckMac_100939.txt   
00000015    0.00103170  [136] Start cmd execution.  
00000016    0.01946740  [136] Cmd execution finished.
Sam Axe
  • 33,313
  • 9
  • 55
  • 89
Bhav
  • 1,957
  • 7
  • 33
  • 66
  • 2
    You want `cmd /c ` or `cmd /k `. You can also just execute against `ejecutable_CheckMac` and use it as your `FileName` parameter (then redirect the output within your application). – Brad Christie Aug 28 '15 at 16:33
  • Does the IIS user have write privilege to that directory? – Ben Voigt Aug 28 '15 at 16:33
  • Also, Brad is right, the `>` redirection support is provided by `cmd.exe`, it's not automatically available with `CreateProcess` (which is what `Process.Start()` uses when `UseShellExecute = false`) – Ben Voigt Aug 28 '15 at 16:34
  • @BenVoigt Yes, read+write. – Bhav Aug 28 '15 at 16:36
  • @BradChristie Sorry, what do you mean by your first point? I want cmd /c instead of what/where? If you submit an answer, I can mark it as correct if it resolves my issue. – Bhav Aug 28 '15 at 16:38

1 Answers1

2

Assuming you want to continue to execute it against the cmd prompt, you can do:

var psi = new ProcessStartInfo("cmd", "/c " + cmd); // note the /c
psi.UseShellExecute = false;
psi.CreateNoWindow = true;
psi.RedirectStandardOutput = true;

Process.Start(psi);

/c directs the prompt to "execute the following string". However, a cleaner method may be to intercept the output and catch it yourself:

var psi = new ProcessStartInfo(ejecutable_CheckMac, archivo_temporal);
psi.UseShellExecute = false;
psi.CreateNoWindow = true;
psi.RedirectStandardOutput = true;

using (var proc = Process.Start(psi))
{
    using (StreamReader sr = proc.StandardOutput)
    {
        // This effectively becomes the intended contents
        // of `archivo_resultado`
        var summary = sr.ReadToEnd();
    }
}

Example

If i wanted to ping -n 1 8.8.8.8, I could do it using either:

// Execute ping against command prompt
var psi = new ProcessStartInfo("cmd", @"/c ping -n 1 8.8.8.8 > save\to\ping.txt");
psi.UseShellExecute = false;
psi.CreateNoWindow = true;

Process.Start(psi);

Or, I could do:

// Call ping directly passing parameters and redirecting output
var psi = new ProcessStartInfo("ping", "-n 1 8.8.8.8");
psi.UseShellExecute = false;
psi.CreateNoWindow = true;

psi.RedirectStandardOutput = true;
using (var proc = Process.Start(psi))
{
    using (StreamReader sr = proc.StandardOutput)
    {
        Console.WriteLine(sr.ReadToEnd());
    }
}

Both end up giving me (roughly) the same output, it's just now I don't have to chase down a file.

Pinging 8.8.8.8 with 32 bytes of data:
Reply from 8.8.8.8: bytes=32 time=18ms TTL=54

Ping statistics for 8.8.8.8:
    Packets: Sent = 1, Received = 1, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
    Minimum = 18ms, Maximum = 18ms, Average = 18ms
Brad Christie
  • 100,477
  • 16
  • 156
  • 200
  • Thanks for the explanation. However, using both methods, the Process.Start(psi) returns the following error: Member 'System.Diagnostics.Process.Start(System.Diagnostics.ProcessStartInfo)' cannot be accessed with an instance reference; qualify it with a type name instead – Bhav Aug 29 '15 at 15:50
  • Are you trying `ProcessStart()`, or `new Process.Start ()`? – Brad Christie Aug 29 '15 at 15:53
  • Resolved it with System.Diagnostics.Process.Start(startInfo). Thanks. – Bhav Aug 29 '15 at 16:50
  • Not a problem, glad to help. – Brad Christie Aug 29 '15 at 18:49