Executing Batch File in C#
This should work. You could try to dump out the contents of the output and error streams in order to find out what's happening:
static void ExecuteCommand(string command)
{
int exitCode;
ProcessStartInfo processInfo;
Process process;
processInfo = new ProcessStartInfo("cmd.exe", "/c " + command);
processInfo.CreateNoWindow = true;
processInfo.UseShellExecute = false;
// *** Redirect the output ***
processInfo.RedirectStandardError = true;
processInfo.RedirectStandardOutput = true;
process = Process.Start(processInfo);
process.WaitForExit();
// *** Read the streams ***
// Warning: This approach can lead to deadlocks, see Edit #2
string output = process.StandardOutput.ReadToEnd();
string error = process.StandardError.ReadToEnd();
exitCode = process.ExitCode;
Console.WriteLine("output>>" + (String.IsNullOrEmpty(output) ? "(none)" : output));
Console.WriteLine("error>>" + (String.IsNullOrEmpty(error) ? "(none)" : error));
Console.WriteLine("ExitCode: " + exitCode.ToString(), "ExecuteCommand");
process.Close();
}
static void Main()
{
ExecuteCommand("echo testing");
}
* EDIT *
Given the extra information in your comment below, I was able to recreate the problem. There seems to be some security setting that results in this behaviour (haven't investigated that in detail).
This does work if the batch file is not located in C:\Windows\System32
. Try moving it to some other location, e.g. the location of your executable. Note that keeping custom batch files or executables in the Windows directory is bad practice anyway.
* EDIT 2 *
It turns out that if the streams are read synchronously, a deadlock can occur, either by reading synchronously before WaitForExit
or by reading both stderr
and stdout
synchronously one after the other.
This should not happen if using the asynchronous read methods instead, as in the following example:
static void ExecuteCommand(string command)
{
var processInfo = new ProcessStartInfo("cmd.exe", "/c " + command);
processInfo.CreateNoWindow = true;
processInfo.UseShellExecute = false;
processInfo.RedirectStandardError = true;
processInfo.RedirectStandardOutput = true;
var process = Process.Start(processInfo);
process.OutputDataReceived += (object sender, DataReceivedEventArgs e) =>
Console.WriteLine("output>>" + e.Data);
process.BeginOutputReadLine();
process.ErrorDataReceived += (object sender, DataReceivedEventArgs e) =>
Console.WriteLine("error>>" + e.Data);
process.BeginErrorReadLine();
process.WaitForExit();
Console.WriteLine("ExitCode: {0}", process.ExitCode);
process.Close();
}
Executing batch files using C# code
You should be using System.Diagnostics.Process
for this.
Based on your comments, the batch file can take up to 2 minutes to execute. I would implement the following code:
public static int ExecuteBatchFile(string batchFilePath, int timeout, bool killOnTimeout = false)
{
using (var p = Process.Start(batchFilePath))
{
p.WaitForExit(timeout);
if (p.HasExited)
return p.ExitCode;
if (killOnTimeout)
{
p.Kill();
}
else
{
p.CloseMainWindow();
}
throw new TimeoutException(string.Format("Time allotted for executing `{0}` has expired ({1} ms).", batchFilePath, timeout));
}
}
UPDATE If you are executing the batch file form a windows service, then normally you have to disable the user interface. You can do so following this pattern:
ProcessStartInfo info = new ProcessStartInfo(exePath); //exePath must be full path.
info.CreateNoWindow = true;
info.UseShellExecute = false;
Process.Start(info);
Calling Batch File From C#
This should work
System.Diagnostics.Process proc = new System.Diagnostics.Process();
proc.StartInfo.FileName = "C:\\Watcher\\Cleanup.bat";
proc.StartInfo.WorkingDirectory = "C:\\Watcher";
proc.Start();
You need to set the WorkingDirectory otherwise the command will be executed in what is the current directory of the calling application
how to use c# run batch file as Administrator to install windows services
This way worked for me in the past:
string exe = @"C:\Project\Test\InstallUtil.exe";
string args = @"C:\Project\Test\ROServerService\Server\bin\Debug\myservices.exe";
var psi = new ProcessStartInfo();
psi.CreateNoWindow = true; //This hides the dos-style black window that the command prompt usually shows
psi.FileName = @"cmd.exe";
psi.Verb = "runas"; //This is what actually runs the command as administrator
psi.Arguments = "/C " + exe + " " + args;
try {
var process = new Process();
process.StartInfo = psi;
process.Start();
process.WaitForExit();
}
catch (Exception){
//If you are here the user clicked decline to grant admin privileges (or he's not administrator)
}
Note that I'm running the commands in your batch file directly here, but of course you can also run the batch file itself:
string bat = @"C:\path\to\your\batch\file.bat";
var psi = new ProcessStartInfo();
psi.CreateNoWindow = true; //This hides the dos-style black window that the command prompt usually shows
psi.FileName = @"cmd.exe";
psi.Verb = "runas"; //This is what actually runs the command as administrator
psi.Arguments = "/C " + bat;
Executing Batch File At This Directory
Originally posted by use Mofi in comments.
posting the same answer as is so this question is not counted in unanswered, question author also confirms in comments that the answer by Mofi was correct and it helped.
I think enough background, here is the comment as the answer.
In C# code use the method Environment.GetEnvironmentVariable to get the string value of predefined Windows environment variable USERPROFILE to build the paths for exp.bat and starting directory dynamically already within C# application. Or even better get current user desktop folder directly, see How to get a path to the desktop for the current user in C#? – Mofi Feb 22 at 12:25
Running string as a Batch file in c#
You can run CMD.EXE with /c as an executable and have the rest as arguments :
Process.Start("cmd.exe", "/c echo \"bla bla\" \n iperf -c 123 ... ... .. ");
Executing batch file command within C#
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();
Related Topics
Entity Framework Code First - Two Foreign Keys from Same Table
Ef Codefirst: Should I Initialize Navigation Properties
Download Excel File Via Ajax MVC
Cannot Convert from List≪Derivedclass≫ to List≪Baseclass≫
How to Escape Braces (Curly Brackets) in a Format String in .Net
Nullable Types and the Ternary Operator: Why Is '? 10: Null' Forbidden
How to Post Messages to an Sta Thread Running a Message Pump
How to Get the Index of the Current Iteration of a Foreach Loop
Transactionscope Automatically Escalating to Msdtc on Some Machines
Why Is Jsonrequestbehavior Needed
C# String Replace Does Not Actually Replace the Value in the String
Is There a Constraint That Restricts My Generic Method to Numeric Types
How to Save Application Settings in a Windows Forms Application
Pass an Instantiated System.Type as a Type Parameter For a Generic Class