2014-10-08 4 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'만으로 새로운 날짜를 입력하라는 명령을 내게됩니다 (명령 행에서 시도해보십시오). 'date/T'를 시도하면 날짜를 출력 할 것이고 아무런 입력을 요구하지 않습니다. 또는 표준 입력에'enter '를 쓸 수도 있습니다. –

답변

1

/c 날짜를 사용하여 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'의 경우'date'에'/ T' 플래그가 필요합니다. 그렇지 않으면'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"); 

, 당신은 실제로 아직 코드를 사용하지 않은 경우에, 그런데 출력

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

냅니다 출력이 방법을

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

또는

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

를 산출 데이터 비동기, 의미 제공 으로으로 프로그램 출력이 전달되므로 100ping, traceroute 등과 같이 시간이 걸리는 프로세스를 실행하면 결과가 완료 될 때까지 기다릴 필요가 없습니다.

또한 중에 응용 프로그램 에 명령을 전달할 수 있습니다. 예를 들어 취소, 반응 및 구문 변경, 또는 첫 번째 실행 결과를 기반으로 비슷한 다른 명령 실행 등이 가능합니다.

기본적으로 cmd 창에 입력하는 것처럼 처리 할 수 ​​있습니다. 피드백을 받으면 적절하게 스레드 된 양식 (다른 스레드의 Windows 컨트롤을 업데이트 할 때주의하십시오)에서 전체 생각을 감싸고 에뮬레이트 된 cmd 프롬프트.

+0

답변을 주셔서 대단히 감사합니다 !!!)))) 매우 유용합니다. 그리고 대단해! 나는 거의 질문이 없다 : 당신의 도구로 "python.exe"와 같은 명령으로부터 어떻게 출력을 얻는가? – neo

+0

python이 경로 명령문에있는 한 cmd 프롬프트와 마찬가지로 작업 할 수 있어야합니다. 파이썬을 시작하고 상호 작용하고 싶습니까? 아니면 파이썬 명령을 자동화하고 출력을 보려고 했습니까? 내가 어디서부터 테스트 할 수없는, 그러나 stderr 및 stdout 출력 경우 cmd를 파이썬 (또는 python 실행 파일에 전체 경로 경로가 아닌 경우) 대체 할 수 있어야합니다. 나는 확실히 알고 테스트해야 할 것입니다. 이 방법으로 CLR로 설치된 .NET 컴파일러를 자동화하는 몇 가지 응용 프로그램을 작성했습니다. – Sabre

+0

cmd.exe를 통해 python.exe를 사용하여 작업을 자동화하고 싶지만 문제가 있습니다. 나는 python stdout과 stderror를 얻을 수 없다. (마치 그것들을 내 응용 프로그램으로 리다이렉트하는 것처럼 보이고 python은 스스로 출력과 에러를 얻을 수 없다.) cmd.exe 대신 python.exe로 프로세스를 실행하면이 동작이 반복된다. 나는 그 문제가 스트림 리다이렉션과 관련이 있다고 생각한다. – neo

관련 문제