Выполнение пакетного файла в 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)



что я делаю не так?

677   7  

7 ответов:

это должно работать. Вы можете попробовать выгрузить содержимое выходных и ошибочных потоков, чтобы узнать, что происходит:

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*

учитывая дополнительную информацию в вашем комментарии ниже, я смог воссоздать проблему. Кажется, есть некоторые настройки безопасности, которые приводят к такому поведению (не исследовали это подробно).

этой тут работать, если пакетный файл не находится в C:\Windows\System32. Попробуйте переместить его в другое место, например, в расположение исполняемого файла. Обратите внимание, что хранение пользовательских пакетных файлов или исполняемых файлов в каталоге Windows является плохой практикой в любом случае.

* EDIT 2* Это получается что если потоки читаются синхронно, может произойти взаимоблокировка, либо путем синхронного чтения перед WaitForExit и одновременно stderr и stdout синхронно один за другим.

этого не должно произойти, если вместо этого используйте асинхронные методы чтения, как в следующем примере:

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;

Я прокомментировал выключение окна, чтобы я мог видеть, как он работает.

ниже код работал штрафа для меня

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

вы пробовали запустить его в качестве администратора? Запустите Visual Studio в качестве администратора, если вы используете его, потому что работа с .bat файлы требуют этих привилегий.

Comments

    Ничего не найдено.