I run a cmd command in c# and somehow it usually crashes. I mean, when I work with smaller files (I run some kind of converter software) it almost always suceeds, but when I try it with larger ones it just crashes. I want to know where. And therefore I would like to run the command and see all the details, like the progress.
When I run it normally, by hand in command line, it writes like : Welcome to ... Progress : ... and so on. But how could I see that in C#? I only see the blank black stuff.
Here's my code. I tried to write out the StandardOutput, the StandardError, but it seems like its good. So my only chance is to see the details of the stuff running.
process = new System.Diagnostics.Process();
startInfo = new System.Diagnostics.ProcessStartInfo();
startInfo.FileName = "cmd.exe";
startInfo.WorkingDirectory = dir.Parent.FullName;
startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Normal;
startInfo.UseShellExecute = false;
startInfo.RedirectStandardOutput = true;
startInfo.RedirectStandardInput = true;
startInfo.RedirectStandardError = true;
process.StartInfo = startInfo;
process.Start();
process.StandardInput.WriteLine(#"make html");
k = new StreamReader(process.StandardOutput.BaseStream);
process.StandardInput.WriteLine(#"exit");
k.ReadToEnd();
Thank you guys, I hope you can help. Have a nice day!
EDIT: Now I see the output, by writing make html > output.txt
So my problem now is, why can I run exactly the same command from cmd, by hand, and why I cannot from C#
Thanks
You are on the right track for the redirection, you just have to hook up what you want to do with it...
Please check this post but here is a portion...
startinfo.OutputDataReceived += DOSOutputResultsHandler;
StringBuilder DOSOutputResults = new StringBuilder();
protected void DOSOutputResultsHandler(object sendingProcess,
System.Diagnostics.DataReceivedEventArgs outLine)
{
if (!string.IsNullOrEmpty(outLine.Data))
// track data into the NORMAL output string builder
DOSOutputResults.Append(Environment.NewLine + outLine.Data);
}
So now I have an answer, that worked for me.
I tried many ways to write out the output, and see where it crashes.
After a few turns I realized it starts working when I write out the output into a txt, with the following two methods:
I used the cmd: "make html > infooutput.txt" and "make html 2> infoerrors.txt".
I cannot explain why this works, but as I put these lines everywhere, where I called this command, it starts working.
Thank you very much for your help, you may find other great advices in the comment sections, for me they did not work properly.
Related
I have found many similar questions to this but non of the answers work quite as I desire and I think the situations were a bit different.
A bit of background: basically I created a C# command line application and I want to create a GUI version of that. My thinking was that the user can select various options that will configure the arguments that are passed to the CLI then I will use Process to start the CLI. And I want to display the output from the CLI into a ListBox on my Form in real time. I have tried a few different solutions provided in different questions: 1, 2, 3.
The closest thing I have at this point looks something like this:
ProcessStartInfo info = new ProcessStartInfo();
info.CreateNoWindow = true;
info.UseShellExecute = false;
info.WindowStyle = ProcessWindowStyle.Hidden;
// FileName and Arguments are specific to my CLI
info.FileName = "SimSwitcher.exe";
info.Arguments = String.Format("{0} -d {1} -f1 {2} -f2 {3} -s {4} -l {5}", command.ToString(), device.ToString(), file1Path, file2Path,
Convert.ToString(this.startingAddress, 16), Convert.ToString(this.length, 16));
info.RedirectStandardOutput = true;
proc = new Process();
proc.StartInfo = info;
proc.EnableRaisingEvents = true;
proc.OutputDataReceived += Proc_OutputDataReceived;
proc.Start();
proc.BeginOutputReadLine();
Then this is my event handler:
private void Proc_OutputDataReceived(object sender, DataReceivedEventArgs e)
{
if (e.Data != null)
{
this.BeginInvoke(new MethodInvoker(() => { outputBox.Items.Add(e.Data);}));
}
}
Where outputBox is the ListBox.
Right now this is close to what I want, but the output is not quite added in real time. Within the code for my SimSwitcher.exe CLI, I am using Process again to run three other CLI's in succession (that I didn't develop). What happens is that the output of the first process is not added to the ListBox until the first process is finished and likewise for the second and third processes. I tried using similar code as above to start those three processes in my SimSwitcher.exe CLI but that didn't help and it actually caused the SimSwitcher.exe CLI to not display the output in real time when it was run from the command line (it did display the output in real time before that change).
My suspicion is that there's nothing I can do to fix this and it's something with the the 3 CLI processes that my CLI is running. But maybe I am missing something, any feedback or suggestions would be appreciated.
Sorry if this is something obvious, I'm super new to C#.
I'm working on a program that runs a python script to check something online, that then writes it back to a file that C# reads and puts on a form. Everything works if I manually run them both at the same time, but I really want to start the script from the C# program.
Here's the function that should start the python script:
private void RunPython()
{
Process p = new Process();
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
startInfo.FileName = "cmd.exe";
startInfo.Arguments = "python " + path + "\\foo.py";
p.StartInfo = startInfo;
p.Start();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
// get things set up... etc.
RunPython();
}
I've tried running it without the window hidden, and it just brings up an empty cmd line in the 'path' directory. Is it never running the python script? It doesn't seem like it is, but it may also be running it and immediately closing it. I can't tell.
I need it to stay open for the duration of the C# program's run, so if the problem is it exiting when the RunPython() method returns, is there some different way I could go about this?
Thanks!!
If you want to run a program in the command line using arguments to cmd.exe you need the /c flag. Alternatively you can use /k but that keeps the command process running which you probably don't want.
/c Carries out the command specified by String and then stops.
So it's usage is cmd.exe /c [string]
Try changing your arguments line to:
startInfo.Arguments = "/c \"python " + path + "\\foo.py\"";
See here for more information about running cmd.exe and dealing with quotes in the string section of the command: https://technet.microsoft.com/en-us/library/cc771320(v=ws.11).aspx
It's all about a line I want to use to get windows update information, which is part of wmic.
My code looks like this:
Process p = new Process();
string arguments = "qfe list full /format:htable > "+ path;
ProcessStartInfo procStartInfo = new ProcessStartInfo("wmic", arguments);
procStartInfo.CreateNoWindow = true;
procStartInfo.WindowStyle = ProcessWindowStyle.Hidden;
procStartInfo.UseShellExecute = false;
p.StartInfo = procStartInfo;
p.Start();
while path is the valid location where the file would be dumped, ending with a hotfixlog.htm of course.
The problem is, that nothing happens at all. However, when I take the final product from the arguments-variable, and paste it manually into cmd with 'wmic < variablecontent >' it's working perfectly fine and I end up with the .htm I expect.
The line created looks like this:
"qfe list full /format:htable > C:\Users\...\WindowsHotfixes.htm"
What do I have to change to make it work from the code? I was expecting the backslashes to cause problems, but when manually entering the line they don't.
Your code will not work because the redirection operator (>) is not an element of the OS available to any application, but an operator in cmd.exe. It works in the command line because cmd is handling it, but wmic doesn't know what to do with it.
You can use the redirection if your command line is something like
cmd /c"wmic qfe list full /format:htable > x:\somewhere\file.htm"
Or you can remove the redirection and indicate to wmic that you want the data saved in a file
wmic /output:"x:\somewhere\file.htm" qfe list full /format:htable
I'm currently solving a problem of starting external tool from .net app.
I have this part of code:
proc.StartInfo = new ProcessStartInfo(_app, _args);
proc.StartInfo.UseShellExecute = false;
proc.StartInfo.RedirectStandardInput = true;
proc.StartInfo.RedirectStandardOutput = true;
proc.StartInfo.RedirectStandardError = true;
proc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
But, after starting application I get an error to StandartError output witn promt confirmation answer "enter y/n".
I've already tried to input "y" via standart input, right after starting process, but still get the same error.
var standartInput = proc.StandardInput;
standartInput.AutoFlush = true;
standartInput.WriteLine("y");
standartInput.Close();
I'd really appreciate any help. Thanks.
PS: PuTTY Secure Copy client - is the external app I'm using from code. There is a confirmation promt, when running app for first time to save servers fingerprint in system registry.
The code looks OK to me. Maybe you need to sleep for a second or something before writing the "y". I would imagine that the program takes a little while to ask the user for input
Our C# (V3.5) application needs to call another C++ executable which is from another company. we need to pass a raw data file name to it, it will process that raw data (about 7MB) file and generate 16 result files (about 124K for each).
The code to call that executable is this:
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.CreateNoWindow = true;
startInfo.UseShellExecute = false;
startInfo.RedirectStandardError = true;
startInfo.RedirectStandardOutput = true;
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
startInfo.FileName = exePath;
startInfo.Arguments = rawDataFileName;
try
{
Process correctionProcess = Process.Start(startInfo);
correctionProcess.WaitForExit();
}
catch(nvalidOperationException ex)
{
....
}
catch(...)
...
It works fine. Now we have new raw data. After replace the old raw data with the new raw data file. That executable process never return to us. It will hang forever. If we kill our C# application, those result files will be generated in the target directoy. It looks like the executable does create those result files but has issue to write to the disk and return to us until the process is terminated.
It is NOT like this with the old raw data file.
When we run the executable with the new raw data directly (no from our C# app call), it works fine. This means this executable has no problem with the new raw data.
My question 1: what's the possible causes for this behaviour?
Now I change our code with startInfo.UseShellExecute = true; and add startInfo.WorkingDirectory= ..., and disabled
//startInfo.RedirectStandardError = true;
//startInfo.RedirectStandardOutput = true;
Then it works.
My question 2: why use Windows Shell solve this issue?
My question 3: why it works before without using Shell?
My question 4: when we should use Shell and When shouldn't?
thanks,
Several possibilities:
You are redirecting output and error but not reading it. The process will stall when its stdout or stderr buffer fills up to capacity.
The program might be displaying an error message and waiting for a keypress. You are not redirecting input nor check stderr, that keypress will never come.
Some programs, xcopy.exe is a very good example, require stdin to be redirected when you redirect stdout. Although the failure mode for xcopy.exe is an immediate exit without any diagnostic.
Seeing it fixed when you kill your C# program makes the first bullet the likeliest reason.
I know this, it is a very common problem. I has to do with the output, which must be handled asynchronously. You just can't WaitForExit when output exceeds certain amount of data.
You need to add
myStdErr= correctionProcess.StandardError.ReadToEnd();
Only once usually works, if you want to overkill this works ("P" being my Process)
while (!P.HasExited)
stdErr+= P.StandardError.ReadToEnd();
If you don't need the stdout/stderr, just turn the Redirect* properties to false.