簡體   English   中英

來自C#的命令提示卡住

[英]Command prompt from C# get stuck

前幾天我問了這個問題 ,但是我既沒有答案,也無法解決。 因此,我試着將其縮小,因為這是一個很大的問題。

問題是,如果我在網絡api中將所有內容公開給運行cmd.exe的方法,那么如果我對每個請求都沒有兩次調用它,那么它將正常工作。

我的意思是,這段代碼可以正常工作:

public class FilesController : ApiController
{
    private readonly IRunner _runner;

    public FilesController(IRunner runner)
    {
        _runner = runner;
    }

    public string Get()
    {
        return _runner.GetFiles();
    }
}

public class Runner : IRunner
{
    public Runner()
    {
        //var cd = @"cd C:\DummyFolder";
        //RunCmdPromptCommand(cd);
    }

    public string GetFiles()
    {
        var dir = @"cd C:\DummyFolder & dir";
        //var dir = "dir";
        return RunCmdPromptCommand(dir);
    }

    private string RunCmdPromptCommand(string command)
    {
        var process = new Process
        {
            StartInfo =
            {
                UseShellExecute = false,
                CreateNoWindow = true,
                WindowStyle = ProcessWindowStyle.Hidden,
                RedirectStandardError = true,
                RedirectStandardOutput = true,
                FileName = @"cmd.exe",
                Arguments = string.Format("/C {0}", command)
            }
        };

        process.Start();
        var error = process.StandardError.ReadToEnd();

        if (!string.IsNullOrEmpty(error))
        {
            throw new Exception(error);
        }

        var output = process.StandardOutput.ReadToEnd();

        process.WaitForExit();

        return output;
    }
}

但是,如果我取消注釋行的注釋(並且顯然注釋掉GetFiles的第一行,則當代碼第二次到達(即帶有“ dir”) RunCmdPromptCommand它將卡在試圖讀取標准錯誤的行中。

我不知道為什么,我也不知道如何在可能發生時強制退出(可能是其他可能發生的情況)

謝謝,

這是因為:

process.StandardOutput.ReadToEnd();

是同步操作。

MSDN摘錄:

重定向的StandardError流可以同步或異步讀取。 Read,ReadLine和ReadToEnd之類的方法對進程的錯誤輸出流執行同步讀取操作。 在關聯的Process 寫入其StandardError流或關閉該流之前,這些同步讀取操作不會完成

換句話說,只要該過程不寫任何標准錯誤或關閉流,它就會永遠卡在那里。

要解決此問題,我建議使用Async BeginErrorReadLine MSDN摘錄:

相反, BeginErrorReadLine在StandardError流上啟動異步讀取操作。 此方法為流輸出啟用指定的事件處理程序,並立即返回到調用方, 在將流輸出定向到事件處理程序時 ,調用方可以執行其他工作

我認為這將適合您的需求。

要使用它。 MSDN中給出的示例非常簡單。 特別檢查以下幾行:

 netProcess.ErrorDataReceived += new DataReceivedEventHandler(NetErrorDataHandler); //note this event handler add

if (errorRedirect) //in your case, it is not needed
{
    // Start the asynchronous read of the standard
    // error stream.
    netProcess.BeginErrorReadLine(); //note this
}

以及如何定義事件處理程序:

private static void NetErrorDataHandler(object sendingProcess, 
    DataReceivedEventArgs errLine)
{
    // Write the error text to the file if there is something
    // to write and an error file has been specified.

    if (!String.IsNullOrEmpty(errLine.Data))
    {
        if (!errorsWritten)
        {
            if (streamError == null)
            {
                // Open the file.
                try 
                {
                    streamError = new StreamWriter(netErrorFile, true);
                }
                catch (Exception e)
                {
                    Console.WriteLine("Could not open error file!");
                    Console.WriteLine(e.Message.ToString());
                }
            }

            if (streamError != null)
            {
                // Write a header to the file if this is the first
                // call to the error output handler.
                streamError.WriteLine();
                streamError.WriteLine(DateTime.Now.ToString());
                streamError.WriteLine("Net View error output:");
            }
            errorsWritten = true;
        }

        if (streamError != null)
        {
            // Write redirected errors to the file.
            streamError.WriteLine(errLine.Data);
            streamError.Flush();
        }
    }
}

暫無
暫無

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

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