Capturing Standard Error - c#

I'm following the guidance of other SO articles on this topic, but I have been unable to find what I need. I have the following codeblock which launches - in this case - a known corrupted .msi (in order to test the retrieval of the standard error message):
ProcessStartInfo procStartInfo = new ProcessStartInfo("cmd.exe", "/c " + thirdPartyApp.Item2.InstallString);
procStartInfo.RedirectStandardOutput = true;
procStartInfo.RedirectStandardError = true;
procStartInfo.UseShellExecute = false;
procStartInfo.CreateNoWindow = true;
System.Diagnostics.Process proc = new System.Diagnostics.Process();
proc.StartInfo = procStartInfo;
writeEvent(EventLogEntryType.Information, "Attempting to launch upgrade: " + thirdPartyApp.Item2.InstallString, "Third Party Update");
proc.Start();
string stderror = proc.StandardError.ReadToEnd();
proc.WaitForExit();
When manually launched, this .msi throws error code 1620 with message "This installation package could not be opened. Contact the application vendor to verify that this is a valid Windows Installer package."
While debugging, if I look at proc.ExitCode its value is 1620 - so it's capturing that correctly. I added the line string stderror = proc.StandardError.ReadToEnd(); to attempt to capture the error text, but after the process executes and errors out stderror has a value of "".
How can I grab the actual error text into a variable?

Related

How to get the text from a pop-up box generated from cmd?

I'm trying to get the activation status of Windows. I've got this code:
Process proc = new Process();
proc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
proc.StartInfo.FileName = "cmd.exe";
proc.StartInfo.Arguments = "/C slmgr /xpr";
proc.StartInfo.UseShellExecute = false;
proc.StartInfo.CreateNoWindow = true;
proc.StartInfo.RedirectStandardOutput = true;
proc.StartInfo.RedirectStandardInput = true;
proc.Start();
string x = "";
while (!proc.HasExited)
{
x += proc.StandardOutput.ReadToEnd();
}
return x;
As some of you may know, the command "slmgr /xpr" will make a pop-up appear informing you of your Windows activation status.
Executing this code, I get the pop-up box (and "x" is empty).
What I want is to get the text that's in it (so it appears on a label in my form). I wonder if there's any way to extract just the text from inside the pop-up that appears, in this case it would be something like "the machine is permanently activated".
Is there any simple way to achieve this?
slmgr is actually a VBScript file not an executable, when you run it it will default to using the WScript runtime which is for windowed scripts and uses Message Boxes for default output. If you change to CScript you will get console output:
proc.StartInfo.FileName = "cscript.exe";
proc.StartInfo.Arguments = "/nologo \"" + Path.Combine(Environment.SystemDirectory, "slmgr.vbs") + "\" /xpr";
You can then capture this: Capturing console output from a .NET application (C#)
You could also look inside the script file, see whats its doing & reimplement it in your code (ymmv).

Process.Start cmd.exe won't run cmd file that is passed as agument when running in IIS

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;
}
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
What about not using "cmd"?
Process proc = new Process ();
proc.StartInfo.FileName = #"c:\mypath\myfile.cmd";

Why is auditpol not applying the local policy settings from C#?

I'm setting local auditing policies from a C# .NET program that reads settings from a file then uses Process.Start() with 'cmd' to execute the commands. This way has worked in the past for everything that I've needed it to do (including this exact situation), but recently it's just started to mysteriously fail to set the policies.
Here's the code: (command is of the form "auditpol /set /subcategory:"blah" /success:enable")
ProcessStartInfo procStartInfo = new ProcessStartInfo("cmd", "/c " + command);
procStartInfo.RedirectStandardOutput = true;
procStartInfo.RedirectStandardError = true;
procStartInfo.UseShellExecute = false;
procStartInfo.CreateNoWindow = true;
Process proc = new Process();
proc.StartInfo = procStartInfo;
proc.Start();
proc.WaitForExit();
string result = proc.StandardOutput.ReadToEnd();
string error = proc.StandardError.ReadToEnd();
In debug in VS2013 it's applying the policies just fine and even on the same computer in the full on .exe it's applying just fine, but when it gets transferred to another computer it will not set the policies from the auditpol command. Anyone have any ideas what could be happening?

Working with the command prompt in C#

I am working on a project of remotely receiving commands from a server, but I am facing a problem when working with the command prompt locally. Once I get it working locally, then I will move to remote communication.
Problem:
I have to completely hide the console, and client must not see any response when the client is working with the command line but it will show a console for a instance and then hide it.
I had to use c# to send a command to cmd.exe and receive the result back in C#. I have done it in one way by setting the StandardOutput... and input to true.
The commands are not working. For example, D: should change the directory to D and it does, but after that, if we use dir to see the directories in D, it does not show the appropriate directories.
Here is my code:
First Method
Process process = new Process();
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
startInfo.FileName = "cmd.exe";
startInfo.Arguments = "/C " + textBoxInputCommand.Text + " >> " + " system";
process.StartInfo = startInfo;
process.Start();
Second Method
ProcessStartInfo procStartInfo = new ProcessStartInfo("cmd", "/c " + textBoxInputCommand.Text);
procStartInfo.WorkingDirectory = #"c:\";
procStartInfo.RedirectStandardOutput = true;
procStartInfo.UseShellExecute = true;
procStartInfo.UseShellExecute = false;
Process proc = new Process();
proc.StartInfo = procStartInfo;
proc.Start();
string result = proc.StandardOutput.ReadToEnd();
richTextBoxCommandOutput.Text += result;
I want the program to run as administrator because the exe it generates does not run commands when it runs from the C drive.
Try not to run the commands by passing them to cmd instead write the commands passed by the client to a.bat file execute the .bat. file from your program this will probably hide your command prompt window.
You can also use process.OutputDataRecieved event handler to do anything with the output.
If you want to execute command using administrator rights you can use runascommand. It is equivalent to the sudo command in Linux. Here is a piece of code may be it will help you
var process = new Process();
var startinfo = new ProcessStartInfo(#"c:\users\Shashwat\Desktop\test.bat");
startinfo.RedirectStandardOutput = true;
startinfo.UseShellExecute = false;
process.StartInfo = startinfo;
process.OutputDataRecieved += DoSomething;
process.Start();
process.BeginOutputReadLine();
process.WaitForExit();
//Event Handler
public void DoSomething(object sener, DataReceivedEventArgs args)
{
//Do something
}
Hope it helps you.
You could hide command prompt window by adding this line of code:
startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
or do not create it at all
startInfo.CreateNoWindow = true;
Here can be found a few awarding solutions:
Run Command Prompt Commands

SNMPWalk Error in C# Process init

I'm creating an application at work that uses SNMPWalk to get details on specific IP addresses. Right now it's meant to use Nmap to find all printers in a specified network and then it uses SNMPWalk to get details on each printer.
The problem is that SNMPWalk is giving me the error:
"No log handling enabled - using stderr logging
-v2c: (Sub-id not found: (top) -> -v2c)"
My code is here:
Process p = new Process();
p.StartInfo.FileName = snmploc + "\\snmpwalk.exe";
p.StartInfo.ErrorDialog = false;
p.StartInfo.UseShellExecute = false;
p.StartInfo.CreateNoWindow = false;
p.StartInfo.WorkingDirectory = snmploc;
p.StartInfo.Arguments = "–mALL -v2c –cpublic " + printer.IP();
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardError = true;
p.Start();
Console.WriteLine("Snmpwalk has been fired");
Console.WriteLine("Waiting for Snmp to terminate...");
string output = p.StandardOutput.ReadToEnd();
string error = p.StandardError.ReadToEnd();
p.WaitForExit();
Console.WriteLine(p.ExitCode);
printer is an object of the class Printer. It is used to contain printer details such as ip address, name, model, serial number, and open ports. snmploc is obtained from command line arguments.
The main reason that this is so complicated is that when I try using the exact same command in a command prompt it works perfectly.

Categories

Resources