第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

如何從命令中獲取輸出以實時顯示在窗體上的控件中?

如何從命令中獲取輸出以實時顯示在窗體上的控件中?

C#
慕運維8079593 2021-11-14 17:04:43
從網(wǎng)絡上的各種來源,我已經(jīng)把下面的代碼用于經(jīng)由執(zhí)行命令CMD.exe,并從捕獲輸出STDOUT和STDERR。public static class Exec{    public delegate void OutputHandler(String line);    // <summary>    /// Run a command in a subprocess    /// </summary>    /// <param name="path">Directory from which to execute the command</param>    /// <param name="cmd">Command to execute</param>    /// <param name="args">Arguments for command</param>    /// <param name="hndlr">Command output handler (null if none)</param>    /// <param name="noshow">True if no windows is to be shown</param>    /// <returns>Exit code from executed command</returns>    public static int Run(String path, String cmd, String args,                          OutputHandler hndlr = null, Boolean noshow = true)    {        // Assume an error        int ret = 1;        // Create a process        using (var p = new Process())        {            // Run command using CMD.EXE            // (this way we can pipe STDERR to STDOUT so they can get handled together)            p.StartInfo.FileName = "cmd.exe";            // Set working directory (if supplied)            if (!String.IsNullOrWhiteSpace(path)) p.StartInfo.WorkingDirectory = path;            // Indicate command and arguments            p.StartInfo.Arguments = "/c \"" + cmd + " " + args + "\" 2>&1";            // Handle noshow argument            p.StartInfo.CreateNoWindow = noshow;            p.StartInfo.UseShellExecute = false;            // See if handler provided      第一次運行不收集任何輸出,只顯示退出代碼。第二次運行不會收集任何輸出,但會顯示窗口。這樣做的效果是輸出實時出現(xiàn)在控制臺窗口中。第三次運行使用 GetOutput 來收集輸出。這樣做的效果是在運行完成之前不會出現(xiàn)輸出。最后一次運行使用處理程序?qū)崟r接收和顯示輸出。從外觀上看,這看起來像第二次運行,但它非常不同。對于接收到的每一行輸出,調(diào)用 ShowString。Show string 只是顯示字符串。然而,它可以對數(shù)據(jù)做任何它需要的事情。我正在嘗試調(diào)整最后一次運行,以便我可以使用命令的輸出實時更新文本框。我遇到的問題是如何在正確的上下文中使用它(因為沒有更好的術語)。因為 OutputHandler 是異步調(diào)用的,所以它必須使用InvokeRequired/BeginInvoke/EndInvoke機制與 UI 線程同步。我對如何使用參數(shù)執(zhí)行此操作有一點問題。在我的代碼中,文本框可能是選項卡控件中的幾個之一,因為可能會發(fā)生多個背景“運行”。
查看完整描述

1 回答

?
瀟湘沐

TA貢獻1816條經(jīng)驗 獲得超6個贊

代碼在此示例中執(zhí)行的操作的簡要說明:


shell 命令 ( cmd.exe) 首先運行,start /WAIT用作參數(shù)?;蚨嗷蛏倥c以下功能相同/k:控制臺在沒有任何特定任務的情況下啟動,在發(fā)送命令時等待處理命令。


StandardOutput,StandardError并且StandardInput都被重定向,將ProcessStartInfo 的RedirectStandardOutput、RedirectStandardError和RedirectStandardInput屬性設置為。true


控制臺輸出流在寫入時將引發(fā)OutputDataReceived事件;它的內(nèi)容可以從DataReceivedEventArgs的e.Data成員中讀取。將其ErrorDataReceived事件用于相同目的。 您可以對這兩個事件使用單個事件處理程序,但是,經(jīng)過一些測試后,您可能會意識到這可能不是一個好主意。將它們分開可以避免一些奇怪的重疊,并允許輕松區(qū)分錯誤與正常輸出(注意,您可以找到寫入錯誤流而不是輸出流的程序)。

StandardError


StandardInput可以重定向,將其分配給StreamWriter流。

每次將字符串寫入流時,控制臺都會將該輸入解釋為要執(zhí)行的命令。


此外,進程被指示在終止時引發(fā)它的Exited事件,將其EnableRaisingEvents屬性設置為true。

在Exited當該過程被關閉,因為引發(fā)事件Exit命令被處理或調(diào)用.Close()方法(或最終的.Kill()方法,應僅用于whcich僅當一個進程不響應了,對于一些原因)。


由于我們需要將控制臺輸出傳遞給某些 UI 控件(RichTextBoxes在此示例中)并且 Process 事件在 ThreadPool 線程中引發(fā),因此我們必須將此上下文與 UI 同步。

這可以通過使用 Process SynchronizingObject屬性、將其設置為父窗體或使用Control.BeginInvoke方法來完成,該方法將在控件句柄所屬的線程上執(zhí)行委托函數(shù)。

在這里,代表委托的MethodInvoker用于此目的。


用于實例化 Process 并設置其屬性和事件處理程序的核心函數(shù):


using System;

using System.Diagnostics;

using System.IO;

using System.Windows.Forms;


StreamWriter stdin = null;


public partial class frmCmdInOut : Form

{

    Process cmdProcess = null;

    StreamWriter stdin = null;


    public frmCmdInOut() => InitializeComponent();


    private void MainForm_Load(object sender, EventArgs e)

    {

        rtbStdIn.Multiline = false;

        rtbStdIn.SelectionIndent = 20;

    }


    private void btnStartProcess_Click(object sender, EventArgs e)

    {

        btnStartProcess.Enabled = false;

        StartCmdProcess();

        btnEndProcess.Enabled = true;

    }


    private void btnEndProcess_Click(object sender, EventArgs e)

    {

        if (stdin.BaseStream.CanWrite) {

            stdin.WriteLine("exit");

        }

        btnEndProcess.Enabled = false;

        btnStartProcess.Enabled = true;

        cmdProcess?.Close();

    }


    private void rtbStdIn_KeyPress(object sender, KeyPressEventArgs e)

    {

        if (e.KeyChar == (char)Keys.Enter) {

            if (stdin == null) {

                rtbStdErr.AppendText("Process not started" + Environment.NewLine);

                return;

            }


            e.Handled = true;

            if (stdin.BaseStream.CanWrite) {

                stdin.Write(rtbStdIn.Text + Environment.NewLine);

                stdin.WriteLine();

                // To write to a Console app, just 

                // stdin.WriteLine(rtbStdIn.Text); 

            }

            rtbStdIn.Clear();

        }

    }


    private void StartCmdProcess()

    {

        var pStartInfo = new ProcessStartInfo {

             FileName = "cmd.exe",

            // Batch File Arguments = "/C START /b /WAIT somebatch.bat",

            // Test: Arguments = "START /WAIT /K ipconfig /all",

            Arguments = "START /WAIT",

            WorkingDirectory = Environment.SystemDirectory,

            // WorkingDirectory = Application.StartupPath,

            RedirectStandardOutput = true,

            RedirectStandardError = true,

            RedirectStandardInput = true,

            UseShellExecute = false,

            CreateNoWindow = true,

            WindowStyle = ProcessWindowStyle.Hidden,

        };


        cmdProcess = new Process {

            StartInfo = pStartInfo,

            EnableRaisingEvents = true,

            // Test without and with this

            // When SynchronizingObject is set, no need to BeginInvoke()

            //SynchronizingObject = this

        };


        cmdProcess.Start();

        cmdProcess.BeginErrorReadLine();

        cmdProcess.BeginOutputReadLine();

        stdin = cmdProcess.StandardInput;

        // stdin.AutoFlush = true;  <- already true


        cmdProcess.OutputDataReceived += (s, evt) => {

            if (evt.Data != null)

            {

                BeginInvoke(new MethodInvoker(() => {

                    rtbStdOut.AppendText(evt.Data + Environment.NewLine);

                    rtbStdOut.ScrollToCaret();

                }));

            }

        };


        cmdProcess.ErrorDataReceived += (s, evt) => {

            if (evt.Data != null) {

                BeginInvoke(new Action(() => {

                    rtbStdErr.AppendText(evt.Data + Environment.NewLine);

                    rtbStdErr.ScrollToCaret();

                }));

            }

        };


        cmdProcess.Exited += (s, evt) => {

            stdin?.Dispose();

            cmdProcess?.Dispose();

        };

    }

}

由于 StandardInput 已被重定向到 StreamWriter:


stdin = cmdProcess.StandardInput;

我們只需寫入 Stream 以執(zhí)行命令:


stdin.WriteLine(["Command Text"]);

示例表單可以從 PasteBin 下載。

http://img1.sycdn.imooc.com//6190d166000114ce00010020.jpg

查看完整回答
反對 回復 2021-11-14
  • 1 回答
  • 0 關注
  • 289 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網(wǎng)微信公眾號