Only some commands produce any output at all for standard output and standard error. In addition, I've read that calling ReadToEnd on both streams may potentially cause a deadlock? If anybody knows of a safer way to read the streams that would be much appreciated. Below is how I am running the process and getting the output. The problem is that for fetch the output is empty (the fetching command does work just doesn't provide output), but not for other commands like pull.
ProcessStartInfo psi= new ProcessStartInfo();
psi.CreateNoWindow = true;
psi.RedirectStandardError = true;
psi.RedirectStandardOutput = true;
psi.FileName = "git.exe";
psi.UseShellExecute = false;
psi.WorkingDirectory = workingDir;
psi.Arguments = "fetch -v";
Process fetchProcess = new Process();
fetchProcess.StartInfo = psi;
fetchProcess.Start();
string err = "";
string stdout = "";
//Both standard error and stdout are empty. But if argument is
// a git pull, then standard error and output are not empty.
using (StreamReader myOutput = fetchProcess.StandardOutput) {
stdout = myOutput.ReadToEnd();
}
using (StreamReader myError = fetchProcess.StandardError) {
err= myError .ReadToEnd();
}
fetchProcess.WaitForExit();
fetchProcess.Close();
Anyway to make sure the fetch results are outputted?
Related
I am trying to execute the cat command from my C# code, but I am running into problems.
So, this is just a very simple test, but I end up with the error:
Error: cat: '>': No such file or directory
Now... both source and target files actually exist.. and same result if target file does not exist.
If I open a console on my Raspberry Pi, it executes just fine. Any help is much appreciated.
My code:
var srcFile = "/home/pi/tm-satellite/Helpers/wpa_supplicant.conf";
var outFile = "/home/pi/tm-satellite/network-test.txt";
StringBuilder sb = new StringBuilder();
var info = new ProcessStartInfo();
info.FileName = "/bin/bash";
info.Arguments = $"-c 'cat {srcFile} > {outFile}'";
info.UseShellExecute = false;
info.CreateNoWindow = true;
info.RedirectStandardOutput = true;
info.RedirectStandardError = true;
var p = Process.Start(info);
//* Read the output (or the error)
sb.AppendLine($"Args: {info.Arguments}");
sb.AppendLine($"Output: {p!.StandardOutput.ReadToEnd()}");
sb.AppendLine($"Error: {p!.StandardError.ReadToEnd()}");
p!.WaitForExit();
return $"Overwrite system file {path}: {p.ExitCode}{Environment.NewLine}{sb}";
This is because you're passing the cat program the > argument.
> only makes sense in bash or sh process where it tells to the interpreter that stdout outputs should be dumped into file. It's not a valid argument for cat.
To get around this, invoke your cat process within your shell:
sh -c 'cat file1 > file2'
In C#
var srcFile = "/home/pi/tm-satellite/Helpers/wpa_supplicant.conf"
var outFile = "/home/pi/tm-satellite/network-test.txt"
var info = new ProcessStartInfo();
info.FileName = "sh";
info.Arguments = $"-c 'cat {srcFile} > {outFile}'";
Alternatively you can use C#'s File utilities to read the first file and write its contents into the second as it might be faster due to less I/O operations.
I've fixed my sample. Use double quotes instead of single quotes:
var srcFile = "~/bad";
var outFile = "~/good";
var pInfo = new ProcessStartInfo()
{
FileName = "sh",
Arguments = $"-c \"cat {srcFile} > {outFile}\""
};
var process = Process.Start(pInfo);
process.WaitForExit();
I have C# automation code that start a process
var proc1 = new ProcessStartInfo();
string anyCommand = " adb logcat - v threadtime emulator-5554 > logcat.log";
proc1.UseShellExecute = true;
proc1.WorkingDirectory = outputDirectory;
proc1.FileName = #"C:\Windows\System32\cmd.exe";
proc1.Verb = "runas";
proc1.Arguments = "/c " + anyCommand;
proc1.WindowStyle = ProcessWindowStyle.Hidden;
Process p = new Process();
p.StartInfo = proc1;
p.Start();
Console.WriteLine(p.Id);
TestLogger.WriteInformationStep("p.Id: " + p.Id);
after some steps I'm trying to read the file
string text2 = System.IO.File.ReadAllText(element);
but I receive error message
System.IO.IOException : The process cannot access the file
'C:\Users\test\Documents\overview9\bin\Debug\Results\logcat.log'
because it is being used by another process. TearDown :
HarVE.Log.FailedStepException : There were 1 failed step(s): Test did
not run to completion
what should i do?
I tried p.Close();p.Kill();
non of them work for me.
If p.Kill(); where placed after System.IO.File.ReadAllText(element); write p.Kill() before System.IO.File.ReadAllText(element),
if it placed correctly, then seems like other process is reading/writting that file,
try to use StreamReader from System.IO, StreamReader can read multiple times, something like this:
StreamReader sr = new StreamReader(path_to_file);//replace path_to_file by your txt file path
string text2 = sr.ReadToEnd();
We have a C# module that needs to pass XML as a string to a python module and get the process result from that python module (has complicated logic and many imported libraries). But somehow I got nothing returned after several tries, the following is my sample code. Also is that possible to use pyinstaller to package the python module into EXE and achieve same functionality?
public InquiryResponse ProcessXML(string xml)
{
ProcessStartInfo psi = new ProcessStartInfo();
psi.FileName = #"C:\Python\python.exe";
psi.Arguments = string.Format(#"C:\myapp.py" {0}", xml);
psi.UseShellExecute = false;
psi.CreateNoWindow = true;
psi.RedirectStandardOutput = true;
psi.RedirectStandardError = true;
var error = "";
var result = "";
using (var process = Process.Start(psi))
{
error = process.StandardError.ReadToEnd();
result = process.StandardOutput.ReadToEnd();
}
// Some other process
}
var p = Process.Start(#"c:\PsTools\PsExec.exe", #"C:\Windows\System32\notepad.exe");
var err = p.StandardError.ReadToEnd();
var msg = p.StandardOutput.ReadToEnd();
lblStatusResponse.Text = "Err: " + err + "Msg: " + msg;
Why is my code not working?
I getting error:
System.InvalidOperationException: StandardError has not been redirected.
But when I add following:
p.StartInfo.RedirectStandardError = true;
var p = Process.Start(#"c:\PsTools\PsExec.exe", #"C:\Windows\System32\notepad.exe");)
it still gets the same error.
The main problem is that I wanna execute a exe with arguments, but I can't get it to work.
The following code generates a new p, this ignoring the settings you change in the previous instance:
var p = Process.Start(#"c:\PsTools\PsExec.exe", #"C:\Windows\System32\notepad.exe");)
So it doesn't really matter whether you initialize p like this
p.StartInfo.RedirectStandardError = true;
or not.
What you need to do
You need to create a ProcessStartInfo object, configure it and then pass it to Process.Start.
ProcessStartInfo p = new ProcessStartInfo(#"c:\PsTools\PsExec.exe", #"C:\Windows\System32\notepad.exe");
p.UseShellExecute = false;
p.RedirectStandardError = true;
p.RedirectStandardOutput = true;
Process proc = Process.Start(p);
var err = proc.StandardError.ReadToEnd();
var msg = proc.StandardOutput.ReadToEnd();
Taken from MSDN: https://msdn.microsoft.com/en-us/library/system.diagnostics.process.standardoutput(v=vs.110).aspx
The StandardOutput stream has not been defined for redirection; ensure ProcessStartInfo.RedirectStandardOutput is set to true and ProcessStartInfo.UseShellExecute is set to false.
So remember to set those flags as instructed by MS.
Process proc = new Process();
proc.StartInfo.FileName = "cmd.exe";
proc.StartInfo.UseShellExecute = false;
proc.StartInfo.RedirectStandardError = true;
proc.StartInfo.RedirectStandardOutput = true;
proc.StartInfo.Arguments = "/C " + command; //Enter your own command
proc.Start();
string output =proc.StandardOutput.ReadToEnd();
I know this is not the same code you have but this is was the only working code I have , that will run external command/process in C# , and return all of it output/errors to the application main window
public void Processing()
{
//Create and start the ffmpeg process
System.Diagnostics.ProcessStartInfo psi = new ProcessStartInfo("ffmpeg")
{ // this is fully command argument you can make it according to user input
Arguments = "-y -i '/mnt/Disk2/Video/Antina03.jpg' pp.mp4 ",
RedirectStandardOutput = true,
WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden,
UseShellExecute = false,
RedirectStandardError=true,
RedirectStandardInput=true
};
System.Diagnostics.Process ischk;
ischk = System.Diagnostics.Process.Start(psi);
ischk.WaitForExit();
////Create a streamreader to capture the output of ischk
System.IO.StreamReader ischkout = ischk.StandardOutput;
ischk.WaitForExit();
if (ischk.HasExited) // this condition very important to make asynchronous output
{
string output = ischkout.ReadToEnd();
out0 = output;
}
/// in case you got error message
System.IO.StreamReader iserror = ischk.StandardError;
ischk.WaitForExit();
if (ischk.HasExited)
{
string output = iserror.ReadToEnd();
out0 = output;
}
}
if you want to run this process just call the function Processing() BTW out0 are global variable so it can use out the function .
credit
I'm using MonoDevlop "C# devloping tool on Linux " and I get the output this way :-
public MainWindow() : base(Gtk.WindowType.Toplevel)
{
Build();
Processing();
textview2.Buffer.Text = out0;
}
I want to execute these steps in CMD using c#
1 - CD C:\MySQL\MySQL Server 5.0\bin
2 - mysqldump -uroot -ppassword sample> d:\Test\222.sql
On manually doing this, i will get file named "222.sql"
I am using the below code to do it, but missing something.. Nothing Happens
public void CreateScript_AAR()
{
string commandLine = #"CD C:\MySQL\MySQL Server 5.0\bin\mysqldump -uroot -ppassword sample> d:\Test\222.sql""";
System.Diagnostics.ProcessStartInfo PSI = new System.Diagnostics.ProcessStartInfo("cmd.exe");
PSI.RedirectStandardInput = true;
PSI.RedirectStandardOutput = true;
PSI.RedirectStandardError = true;
PSI.UseShellExecute = false;
System.Diagnostics.Process p = System.Diagnostics.Process.Start(PSI);
System.IO.StreamWriter SW = p.StandardInput;
System.IO.StreamReader SR = p.StandardOutput;
SW.WriteLine(commandLine);
SW.Close();
}
You're executing both commands in 1 command, this is not valid syntax.
You don't even need to change the directory, so just remove the dirchange (CD) from your command string. Also, use quotes like Oded said.
string commandLine = #"""C:\MySQL\MySQL Server 5.0\bin\mysqldump"" -uroot -ppassword sample > d:\Test\222.sql";
You can also call MySqlDump.exe directly from your code without cmd.exe. Capture its output and write it to a file. Writing it in the correct encoding is important so that it restores correctly.
string binary = #"C:\MySQL\MySQL Server 5.0\bin\mysqldump.exe"
string arguments = #"-uroot -ppassword sample"
System.Diagnostics.ProcessStartInfo PSI = new System.Diagnostics.ProcessStartInfo(binary, arguments);
PSI.RedirectStandardInput = true;
PSI.RedirectStandardOutput = true;
PSI.RedirectStandardError = true;
PSI.UseShellExecute = false;
System.Diagnostics.Process p = System.Diagnostics.Process.Start(PSI);
Encoding encoding = p.StandardOutput.CurrentEncoding;
System.IO.StreamWriter SW = new StreamWriter(#"d:\Test\222.sql", false, encoding);
p.WaitOnExit();
string output = p.StandardOutput.ReadToEnd()
SW.Write(output)
SW.Close();
This is how I used it to meet my requirements.
public static void runResGen()
{
string ResGen = #"C:\Program Files (x86)\Microsoft SDKs\Windows\v8.0A\bin\NETFX 4.0 Tools\ResGen.exe";
string outputPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + "\\resxMerge";
DirectoryInfo dinfo = new DirectoryInfo(outputPath);
DirectoryInfo latestdir = dinfo.GetDirectories().OrderByDescending(f => f.CreationTime).FirstOrDefault();
string latestDirectory = latestdir.FullName.ToString();
string arguments = latestDirectory + "\\StringResources.resx /str:c#,,StringResources /publicClass";
ProcessStartInfo PSI = new ProcessStartInfo(ResGen, arguments);
PSI.RedirectStandardInput = true;
PSI.RedirectStandardOutput = true;
PSI.RedirectStandardError = true;
PSI.UseShellExecute = false;
PSI.CreateNoWindow = true;
System.Diagnostics.Process p = System.Diagnostics.Process.Start(PSI);
Encoding encoding = p.StandardOutput.CurrentEncoding;
p.Close();
}