So I have this code to launch a bat script which will execute certain java commands, starting with "java -version" just to get some output. The first time I call it it works, but the second time I am stuck with a black cmd screen.
The same code is used but in different locations.
Process proc = new Process();
ProcessStartInfo StartInfo = new ProcessStartInfo();
StartInfo.RedirectStandardOutput = true;
StartInfo.RedirectStandardError = true;
StartInfo.FileName = path + "javaScript.bat";
StartInfo.Arguments = "\"" + path + "\"";
StartInfo.UseShellExecute = false;
StartInfo.CreateNoWindow = false;
proc.StartInfo = StartInfo;
proc.Start();
proc.WaitForExit();
string output = proc.StandardOutput.ReadToEnd();
Anyone can help me figure out what happens? Since I don't get any echo I doubt the bat file gets stuck anywhere (echo is on and the first command is java -version so it should write something instead of just getting stuck at black cmd window)
proc.WaitForExit();
string output = proc.StandardOutput.ReadToEnd();
You are deadlocking the process with this code. It cannot exit until you empty its output buffer. But you don't read its output until it exits. The program can't continue, nor can you. A "deadly embrace", better known as deadlock.
Simply swap these two lines of code to fix the problem.
Do note that you have a problem with StandardError as well, it will still deadlock when it sends a bunch of error text to that stream. If you don't want to read it then don't redirect it. If you want to make it completely solid then you'll need to use BeginErrorReadLine and BeginOutputReadLine.
Related
I have a button in my form that when its clicked, it will open command prompt and automatically run a javascript file. My code so far only opens the command prompt. How do you run a javascript file?
Process process = new Process();
process.StartInfo.FileName = #"C:\windows\system32\cmd.exe";
process.Start();
Now that we know that you're trying to launch a Node.js app, try this new version.
And don't forget that C# is pretty well documented on MSDN.
If the rest of your code is working as is, and you don't actually want/need to run CMD.exe, this should do the trick:
Process process = new Process();
process.StartInfo.FileName = #"C:\Program Files\nodejs\node.exe";
process.StartInfo.Arguments = #"P:\ath\To\Your\File.js";
process.Start();
As a holdover from the original question: If you had been trying to launch a JScript script, you would want to use #"C:\Windows\System32\Cscript.exe", or if you want to launch a JScript script without seeing a command prompt window, replace Cscript with Wscript.
Try this:
process.StartInfo.FileName = #"C:\windows\system32\cmd.exe";
process.StartInfo.RedirectStandardInput = true;
process.StartInfo.UseShellExecute = false;
process.Start();
process.StandardInput.WriteLine("Cscript.exe \"PathToYourFile\\file.js\"");
//OR
//process.StandardInput.WriteLine("Wscript.exe \"PathToYourFile\\file.js\"");
process.StandardInput.Flush();
process.StandardInput.Close();
This is the command I am currently using for remote installation using psExec.
psExec \\MyRemoteComputer -s -c MyInstallationFile.exe /q
When I issue this command in Command Prompt Window, it works fine. If MyRemoteComputer cannot be reached, it returns error. After that, when I check the exit code with "echo %errorlevel%", it returns 53, which is correct exit code.
I coded with C# using Process like this..
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.FileName = ".....psExec.exe";
startInfo.WorkingDirectory = ".....";
startInfo.Arguments = #"\\MyRemoteComputer -s -c MyInstallationFile.exe /q";
startInfo.UseShellExecute = false;
startInfo.RedirectStandardOutput = true;
startInfo.RedirectStandardError = true;
startInfo.CreateNoWindow = true;
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
Process proc = Process.Start(startInfo);
....
proc.WaitForExit();
Console.WriteLine(proc.ExitCode);
It runs fine..but..when I checked the ExitCode(Obviously, when myRemoteComputer cannot be reached), it was 6, which is other than 53.
It is sort of making sense why it is happening, but is there any way I can retrieve the 53 value, NOT 6?
I tried a couple of things..
cmd /c psExec.exe ....
created a batch file, then output %errorlevel% as a file inside that batch file...then I used this batch file in my ProcessStartInfo....
Environment.GetEnvironmentVariable
None of them worked at all...I can't get my desired return value at all in the code...
There is really no way to retrieve the value I want??
Thanks in advance.
Hi I need to write the result of a mysqldump to a file with a standard windows commands.
System.Diagnostics.Process proc = new System.Diagnostics.Process();
proc.EnableRaisingEvents = false;
proc.StartInfo.WorkingDirectory = "sample directory";
proc.StartInfo.FileName = "mysqldump";
proc.StartInfo.Arguments = "-u root -pPassword --all-databases > db.sql";
proc.StartInfo.RedirectStandardOutput = false;
proc.StartInfo.UseShellExecute = false;
proc.Start();
proc.WaitForExit();
But it doesn't write to file this way...
I don't want to read the output and then write it to file, since mysqldump output can become really big...
Any solutions?
Try executing through cmd.exe and enquote the command to keep your program from gobbling up the redirect:
proc.StartInfo.FileName = "cmd.exe";
proc.startinfo.Arguments =
"/c \"mysqldump -u root -pPassword --all-databases\" > db.sql"
If it's a lot of output you can use the proc.OutputDataReceived event, in the event handler just write the output to your file.
Read the MSDN article here
For piped output you may need ShellExecute to be true. If that doesnt work, you may had to pipe it yourself (i.e. either handle the data events, or have an async read/write loop), but the size shouldn't matter since you should only be reading small chunks of it at any time.
Pretty much on similar lines, but written in VB.NET. Convert it and you should be good... Link
So say I run my program:
Process proc = new Process();
proc.StartInfo.FileName = Path.GetDirectoryName(Application.ExecutablePath)
+ #"\Console.exe";
proc.Start();
And then wish to output my console stream to this application, how would I go about doing so?
So say I have:
Console.WriteLine("HEY!");
I want that to show up in program that I ran's console. I know I have to redirect the output using
Console.SetOut(TextWriter);
But I have no idea how I would go about making it write to the other program.
I can see how I could do it if I were running my main program from Console.exe using RedirectStandardInput.. but that doesn't really help :P
RedirectStandardInput makes Console.exe take its input from a stream which you can access in the main program. You can either write directly to that stream, or use SetOut to redirect console output there...
Process proc = new Process();
proc.StartInfo.FileName = Path.GetDirectoryName(Application.ExecutablePath)
+ #"\Console.exe";
proc.StartInfo.UseShellExecute = false;
proc.StartInfo.RedirectStandardInput = true;
proc.Start();
proc.StandardInput.WriteLine("Hello");
Console.SetOut(proc.StandardInput);
Console.WriteLine("World");
EDIT
It's possible that Console.exe doesn't cope well with having data piped into it rather than entered interactively. You could check this from the command line with something like
echo "Hello" | Console.exe
If that doesn't do what you expect, redirecting your program's output won't either. To test your program without worrying about the target program, you could try
proc.StartInfo.FileName = #"cmd";
proc.StartInfo.Arguments = #"/C ""more""";
If that displays the text that you write to it, then the problem is on the receiving end.
RedirectStandardInput isn't the problem. Console is the problem.
StreamWriter myConsole = null;
if (redirect)
{
Process proc = new Process();
proc.StartInfo.FileName = Path.GetDirectoryName(Application.ExecutablePath)
+ #"\Console.exe";
proc.StartInfo.UseShellExecute = false;
proc.StartInfo.RedirectStandardInput = true;
proc.Start();
myConsole = myProcess.StandardInput;
}
else
myConsole = Console.Out;
Then just use myConsole as you would Console.
You need to use Process.StandardOutput and Process.StandardInput. Check out this article from MSDN, which may help point you into the right direction: http://msdn.microsoft.com/en-us/library/system.diagnostics.process.standardoutput.aspx
By the way, a much easier way to do what you are doing can be found here, as an accepted answer to a similar SO question: c# redirect (pipe) process output to another process
I'm trying to run a Jscript task from a C# console application.
The Jscipt file is not mine so I can't change it. The script moves some files and this is what is causing the issues.
When I run the script manually, i.e. form the shell it executes correctly. When I try and run the script from my console application the bulk of the process runs but I get a ":Error = Permission denied" error when it tries to move the files.
I've tried every permutation of the Diagnostics.Process class that I can think of but I've had no luck.
My current code:
Process process = new Process();
process.StartInfo.WorkingDirectory = Path.GetDirectoryName((string)path);
process.StartInfo.FileName = #"cmd.exe";
process.StartInfo.Arguments = "/C " + (string)path;
process.StartInfo.UseShellExecute = false;
process.StartInfo.Verb = "runas";
process.StartInfo.LoadUserProfile = true;
process.StartInfo.Domain = "admin";
process.StartInfo.UserName = #"cardax_sync_test";
process.StartInfo.Password = GetSecureString("abc123");
process.Start();
process.WaitForExit();
Any ideas?
Thanx
Rookie Mistake!
I forgot to close the text reader that creates one of the input files for the jscript.
I'll submit this question for deletion when it get's old enough. Don't want more useless info clogging up the net!