thanks in advance for your time.
I'm working on an application to automate some of the things that I have to check each day.
One of them is making sure that all of our daily Robocopies took place successfully.
I'm having issues figuring out the best way to communicate this to my program. I've looked into the various Exit codes that Robocopy uses which would be very useful, but is there anyway to output this to a file, and would there be anyway to know which backup it was associated with?
Sorry if this is vague, please let me know of any other info that could be of use.
Thanks,
Will
If you start the robocopy process from your application you could check the exit code from there.
Process myProcess = null;
// Start the process.
myProcess = Process.Start("robocopy ....");
myProcess.WaitForExit(1000);
Console.WriteLine("Process exit code: {0}", myProcess.ExitCode);
http://msdn.microsoft.com/en-us/library/system.diagnostics.process.exitcode(v=vs.110).aspx
You could write the Robocopy output to a file and read that in, like
robocopy c:\Test\ c:\temp /LOG+:myLogFile
Then experiment with the log options to get a useful verbosity ( see http://ss64.com/nt/robocopy.html )
You could do something like this:
public static void Main()
{
// Prepare the process.
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.CreateNoWindow = false;
startInfo.UseShellExecute = false;
startInfo.FileName = "robocopy.exe";
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
startInfo.Arguments = "WHATEVER YOU NEED"
// Start process and wait for it to end
Process exeProcess = Process.Start(startInfo)
exeProcess.WaitForExit();
// Display what the exit code was
Console.WriteLine();
Console.WriteLine("Process exit code: {0}", exeProcess.ExitCode);
}
Create a Robocopy-process like this:
string command = $"Robocopy {sourcePath} {targetPath} /MIR /w:1 /r:10";
var copyTask = new Process()
{
StartInfo = new ProcessStartInfo()
{
FileName = "CMD.exe"
Arguments = $"/c {command}",
UseShellExecute = false,
RedirectStandardOutput = true,
CreateNoWindow = true
}
};
Use it like this:
copyTask.Start()
string Output = copyTask.StandardOutput.ReadToEnd();
copyTask.WaitForExit();
Now you have the whole log in the "string output". This is useful if you want to find out WHAT went wrong.
Related
I would like to open a simple console application that looks like this :
static void Main(string[] args)
{
Console.WriteLine("Beginning");
string smth = Console.ReadLine();
Console.WriteLine("End");
}
I open it thanks to Process.Start in a Form like this :
private void button1_Click(object sender, EventArgs e)
{
ProcessStartInfo processInfo = new ProcessStartInfo();
processInfo.FileName = myexe;
processInfo.CreateNoWindow = true;
processInfo.UseShellExecute = false;
processInfo.RedirectStandardOutput = true;
processInfo.RedirectStandardInput = true;
processInfo.StandardOutputEncoding = Encoding.GetEncoding(850);
Process process = new Process();
process.StartInfo = processInfo;
process.Start();
}
I managed to read output using a StreamReader and get this into a textbox :
Beginning
End
But the problem is the program doesn't wait at Console.ReadLine(), like it is ignored. And i don't know how to let the user input from keyboard (better if it's directly in the console).
Is there a way to do it ?
EDIT
Looks like i wasn't clear enough, sorry.
I'm trying to make a simple Form, with no control, able to "react" when i scan a barcode.
Basically, i want the console application to run background so when my barcode is scanned, i can get it as my output value :
Form "Please scan your barcode"
Console app is launched
Barcode is scanned
Console app close
Barcode as output value
So StandardInput doesn't seems to be the solution for my problem.
That's why i'm asking you if there is a way to achieve this.
I am not quite sure what kind of problem you are facing, but I'm noticing that you aren't utilizing the StandardInput and StandardOutput properties of the Process instance (which is what you should be doing after redirecting them). See if the following example helps you.
If you have this console application:
static void Main(string[] args)
{
Console.WriteLine("Beginning");
var str = Console.ReadLine();
Console.WriteLine("End: " + str);
}
And you invoke it through this:
ProcessStartInfo processInfo = new ProcessStartInfo
{
FileName = "console_program",
CreateNoWindow = true,
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardInput = true,
};
Process process = new Process
{
StartInfo = processInfo,
};
process.Start();
process.StandardInput.WriteLine("Hey!");
string output = process.StandardOutput.ReadToEnd();
process.WaitForExit();
You will get the output value:
"Beginning\r\nEnd: Hey!\r\n"
I'm looking to automate nupkg creation in a c# app. I'm aiming to include nuget.exe in my project and use System.Diagnostics to launch cmd.exe as a process and then pass the required commands, which would be 'cd project\path\here', 'nuget spec something.dll' and 'nuget pack something.nuspec'.
The code I have so far is:
Process p = new Process();
ProcessStartInfo info = new ProcessStartInfo(#"C:\Windows\System32\cmd.exe", #"mkdir testdir");
p.StartInfo = info;
p.Start();
Console.ReadLine();
However, it doesn't even create the testdir, and I've got no idea how to chain those commands. There is a method called WaitForInputIdle on my p Process, but it raises events and I've got no idea how to handle those to be honest.
A perfect solution would also let me read output and input. I've tried using StreamWriter p.StandardInput, but then there's the problem of checking whether a command is finnished and what was the result.
Any help would be much appreciated.
Edit: Success! I've managed to create a directory :)
Here's my code now:
Process p = new Process();
ProcessStartInfo info = new ProcessStartInfo(#"C:\Windows\System32\cmd.exe");
info.RedirectStandardInput = true;
info.UseShellExecute = false;
p.StartInfo = info;
p.Start();
using (StreamWriter sw = p.StandardInput)
{
sw.WriteLine("mkdir lulz");
}
Still no idea how to await for input and follow up with more commands, though.
You can do this by three ways
1- The easiest option is to combine the two commands with the '&' symbol.
var processInfo = new ProcessStartInfo("cmd.exe", #"command1 & command2");
2- Set the working directory of the process through ProcessStartInfo.
var processInfo = new ProcessStartInfo("cmd.exe", #"your commands here ");
processInfo.UseShellExecute = false;
processInfo.WorkingDirectory = path;
3- Redirecting the input and output of the process. (Also done through the ProcessStartInfo).This is required when you like to send more input to the process, or when you want to get the output of the process
Also see this answer
I have been messing around with triggering a bash script via C#. This all works fine when I first call the "open" command with arguments which in turn opens my .command script via Terminal.
Once the "open" command is used once Terminal or iTerm will remain open in the background, at which point calling the "open" command with arguments then has no further effect. I sadly have to manually quit the application to trigger my script again.
How can I pass arguments to an already open terminal application to restart my script without quitting?
I've searched online ad can't seem to work it out, it already took a good amount of time solve the opening code. Your help is much appreciated.
Here is the C# code I'm using to start the process:
var p = new System.Diagnostics.Process();
p.StartInfo.FileName = "open";
p.StartInfo.WorkingDirectory = installFolder;
p.StartInfo.Arguments = "/bin/bash --args \"open \"SomePath/Commands/myscript.command\"\"";
p.Start();
Thanks
EDIT:
Both answers were correct, this might help others:
ProcessStartInfo startInfo = new ProcessStartInfo("/bin/bash");
startInfo.WorkingDirectory = installFolder;
startInfo.UseShellExecute = false;
startInfo.RedirectStandardInput = true;
startInfo.RedirectStandardOutput = true;
Process process = new Process();
process.StartInfo = startInfo;
process.Start();
process.StandardInput.WriteLine("echo helloworld");
process.StandardInput.WriteLine("exit"); // if no exit then WaitForExit will lockup your program
process.StandardInput.Flush();
string line = process.StandardOutput.ReadLine();
while (line != null)
{
Debug.Log("line:" + line);
line = process.StandardOutput.ReadLine();
}
process.WaitForExit();
//process.Kill(); // already killed my console told me with an error
You can try:
before calling p.Start():
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardInput = true;
// for the process to take commands from you, not from the keyboard
and after:
if (p != null)
{
p.StandardInput.WriteLine("echo helloworld");
p.StandardInput.WriteLine("executable.exe arg1 arg2");
}
(taken from here)
This is what you may be looking for :
Gets a stream used to write the input of the application.
MSDN | Process.StandardInput Property
// This could do the trick
process.StandardInput.WriteLine("..");
I am working on a c# program to loop over my Windows Media Center recorded TV shows (.wtv) and convert them using the handbrake cli. I just got everything to work now and I wanted to also utilize the --scan function so that I can customize the audio and video arguments based on the input file rather then set a static.
This is what I have so far for the scan but I can't seem to find where the data is that prints out to the console window.
var p = new Process();
var pSI = new ProcessStartInfo();
pSI.RedirectStandardOutput = true;
pSI.UseShellExecute = false;
pSI.FileName = HandBrakeLocation;
pSI.Arguments = string.Concat(#"--scan -i ", '"', inputFile, '"');
pSI.WindowStyle = ProcessWindowStyle.Hidden;
p.StartInfo = pSI;
p.Start();
var stdout = p.StandardOutput;//streamreader
p.WaitForExit();
I thought that perhaps the p.StandardOutput would send the console output to the stdout StreamReader variable, but I could not find it anywhere inside the object. What am i missing?
Thanks for you time and assistance.
You can read the program output using the StandardOutput property of the process (which is a stream):
var output = stdout.ReadToEnd();
p.WaitForExit();
More info can be found on MSDN: https://msdn.microsoft.com/en-us/library/system.diagnostics.process.standardoutput%28v=vs.110%29.aspx
Hellp. In my 'plumbing' I have 3 command that should performed sequentially, and each request must wait until the end of the previous command. Now I have done the 1st request, but 2nd and 3rd just skips...
Could you please suggest how to change this 'plumbing'?
string strCmdText = s1;
var startInfo = new ProcessStartInfo
{
FileName = "cmd.exe",
RedirectStandardInput = true,
RedirectStandardOutput = true,
UseShellExecute = false,
CreateNoWindow = true
};
var process = new Process { StartInfo = startInfo };
process.Start();
process.StandardInput.WriteLine(strCmdText);
process.WaitForExit();
string strCmdText1 = s2;
process.StandardInput.WriteLine(strCmdText1);
process.WaitForExit();
string strCmdText2 = s3;
process.StandardInput.WriteLine(strCmdText2);
process.StandardInput.WriteLine("exit");
Thank you.
Let's go through your code:
You start an instance of cmd.exe:
var process = new Process { StartInfo = startInfo };
process.Start();
You write a command to its standard input:
process.StandardInput.WriteLine(strCmdText);
And then you wait for cmd.exe to exit:
process.WaitForExit();
Now, you write another command to its standard input:
string strCmdText1 = s2;
process.StandardInput.WriteLine(strCmdText1);
Wait, what? cmd.exe exited in the previous step, so there's no more process you could send a command to in the first place.
Then you wait for the process to exit, but it's already dead a long time ago:
process.WaitForExit();
And you repeat the same non-working code:
string strCmdText2 = s3;
process.StandardInput.WriteLine(strCmdText2);
process.StandardInput.WriteLine("exit");
You should better understand what's the the problem now. It looks like cmd.exe quits after executing your first command.
There's a couple things you can try:
Get rid of cmd.exe altogether. Unless you execute some batch script you can directly call the intended executable (like python.exe).
Start 3 different instances of cmd.exe for your 3 commands.
Try to pass some arguments to cmd.exe, like /Q.
Try the first approach first, it's the cleanest one.