C# Process.StandardOutput.ReadLine() 挂起 [英] C# Process.StandardOutput.ReadLine() hangs

查看:244
本文介绍了C# Process.StandardOutput.ReadLine() 挂起的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以基本上 ReadLine() 方法只是挂在最后一个输出行上.

So basicly the ReadLine() method just hangs right on the last output line.

我不需要结束这个过程.主要目标是做cmd-shell"使用标准输入和标准输出(在变量中/打印出来).

I dont need to end the process. The main goal is to do "cmd-shell" with stdin and stdout (in variables/Printed out).

如果使用异步方法可以实现相同的效果,请在评论中留言.提前致谢.

If the same can be achieved with async methods, please, leave it in comments. Thanks in advance.

        {
            Process p = new Process()
            {
                StartInfo = new ProcessStartInfo("cmd")
                {
                    UseShellExecute = false,
                    RedirectStandardInput = true,
                    RedirectStandardError = true,
                    RedirectStandardOutput = true,
                    CreateNoWindow = true,
                    Arguments = "/K",
                    
                }
            };
            p.ErrorDataReceived += (s, e) =>
            {
                if (!string.IsNullOrEmpty(e.Data))
                {
                    Console.WriteLine(e.Data);
                }
            };
            p.Start();
            while (true)
            {
                Console.Write("/SHELL/ #> ");
                input = Console.ReadLine();
                p.StandardInput.WriteLine(input);
                p.BeginErrorReadLine();
                Console.WriteLine("Errorgoing...");
                while (p.StandardOutput.Peek() > -1) {
                    Console.WriteLine(p.StandardOutput.Peek());
                    Console.WriteLine(p.StandardOutput.ReadLine());
                    
                    // When it hangs, Peek() outputs 67, that represents "C" char.
                    // Seems like just the last stdout line dont want to be printed out.
                }
            }
        }
    }```

推荐答案

在实施了一些技巧之后,我最终得到了以下代码.相当棘手.

After few implemented tricks I've ended up with the following code. Quite tricky.

static async Task Main(string[] args)
{
    using (SemaphoreSlim semaphore = new SemaphoreSlim(0, 1))
    {
        Process p = new Process()
        {
            StartInfo = new ProcessStartInfo("cmd")
            {
                UseShellExecute = false,
                RedirectStandardInput = true,
                RedirectStandardError = true,
                RedirectStandardOutput = true,
                CreateNoWindow = true,
                Arguments = "/K set PROMPT=PROMPT$P$G$_",
            }
        };
        p.ErrorDataReceived += (s, e) =>
        {
            if (e.Data?.Length > 0)
            {
                Console.WriteLine(e.Data);
            }
        };
        bool wasprompt = false;
        string prompt = "";
        p.OutputDataReceived += (s, e) =>
        {
            if (e.Data?.Length > 0)
            {
                if (e.Data.StartsWith("PROMPT") && e.Data.EndsWith(">"))
                {
                    prompt = e.Data.Substring(6, e.Data.Length - 7);
                    semaphore.Release();
                    wasprompt = true;
                }
                else
                {
                    if (!wasprompt)
                        Console.WriteLine(e.Data);
                    else
                        wasprompt = false;
                }
            }
        };
        p.Start();
        p.BeginErrorReadLine();
        p.BeginOutputReadLine();
        await semaphore.WaitAsync();
        while (!p.HasExited)
        {
            Console.Write($"/SHELL/ {prompt}#> ");
            string input = Console.ReadLine();
            p.StandardInput.WriteLine(input);
            if (input == "exit") break;
            await semaphore.WaitAsync();
        }
        p.WaitForExit();
    }

    Console.WriteLine("Bye.");
    Console.ReadKey();
}

经过几次测试,看起来像您预期的那样工作.

Few times tested and looks like it works as you expect.

这个想法是将 $_ 添加到 PROMPT 环境变量以强制打印的提示输出.然后我捕捉到该提示并使用 SemaphoreSlim 实现输入/输出同步.

The idea was adding $_ to PROMPT environment variable to force the prompt printed to output. Then I catch that prompt and implement input/output synchronization with SemaphoreSlim.

这篇关于C# Process.StandardOutput.ReadLine() 挂起的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆