1

I'm trying to create a small program to run on a centralized device. This program will run

"psexec \server(s) netstat -na | findstr "LISTENING""

to collect netstat data from remote nodes (should redirect output to string), then parse the data and compare against a known list. I can run the psexec cmd above without any issues from the cmd line, but when I try to run the same command as a process within my C# program, no data is returned to be parsed. I can see that the netstat is being run (cmd window flashes with netstat results), but the process.standardoutput is not catching the stream. If I use ping or pretty much anything other than psexec as an argument, the stream is caught and the results are shown in my text box. I've also tried setting the filename to psexec.exe and specifying the arguments but I get the same results. Last but not least, if I run psexec without any arguments, I get the help kickback info returned in my textbox. This is true if I'm running psexec.exe as the filename OR if I run cmd.exe as filename with "/c psexec" specified as args.

I'm just trying to get psexec output to be caught when executing locally at this point. I'll worry about psexec to remote machines later. Any help would be MUCH appreciated.

Here's the code:

        System.Diagnostics.Process pProcess = new System.Diagnostics.Process();  
        pProcess.StartInfo.FileName = "cmd.exe";  
        pProcess.StartInfo.Arguments = "/c psexec netstat";  
        pProcess.StartInfo.UseShellExecute = false;  
        pProcess.StartInfo.RedirectStandardOutput = true;     
        pProcess.Start();
        string strOutput = pProcess.StandardOutput.ReadToEnd(); 
        pProcess.WaitForExit();

        if (pProcess.HasExited)
        {
            textBox1.Text = strOutput;
        }
        else
        {
            textBox1.Text = "TIMEOUT FAIL";
        }
Conspicuous Compiler
  • 6,403
  • 1
  • 40
  • 52
JStillwell
  • 43
  • 1
  • 5
  • You will likely [find the sample code at `BeginOutputReadLine` to be of assistance](http://msdn.microsoft.com/en-us/library/system.diagnostics.process.beginoutputreadline.aspx). – Conspicuous Compiler Dec 20 '11 at 23:53

2 Answers2

3

I would recommend also capturing the standard error output in case anything is being reported there.

Also, you may have a disconnect between "bitness" of psexec and your application if you are running on a 64-bit OS. If this is the case, change the platform for the project to match that of psexec rather than building as Any CPU.

competent_tech
  • 44,465
  • 11
  • 90
  • 113
  • Will check the standard error output as well. Psexec is 32bit (will work on 64bit) and since I'm using VS10 C# Express, I'm running into difficulty confirming the platform but I assume it should not matter in this case. Machine I'm using to dev/debug/run is 32bit. – JStillwell Dec 21 '11 at 21:07
  • Came across a few things to be changed but your recommendation of capturing standard error output was dead on and a good start. Also needed to catch standard input if I wanted to supply credentials. Turns out info was being sent to the error output so I knew at that point psexec wasn't just eating the output. Threw in some str literals and credentials to run remotely, works perfectly. Thanks for the help. Here is the updated code: – JStillwell Dec 22 '11 at 16:29
3

Came across a few things to be changed but your recommendation of capturing standard error output was dead on and a good start. Turns out some info was being sent to the error output (even though really wasn't error, just run status 0 from psexec) so I knew at that point psexec wasn't just eating ALL the output. Once I started trying to pass remote hosts as args, I started getting user/pass error data back. Also needed to catch standard input if I wanted to supply credentials for proc run. Threw in some str literals and credentials for the remote exec, works perfectly. Thanks for the help. Here is the updated code--

        System.Diagnostics.Process pProcess = new System.Diagnostics.Process();
        pProcess.StartInfo.Domain = "domain";
        pProcess.StartInfo.UserName = "user with priv";
        pProcess.StartInfo.Password = new System.Security.SecureString();
        char [] pass = textBox3.Text.ToArray();
        for (int x = 0; x < pass.Length; ++x)
        {
            pProcess.StartInfo.Password.AppendChar(pass[x]);
        }
        pProcess.StartInfo.FileName = @"psexec.exe";
        pProcess.StartInfo.Arguments = @"\\remoteHost netstat -ano";
        pProcess.StartInfo.UseShellExecute = false;
        pProcess.StartInfo.RedirectStandardInput = true;
        pProcess.StartInfo.RedirectStandardOutput = true;
        pProcess.StartInfo.RedirectStandardError = true;
        pProcess.Start();
        pProcess.WaitForExit(30000);
        if (!pProcess.HasExited)
        {
            pProcess.Kill();
        }

        string strOutput = pProcess.StandardOutput.ReadToEnd();
        string errOutput = pProcess.StandardError.ReadToEnd();
        textBox1.Text = strOutput;
        textBox2.Text = errOutput;
JStillwell
  • 43
  • 1
  • 5