2014-10-08 3 views
1

Я хочу написать код C# для выполнения некоторых строк командной строки и сохранить результат в глобальной переменной в C#, которая будет использоваться для дальнейшей обработки в другой части кода в C#.C# выполнить командную строку, например, командную строку?

Я купил устройство, и я установил его драйвер. Единственный способ получить мои данные - использовать командную строку в командной строке. API недоступен. Но я хочу сделать это в C#, поэтому у меня возникают проблемы.

У меня есть код, и по какой-то причине он не работает. Заметьте, я использовал аргумент input = "date" только для иллюстрации. Моя работа не использует «дату», а некоторые аргументы для получения данных.

static void Main(string[] args) 
{ 
    System.Diagnostics.Process process = new System.Diagnostics.Process(); 
    System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo(); 
    startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden; 
    // the cmd program 
    startInfo.FileName = "cmd.exe"; 
    // set my arguments. date is just a dummy example. the real work isn't use date. 
    startInfo.Arguments = "date"; 
    startInfo.RedirectStandardOutput = true; 
    startInfo.UseShellExecute = false; 
    process.StartInfo = startInfo; 
    process.Start(); 
    // capture what is generated in command prompt 
    var output = process.StandardOutput.ReadToEnd(); 
    // write output to console 
    Console.WriteLine(output); 
    process.WaitForExit(); 

    Console.Read(); 
} 

Любая помощь приветствуется.

+5

'поэтому поэтому у меня проблемы: какая проблема? «это не работает» не является описанием проблемы. Что оно делает? Сбой? Дайте ошибку? Свернуть в сингулярность? Ничего не делать? Что вы ожидаете от этого? –

+0

Вероятно, ваша проблема заключается в том, что сама «дата» предлагает ввести новую дату (попробуйте в командной строке). Попробуйте 'date/T', который выведет дату и не потребует от вас ввода каких-либо данных. Кроме того, вы можете просто написать «enter» на стандартный ввод. –

ответ

1

вам нужно будет использовать/c date, чтобы получить cmd для запуска такой даты.

static void Main(string[] args) 
{ 
    System.Diagnostics.Process process = new System.Diagnostics.Process(); 
    System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo(); 
    startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden; 
    // the cmd program 
    startInfo.FileName = "cmd.exe"; 
    // set my arguments. date is just a dummy example. the real work isn't use date. 
    startInfo.Arguments = "/c date"; 
    startInfo.RedirectStandardOutput = true; 
    startInfo.UseShellExecute = false; 
    process.StartInfo = startInfo; 
    process.Start(); 
    // capture what is generated in command prompt 
    var output = process.StandardOutput.ReadToEnd(); 
    // write output to console 
    Console.WriteLine(output); 
    process.WaitForExit(); 

    Console.Read(); 
} 

флагов/c и/k являются вашими друзьями при использовании cmd.exe для запуска других программ./c используется для выполнения программы, а затем выхода из CMD./k используется для выполнения программы, а затем покидает CMD.

+0

В случае 'date' вам также нужен флаг'/T' для 'date', иначе вам нужно перенаправить на него' StandardInput' и 'WriteLine'. –

+0

спасибо. но код по-прежнему не указывает дату. Пусто. – CB4

+0

на самом деле это работает. что-то не так с датой. Я попробовал ipconfig, и он дает данные. отличная работа. – CB4

2

Я бы также предположил, что не все приложения используют stderr и stdout правильно, поэтому возможно, что вы видите в «Консольном приложении», не доставляя информацию там, где вы ожидаете.

Если ничего более перенаправляемого stderr также, вы также можете увидеть, связано ли это синтаксис, и приложение бросает исключение.

startInfo.RedirectStandardError = true; 

Я хочу добавить к этому, обернув его в классе, вы можете взаимодействовать с CMD оболочки, а не просто бежать и вернуться ... Если вы пытаетесь автоматизировать приложение молча, это вероятно, подход, который вы хотите ...

Я только что написал образец этого для парня в VB, синтаксис, вероятно, был грубым, потому что я не запускал VB годами, но вы получаете суть этого и должны быть в состоянии для репликации на C# довольно легко. Это был черновик Как типа подход, а не кусок кода, который я бы назвал готовый к производству, научить человека к образцу рыбы;)

#Region " Imports " 

Imports System.Threading 
Imports System.ComponentModel 

#End Region 

Namespace Common 

    Public Class CmdShell 

#Region " Variables " 

     Private WithEvents ShellProcess As Process 

#End Region 

#Region " Events " 

     ''' <summary> 
     ''' Event indicating an asyc read of the command process's StdOut pipe has occured. 
     ''' </summary> 
     Public Event DataReceived As EventHandler(Of CmdShellDataReceivedEventArgs) 

#End Region 

#Region " Public Methods " 

     Public Sub New() 
      ThreadPool.QueueUserWorkItem(AddressOf ShellLoop, Nothing) 
      Do Until Not ShellProcess Is Nothing : Loop 
     End Sub 

     ''' <param name="Value">String value to write to the StdIn pipe of the command process, (CRLF not required).</param> 
     Public Sub Write(ByVal value As String) 
      ShellProcess.StandardInput.WriteLine(value) 
     End Sub 

#End Region 

#Region " Private Methods " 

     Private Sub ShellLoop(ByVal state As Object) 
      Try 
       Dim SI As New ProcessStartInfo("cmd.exe") 
       With SI 
        .Arguments = "/k" 
        .RedirectStandardInput = True 
        .RedirectStandardOutput = True 
        .RedirectStandardError = True 
        .UseShellExecute = False 
        .CreateNoWindow = True 
        .WorkingDirectory = Environ("windir") 
       End With 
       Try 
        ShellProcess = Process.Start(SI) 
        With ShellProcess 
         .BeginOutputReadLine() 
         .BeginErrorReadLine() 
         .WaitForExit() 
        End With 
       Catch ex As Exception 
        With ex 
         Trace.WriteLine(.Message) 
         Trace.WriteLine(.Source) 
         Trace.WriteLine(.StackTrace) 
        End With 
       End Try 
      Catch ex As Exception 
       With ex 
        Trace.WriteLine(.Message) 
        Trace.WriteLine(.Source) 
        Trace.WriteLine(.StackTrace) 
       End With 
      End Try 
     End Sub 

     Private Sub ShellProcess_ErrorDataReceived(ByVal sender As Object, ByVal e As System.Diagnostics.DataReceivedEventArgs) Handles ShellProcess.ErrorDataReceived 
      If Not e.Data Is Nothing Then RaiseEvent DataReceived(Me, New CmdShellDataReceivedEventArgs(e.Data)) 
     End Sub 

     Private Sub ShellProcess_OutputDataReceived(ByVal sender As Object, ByVal e As System.Diagnostics.DataReceivedEventArgs) Handles ShellProcess.OutputDataReceived 
      If Not e.Data Is Nothing Then RaiseEvent DataReceived(Me, New CmdShellDataReceivedEventArgs(e.Data & Environment.NewLine)) 
     End Sub 

#End Region 

    End Class 

    <EditorBrowsable(EditorBrowsableState.Never)> _ 
     Public Class CmdShellDataReceivedEventArgs : Inherits EventArgs 
     Private _Value As String 

     Public Sub New(ByVal value As String) 
      _Value = value 
     End Sub 

     Public ReadOnly Property Value() As String 
      Get 
       Return _Value 
      End Get 
     End Property 

    End Class 

End Namespace 

Просто, чтобы убедиться, что не было никаких подводных камней, я пошел вперед и сделал это грязный в C#

public class cmdShell 
    { 
     private Process shellProcess; 

     public delegate void onDataHandler(cmdShell sender, string e); 
     public event onDataHandler onData; 

     public cmdShell() 
     { 
      try 
      { 
       shellProcess = new Process(); 
       ProcessStartInfo si = new ProcessStartInfo("cmd.exe"); 
       si.Arguments = "/k"; 
       si.RedirectStandardInput = true; 
       si.RedirectStandardOutput = true; 
       si.RedirectStandardError = true; 
       si.UseShellExecute = false; 
       si.CreateNoWindow = true; 
       si.WorkingDirectory = Environment.GetEnvironmentVariable("windir"); 
       shellProcess.StartInfo = si; 
       shellProcess.OutputDataReceived += shellProcess_OutputDataReceived; 
       shellProcess.ErrorDataReceived += shellProcess_ErrorDataReceived; 
       shellProcess.Start(); 
       shellProcess.BeginErrorReadLine(); 
       shellProcess.BeginOutputReadLine(); 
      } 
      catch (Exception ex) 
      { 
       Trace.WriteLine(ex.Message); 
      } 
     } 

     void shellProcess_ErrorDataReceived(object sender, DataReceivedEventArgs e) 
     { 
      doOnData(e.Data); 
     } 

     void shellProcess_OutputDataReceived(object sender, DataReceivedEventArgs e) 
     { 
      doOnData(e.Data); 
     } 

     private void doOnData(string data) 
     { 
      if (onData != null) onData(this, data); 
     } 

     public void write(string data) 
     { 
      try 
      { 
       shellProcess.StandardInput.WriteLine(data); 
      } 
      catch (Exception ex) 
      { 
       Trace.WriteLine(ex.Message); 
      } 
     } 
    } 

Так что теперь, используя как этот

cmdShell test = new cmdShell(); 
test.onData += test_onData; 
test.write("ping 127.0.0.1"); 

с этим на месте

void test_onData(cmdShell sender, string e) 
     { 
      Trace.WriteLine(e); 
     } 

У вас есть полностью интерактивный процесс cmd для записи и получения асинхронных данных.

выводит в окне

C:\Windows>ping 127.0.0.1 

Pinging 127.0.0.1 with 32 bytes of data: 
Reply from 127.0.0.1: bytes=32 time<1ms TTL=128 
Reply from 127.0.0.1: bytes=32 time<1ms TTL=128 
Reply from 127.0.0.1: bytes=32 time<1ms TTL=128 
Reply from 127.0.0.1: bytes=32 time<1ms TTL=128 

Ping statistics for 127.0.0.1: 
    Packets: Sent = 4, Received = 4, Lost = 0 (0% loss), 
Approximate round trip times in milli-seconds: 
    Minimum = 0ms, Maximum = 0ms, Average = 0ms 

кофе, сон ... лол

Если вы действительно хотите дату ...

cmdShell test = new cmdShell(); 
test.onData += test_onData; 
test.write("date"); 

Урожайность OUTPUT

C:\Windows>date 
The current date is: Wed 10/08/2014 

или

cmdShell test = new cmdShell(); 
    test.onData += test_onData; 
    test.write("echo %date%"); 

Урожайность выход

C:\Windows>echo %date% 
Wed 10/08/2014 

Кстати, в случае, если вы на самом деле не используется код все же, этот метод дает данные async, что означает как выходы программы передаются вам, поэтому, если вы запустите процесс, требующий времени, например, 100 pings, traceroute и т. Д., Вы увидите их, как они есть, не нужно дождаться завершения и возврата.

Также вы можете передать команды обратно в приложение во время, что, как отмена, реагирование и изменение синтаксиса, или просто выполнение чего-то другого похожего на основе результата первого запуска.

По существу, вы можете относиться к нему так же, как вы печатали в CMD-окне, и получать обратную связь там, обернуть все мыслить в правильно нарезанной форме (осторожно при обновлении элементов управления Windows из других потоков), и у вас будет эмулировать подсказку cmd.

+0

Большое спасибо за ваш ответ !!!))))) Это очень-очень полезно и здорово! У меня мало вопросов: как получить результат из команды, например, «python.exe» с помощью вашего инструмента? – neo

+0

до тех пор, пока python находится в вашем указателе пути, вы должны иметь возможность работать с ним так же, как и с приглашением cmd. Вы хотите запустить python и взаимодействовать с ним? Или вы хотите автоматизировать команду на python и просто просмотреть результат? Я не могу проверить, откуда я, однако, если он выводится на stderr и stdout, вы должны просто заменить cmd на python (или полный путь к исполняемому файлу python, если не в пути), я должен был бы проверить, чтобы знать наверняка. Я написал несколько приложений, которые автоматизируют компиляторы .NET, установленные с CLR таким образом. – Sabre

+0

Я хочу автоматизировать работу с python.exe через cmd.exe, но у меня есть проблема. Я не могу получить python stdout и stderror (((похоже, что я перенаправляю их на свое приложение, и python не смог получить их сам для вывода и ошибок. Если я запустил процесс с python.exe вместо cmd.exe, это поведение повторяется Я думаю, что проблема, связанная с перенаправлением потоков. – neo

Смежные вопросы