Executing Batch File in C#

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



Leave a reply



Submit