[C#] C #에서 배치 파일 실행

C #에서 배치 파일을 실행하려고하는데 운이 좋지 않습니다.

인터넷에서 여러 가지 예제를 찾았지만 작동하지 않습니다.

public void ExecuteCommand(string command)
{
    int ExitCode;
    ProcessStartInfo ProcessInfo;
    Process Process;

    ProcessInfo = new ProcessStartInfo("cmd.exe", "/c " + command);
    ProcessInfo.CreateNoWindow = true;
    ProcessInfo.UseShellExecute = false;

    Process = Process.Start(ProcessInfo);
    Process.WaitForExit();

    ExitCode = Process.ExitCode;
    Process.Close();

    MessageBox.Show("ExitCode: " + ExitCode.ToString(), "ExecuteCommand");
}

명령 문자열에는 배치 파일 (에 저장된 system32) 의 이름 과 조작해야하는 일부 파일이 포함됩니다. (예 🙂 txtmanipulator file1.txt file2.txt file3.txt. 배치 파일을 수동으로 실행하면 올바르게 작동합니다.

코드를 실행할 때 나에게 **ExitCode: 1** (Catch all for general errors)

내가 뭘 잘못하고 있죠?



답변

이 작동합니다. 무슨 일이 일어나고 있는지 확인하기 위해 출력 및 오류 스트림의 내용을 덤프 할 수 있습니다.

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");
}   

* 편집하다 *

아래 의견에 추가 정보가 있으면 문제를 재현 할 수있었습니다. 이 동작을 일으키는 보안 설정이있는 것 같습니다 (자세한 내용은 조사하지 않았습니다).

이것은 않는 배치 파일에 위치하지 않은 경우 작업을 C:\Windows\System32. 실행 파일의 위치와 같은 다른 위치로 이동해보십시오. 어쨌든 Windows 디렉토리에 사용자 정의 배치 파일 또는 실행 파일을 유지하는 것은 좋지 않습니다.

* 2 EDIT
그것은 밝혀 전에 동기식 판독하여 하나의 스트림을 동 기적으로 판독되는 경우에 교착 상태를 초래할 수 WaitForExit또는 모두 읽어 stderrstdout다른 동기 후에 하나.

다음 예제와 같이 비동기 읽기 메소드를 대신 사용하는 경우에는 발생하지 않아야합니다.

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();
}


답변

System.Diagnostics.Process.Start("c:\\batchfilename.bat");

이 간단한 줄은 배치 파일을 실행합니다.


답변

steinar의 큰 도움을 얻은 후에 이것은 나를 위해 일한 것입니다.

public void ExecuteCommand(string command)
{
    int ExitCode;
    ProcessStartInfo ProcessInfo;
    Process process;

    ProcessInfo = new ProcessStartInfo(Application.StartupPath + "\\txtmanipulator\\txtmanipulator.bat", command);
    ProcessInfo.CreateNoWindow = true;
    ProcessInfo.UseShellExecute = false;
    ProcessInfo.WorkingDirectory = Application.StartupPath + "\\txtmanipulator";
    // *** Redirect the output ***
    ProcessInfo.RedirectStandardError = true;
    ProcessInfo.RedirectStandardOutput = true;

    process = Process.Start(ProcessInfo);
    process.WaitForExit();

    // *** Read the streams ***
    string output = process.StandardOutput.ReadToEnd();
    string error = process.StandardError.ReadToEnd();

    ExitCode = process.ExitCode;

    MessageBox.Show("output>>" + (String.IsNullOrEmpty(output) ? "(none)" : output));
    MessageBox.Show("error>>" + (String.IsNullOrEmpty(error) ? "(none)" : error));
    MessageBox.Show("ExitCode: " + ExitCode.ToString(), "ExecuteCommand");
    process.Close();
}


답변

잘 작동합니다. 나는 이것을 다음과 같이 테스트했다.

String command = @"C:\Doit.bat";

ProcessInfo = new ProcessStartInfo("cmd.exe", "/c " + command);
// ProcessInfo.CreateNoWindow = true;

나는 창문을 끄고 주석을 달아서 그것을 볼 수 있다고 언급했다.


답변

다음은이 질문에 대한 답변을 위해 bat / cmd 파일에 2 개의 매개 변수를 보내는 샘플 C # 코드입니다 .

주석 : 매개 변수를 전달하고 명령 실행 결과를 읽으려면 어떻게해야합니까?

/로 @Janatbek Sharsheyev

옵션 1 : 콘솔 창을 숨기거나 인수를 전달하지 않고 출력을 얻지 않음

using System;
using System.Diagnostics;


namespace ConsoleApplication
{
    class Program
    {
        static void Main(string[] args)
        {
         System.Diagnostics.Process.Start(@"c:\batchfilename.bat", "\"1st\" \"2nd\"");
        }
    }
}

옵션 2 : 콘솔 창 숨기기, 인수 전달 및 출력


using System;
using System.Diagnostics;

namespace ConsoleApplication
{
    class Program
    {
        static void Main(string[] args)
        {
         var process = new Process();
         var startinfo = new ProcessStartInfo(@"c:\batchfilename.bat", "\"1st_arg\" \"2nd_arg\" \"3rd_arg\"");
         startinfo.RedirectStandardOutput = true;
         startinfo.UseShellExecute = false;
         process.StartInfo = startinfo;
         process.OutputDataReceived += (sender, argsx) => Console.WriteLine(argsx.Data); // do whatever processing you need to do in this handler
         process.Start();
         process.BeginOutputReadLine();
         process.WaitForExit();
        }
    }
}


답변

아래 코드는 나를 위해 잘 작동했습니다.

using System.Diagnostics;

public void ExecuteBatFile()
{
    Process proc = null;

    string _batDir = string.Format(@"C:\");
    proc = new Process();
    proc.StartInfo.WorkingDirectory = _batDir;
    proc.StartInfo.FileName = "myfile.bat";
    proc.StartInfo.CreateNoWindow = false;
    proc.Start();
    proc.WaitForExit();
    ExitCode = proc.ExitCode;
    proc.Close();
    MessageBox.Show("Bat file executed...");
}


답변

using System.Diagnostics;

private void ExecuteBatFile()
{
    Process proc = null;
    try
    {
        string targetDir = string.Format(@"D:\mydir");   //this is where mybatch.bat lies
        proc = new Process();
        proc.StartInfo.WorkingDirectory = targetDir;
        proc.StartInfo.FileName = "lorenzo.bat";
        proc.StartInfo.Arguments = string.Format("10");  //this is argument
        proc.StartInfo.CreateNoWindow = false;
        proc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;  //this is for hiding the cmd window...so execution will happen in back ground.
        proc.Start();
        proc.WaitForExit();
    }
    catch (Exception ex)
    {
        Console.WriteLine("Exception Occurred :{0},{1}", ex.Message, ex.StackTrace.ToString());
    }
}