I have the following code in my C# application which loaded a batch file silently using command prompt and executed and returned the result to a string:
System.Diagnostics.Process proc = new System.Diagnostics.Process();
proc.StartInfo.FileName = #"C:\files\send.bat";
proc.StartInfo.RedirectStandardError = false;
proc.StartInfo.RedirectStandardOutput = true;
proc.StartInfo.UseShellExecute = false;
proc.StartInfo.CreateNoWindow = true;
proc.Start();
string strGetInfo = proc.StandardOutput.ReadToEnd();
strCMDOut = strGetInfo.Substring(strGetInfo.Length - 5, 3);
proc.WaitForExit();
I am trying to avoid my application going out to a different file to execute the batch file, rather I wanted to embed it inside my application. So I changed the above code to this:
System.Diagnostics.Process proc = new System.Diagnostics.Process();
System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
startInfo.FileName = "cmd.exe";
startInfo.Arguments = "#ECHO ON java com.this.test567 send";
startInfo.RedirectStandardOutput = true;
startInfo.UseShellExecute = false;
proc.StartInfo = startInfo;
proc.Start();
string strGetInfo = proc.StandardOutput.ReadToEnd();
strCMDOut = strGetInfo.Substring(strGetInfo.Length - 5, 3);
When the code executes, I can see the command prompt window for a brief moment before it closes and the execution is not working correctly. How can I fix the issue?
Instead of using cmd.exe just use java directly, you should also redirect standard error and check that after the process ends.
System.Diagnostics.Process proc = new System.Diagnostics.Process();
proc.StartInfo.FileName = #"java.exe";
proc.StartInfo.Arguments = "com.this.test567";
proc.StartInfo.RedirectStandardError = true;
proc.StartInfo.RedirectStandardOutput = true;
proc.StartInfo.UseShellExecute = false;
proc.StartInfo.CreateNoWindow = true;
proc.Start();
string strGetInfo = proc.StandardOutput.ReadToEnd();
if(string.IsNullOrEmpty(strGetInfo))
strGetInfo = proc.StandardError.ReadToEnd();
proc.WaitForExit();
Note that by calling cmd directly, you're effectively making a batch script with whatever you use for in the Arguments Property. Like a .bat file, the command window closes as soon as it's done. To fix this, add a pause command to the end.
startInfo.Arguments = "#ECHO ON java com.this.test567 send\npause";
& seperates commands on a line.
&& executes this command only if previous command's errorlevel is 0.
|| (not used above) executes this command only if previous command's errorlevel is NOT 0
> output to a file
>> append output to a file
< input from a file
| output of one command into the input of another command
^ escapes any of the above, including itself, if needed to be passed to a program
so seperate commands with &
"/k #ECHO ON&java com.this.test567&send"
/k keeps a window open.
so you'll get in cmd
cmd /k #ECHO ON&java com.this.test567&send
Related
I am attempting to run a windows command (e.g. whoami) without calling cmd.exe (or powershell) directly using C#.
Within VB this is possible using CreateObject(WScript.Shell) it obviously does not have to be the same method as within the VB, although that would be nice, but I just do not want to call cmd.exe directly.
How would I be able to achieve this?
This runs a console program, waits for exit and reads the output. I changed the cmd to ping since that takes longer and I can verify no console window opens.
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.FileName = "ping.exe";
startInfo.Arguments = "google.com";
startInfo.RedirectStandardOutput = true;
startInfo.UseShellExecute = false;
startInfo.CreateNoWindow = true;
// This wasn't needed
//startInfo.WindowStyle = ProcessWindowStyle.Hidden;
Process processTemp = new Process();
processTemp.StartInfo = startInfo;
processTemp.EnableRaisingEvents = true;
try
{
processTemp.Start();
textBox1.Text = processTemp.StandardOutput.ReadToEnd();
processTemp.WaitForExit();
}
catch (Exception ex)
{
textBox1.Text = ex.Message;
}
You could call whoami.exe and capture the output directly.
The key is UseShellExecute = false to run the executable directly.
var proc = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = #$"{Environment.ExpandEnvironmentVariables("%systemroot%")}\system32\whoami.exe",
Arguments = // Put any command line arguments here
UseShellExecute = false,
RedirectStandardOutput = true,
CreateNoWindow = true
}
};
proc.Start();
string line = proc.StandardOutput.ReadToEnd();
I use sqlcmd to run large script SQL from C# code:
ProcessStartInfo info = new ProcessStartInfo("sqlcmd", #" -S . -i "+ currentDBScript.Value + " -b");
info.UseShellExecute = false;
//No new window is required
info.CreateNoWindow = true;
//The windows style will be hidden
info.WindowStyle = ProcessWindowStyle.Hidden;
//The output will be read by the starndar output process
info.RedirectStandardOutput = true;
Process proc = new Process();
proc.StartInfo = info;
//Start the process
proc.Start();
Note that currentDBScript.Value is the path of my file script
I want to catch error if script executed by sqlcmd didn't succeed.
I'm using C# and I need to execute command in cmd without displaying shell window and retrieve the result, so I did some work like the following:
System.Diagnostics.Process proc = new System.Diagnostics.Process();
proc.StartInfo.FileName = "cmd.exe";
proc.StartInfo.Arguments = command;
proc.StartInfo.UseShellExecute = false;
proc.StartInfo.RedirectStandardError = true;
proc.StartInfo.CreateNoWindow = true;
proc.Start();
string output = string.Empty;
while (!proc.StandardOutput.EndOfStream) {
output = proc.StandardOutput.ReadLine();
}
But when I executed this code, console returned me this error: 'System.InvalidOperationException'(System.dll).
Why is this problem happening and how can I solve this problem?
Thanks to #user2526830 for the code. Based on that code I added few lines to my program since I want to read the output of the SSH command. Below is my code which gives an error at line while
StandardOut has not been redirected or the process hasn't started yet.
What I want to achieve is that I want to read the output of ls into a string.
ProcessStartInfo startinfo = new ProcessStartInfo();
startinfo.FileName = #"f:\plink.exe";
startinfo.Arguments = "-ssh abc#x.x.x.x -pw abc123";
Process process = new Process();
process.StartInfo = startinfo;
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardInput = true;
process.Start();
process.StandardInput.WriteLine("ls -ltr /opt/*.tmp");
process.StandardInput.WriteLine("exit");
process.StartInfo.RedirectStandardOutput = true;
while (!process.StandardOutput.EndOfStream)
{
string line = process.StandardOutput.ReadLine();
}
process.WaitForExit();
Console.ReadKey();
Try setting standard output redirection before starting the process.
process.StartInfo.RedirectStandardOutput = true;
process.Start();
It might be that the process already terminated when you try to read the output (dues to your "exit" command). Try the below slightly modified version where I moved your while loop after the "ls" command but before the "exit" command.
It should read the output of your "ls" command fine, but unfortunately will most probably hang at some point as you will never get EndOfStream on the StandardOutput. When there is nothing more to read, ReadLine will block until it can get read another line.
So unless you know how to detect the last line of the output generated by your command and break out of the loop after you read it, you may need to use a separate thread either for reading or for writing.
ProcessStartInfo startinfo = new ProcessStartInfo();
startinfo.FileName = #"f:\plink.exe";
startinfo.Arguments = "-ssh abc#x.x.x.x -pw abc123";
Process process = new Process();
process.StartInfo = startinfo;
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardInput = true;
process.StartInfo.RedirectStandardOutput = true;
process.Start();
process.StandardInput.WriteLine("ls -ltr /opt/*.tmp");
while (!process.StandardOutput.EndOfStream)
{
string line = process.StandardOutput.ReadLine();
}
process.StandardInput.WriteLine("exit");
process.WaitForExit();
Console.ReadKey();
I have created a Process to run command in CMD.
var process = Process.Start("CMD.exe", "/c apktool d app.apk");
process.WaitForExit();
How can I run this command without displaying actual CMD window?
You can use the WindowsStyle-Property to indicate whether the process is started in a window that is maximized, minimized, normal (neither maximized nor minimized), or not visible
process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden
Source:
Property:MSDN
Enumartion: MSDN
And change your code to this, becaeuse you started the process when initializing the object, so the properties (who got set after starting the process) won't be recognized.
Process proc = new Process();
proc.StartInfo.FileName = "CMD.exe";
proc.StartInfo.Arguments = "/c apktool d app.apk";
proc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
proc.Start();
proc.WaitForExit();
There are several issues with your program, as pointed out in the various comments and answers. I tried to address all of them here.
ProcessStartInfo psi = new ProcessStartInfo();
psi.FileName = "apktool";
//join the arguments with a space, this allows you to set "app.apk" to a variable
psi.Arguments = String.Join(" ", "d", "app.apk");
//leave it to the application, not the OS to launch the file
psi.UseShellExecute = false;
//choose to not create a window
psi.CreateNoWindow = true;
//set the window's style to 'hidden'
psi.WindowStyle = ProcessWindowStyle.Hidden;
var proc = new Process();
proc.StartInfo = psi;
proc.Start();
proc.WaitForExit();
The main issues:
using cmd /c when not necessary
starting the app without setting the properties for hiding it
Try this :
proc.StartInfo.CreateNoWindow = true;
proc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
proc.WaitForExit();
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.CreateNoWindow = true;
startInfo.UseShellExecute = false;
startInfo.FileName = "dcm2jpg.exe";
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
startInfo.Arguments = "-f j -o \"" + ex1 + "\" -z 1.0 -s y " + ex2;