Выполнить несколько командных строк с одним и тем же процессом, используя .NET - PullRequest
51 голосов
/ 13 января 2009

Я пытаюсь выполнить несколько команд без создания нового процесса каждый раз. По сути, я хочу запустить командную оболочку DOS, переключиться на командную оболочку MySQL и выполнить команду. Вот как я называю процедуру (также ниже). Кроме того, как мне обработать "\" в команде?

ExecuteCommand("mysql --user=root --password=sa casemanager", 100, false);

ExecuteCommand(@"\. " + Environment.CurrentDirectory + @"\MySQL\CaseManager.sql", 100, true);

private void ExecuteCommand(string Command, int Timeout, Boolean closeProcess)
{
    ProcessStartInfo ProcessInfo;
    Process Process;

    ProcessInfo = new ProcessStartInfo("cmd.exe", "/C " + Command);
    ProcessInfo.CreateNoWindow = false;
    ProcessInfo.UseShellExecute = false;
    Process = Process.Start(ProcessInfo);
    Process.WaitForExit(Timeout);

    if (closeProcess == true) { Process.Close(); }
}

Ответы [ 8 ]

72 голосов
/ 13 января 2009

Вы можете перенаправить стандартный ввод и использовать StreamWriter для записи в него:

        Process p = new Process();
        ProcessStartInfo info = new ProcessStartInfo();
        info.FileName = "cmd.exe";
        info.RedirectStandardInput = true;
        info.UseShellExecute = false;

        p.StartInfo = info;
        p.Start();

        using (StreamWriter sw = p.StandardInput)
        {
            if (sw.BaseStream.CanWrite)
            {
                sw.WriteLine("mysql -u root -p");
                sw.WriteLine("mypassword");
                sw.WriteLine("use mydb;");
            }
        }
41 голосов
/ 12 апреля 2013
const string strCmdText = "/C command1&command2";
Process.Start("CMD.exe", strCmdText);
11 голосов
/ 13 января 2009

Не могли бы вы просто записать все команды в файл .cmd во временной папке и затем выполнить этот файл?

5 голосов
/ 22 августа 2012
ProcessStartInfo pStartInfo = new ProcessStartInfo();
pStartInfo.FileName = "CMD";
pStartInfo.Arguments = @"/C mysql --user=root --password=sa casemanager && \. " + Environment.CurrentDirectory + @"\MySQL\CaseManager.sql"
pStartInfo.WindowStyle = ProcessWindowStyle.Hidden;
Process.Start(pStartInfo);

&& - это способ сообщить командной оболочке, что существует другая команда для выполнения.

3 голосов
/ 03 января 2019

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

static void RunCommands(List<string> cmds, string workingDirectory = "")
{
    var process = new Process();
    var psi = new ProcessStartInfo();
    psi.FileName = "cmd.exe";
    psi.RedirectStandardInput = true;
    psi.RedirectStandardOutput = true;
    psi.RedirectStandardError = true;
    psi.UseShellExecute = false;
    psi.WorkingDirectory = workingDirectory;
    process.StartInfo = psi;
    process.Start();
    process.OutputDataReceived += (sender, e) => { Console.WriteLine(e.Data); };
    process.ErrorDataReceived += (sender, e) => { Console.WriteLine(e.Data); };
    process.BeginOutputReadLine();
    process.BeginErrorReadLine();
    using (StreamWriter sw = process.StandardInput)
    {
        foreach (var cmd in cmds)
        {
            sw.WriteLine (cmd);
        }
    }
    process.WaitForExit();
}
3 голосов
/ 13 января 2009

Процесс командной строки, такой как cmd.exe или mysql.exe, обычно читает (и выполняет) все, что вы (пользователь) вводите (на клавиатуре).

Чтобы имитировать это, я думаю, вы хотите использовать свойство RedirectStandardInput: http://msdn.microsoft.com/en-us/library/system.diagnostics.processstartinfo.redirectstandardinput.aspx

1 голос
/ 06 июля 2014

Вам необходимо СЧИТАТЬ ВСЕ данные с ввода, прежде чем отправить другую команду!

И вы не можете попросить ПРОЧИТАТЬ, если нет доступных данных ... немного сосать не так?

Мои решения ... когда просят прочитать ... просят прочитать большой буфер ... как 1 МЕГА ...

И вам нужно будет подождать минимум 100 миллисекунд ... пример кода ...

Public Class Form1

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Dim oProcess As New Process()
        Dim oStartInfo As New ProcessStartInfo("cmd.exe", "")
        oStartInfo.UseShellExecute = False
        oStartInfo.RedirectStandardOutput = True
        oStartInfo.RedirectStandardInput = True
        oStartInfo.CreateNoWindow = True
        oProcess.StartInfo = oStartInfo
        oProcess.Start()


        Dim Response As String = String.Empty
        Dim BuffSize As Integer = 1024 * 1024
        Dim x As Char() = New Char(BuffSize - 1) {}
        Dim bytesRead As Integer = 0


        oProcess.StandardInput.WriteLine("dir")
        Threading.Thread.Sleep(100)
        bytesRead = oProcess.StandardOutput.Read(x, 0, BuffSize)
        Response = String.Concat(Response, String.Join("", x).Substring(0, bytesRead))




        MsgBox(Response)
        Response = String.Empty






        oProcess.StandardInput.WriteLine("dir c:\")
        Threading.Thread.Sleep(100)
        bytesRead = 0
        bytesRead = oProcess.StandardOutput.Read(x, 0, BuffSize)
        Response = String.Concat(Response, String.Join("", x).Substring(0, bytesRead))

        MsgBox(Response)


    End Sub
End Class
1 голос
/ 13 января 2009

Вы также можете указать MySQL выполнить команды в данном файле, например:

mysql --user=root --password=sa casemanager < CaseManager.sql
...