簡體   English   中英

c#執行命令行如命令提示符?

[英]c# execute command line like command prompt?

我想編寫ac#代碼來執行一些命令提示行並將結果存儲到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();
}

任何幫助表示贊賞。

我猜也不是所有的應用程序都能正確使用stderr和stdout,所以你在“控制台應用程序”中看到的信息可能無法提供你所期望的信息。

如果沒有更多重定向stderr,也將允許您查看它是否與語法相關並且應用程序正在拋出異常。

startInfo.RedirectStandardError = true;

我想補充一點,通過將其包裝在一個類中,您可以與cmd shell進行交互,而不僅僅是運行並返回...如果您嘗試靜默自動化應用程序,這可能是您想要的方法。 。

我剛剛為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>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

順便說一句,如果你還沒有實際使用的代碼呢,這個方法給出了數據異步,這意味着在遞送到你的程序的輸出,所以如果你運行一個過程,需要時間,像100坪,路由跟蹤等......你看到它們發生的時候,不必等待它完成並返回。

此外,您可以在此期間將命令傳遞回應用程序,例如取消,響應和更改語法,或者根據第一次運行的結果運行其他類似的操作。

基本上你可以像在cmd窗口中輸入一樣對待它,並在那里接收反饋,以正確的線程形式包裝整個思考(從其他線程更新Windows控件時小心),你會有一個模擬的cmd提示符。

你需要使用/ 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();
}

使用cmd.exe啟動其他程序時,flags / c和/ k是您的朋友。 / c用於執行程序然后退出CMD。 / k用於執行程序,然后讓CMD運行。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM