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();
Related
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();
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?
How do I run this python 2.7 code from C# (file name is myPythonScript.py):
import argparse
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument(
'-sd', '-start_date', help='start date to download data')
parser.add_argument(
'-ed', '-end_date', help='end date to download data')
args = parser.parse_args()
#print(args.accumulate(args.start_date))
print(args.sd, args.ed)
Above code only takes two dates as command line params and shows it to the user. I want to run it as a process from C#.
When I use this C# code it runs script without params well. But when I add params it can`t find python file. Why? How to resolve this?
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.FileName = #"C:\Anaconda2\python.exe";
// path to my python script
string appEXE = AppDomain.CurrentDomain.BaseDirectory;
// this scripts runs without params
python_script_name = #"myPythonScript.py -sd 01/01/2015 -ed 05/09/2017";
startInfo.Arguments="\""+appEXE+ "Python\\"+ python_script_name + "\"";
startInfo.UseShellExecute = false;
startInfo.RedirectStandardOutput = true;
startInfo.CreateNoWindow = true;
startInfo.RedirectStandardError = true;
using (Process process = Process.Start(startInfo))
{
using (StreamReader reader = process.StandardOutput)
{
string result = reader.ReadToEnd();
//MessageBox.Show("Normal results"+result);
Debug.WriteLine(result);
}
process.WaitForExit();
// This will show error: no such file or directory
MessageBox.Show("Errors"+process.StandardError.ReadToEnd());
GC.Collect();
Try these lines out:
string scriptPath = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Python", "myPythonScript.py")
startInfo.Arguments = "\"" + scriptPath + "\"" + " -sd 01/01/2015 -ed 05/09/2017"
I think you had an issue with quotation marks.
I tried following code to pause command line screen after execution of msbuild.exe
var solutionFile = "c:\test\myconsole.sln";
regKey = Registry.LocalMachine.OpenSubKey(#"SOFTWARE\Microsoft\MSBuild\ToolsVersions\3.5");
var msbuildPath = (string)regKey.GetValue("MSBuildToolsPath");;
var startInfo = new ProcessStartInfo()
{
Arguments = String.Format("\"{0}\" /nologo", solutionFile),
FileName = Path.Combine(msbuildPath, "msbuild.exe")
};
var proc = Process.Start(startInfo);
proc.WaitForExit();
Any argument I can use to pause cmd screen? or write output in log file?
I would try launching msbuild.exe within and actual cmd.exe as presented here.
EDIT
const string solutionFile = #"c:\test\myconsole.sln";
var regKey = Registry.LocalMachine.OpenSubKey(#"SOFTWARE\Microsoft\MSBuild\ToolsVersions\3.5");
var msbuildPath = (string) regKey.GetValue("MSBuildToolsPath");
var msBuild = Path.Combine(msbuildPath, "msbuild.exe");
var strCmdText = string.Format("/K {0} \"{1}\" /nologo", msBuild, solutionFile);
var proc = Process.Start("CMD.exe", strCmdText);
// Not necessary if you don't actually want to wait for it to exit before
// proceeding to following code
proc.WaitForExit();
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;
}