草庐IT

c# - 我正在为 cmd 编写包装器,但在重定向标准输入时遇到问题

coder 2024-06-13 原文

好的,这就是我正在做的事情——我想编写一个将标准输出/输入重定向到富文本框的 .net 应用程序。我已经让它工作得很好,但是一旦我将标准输入添加到混合中,我的读取命令就会卡住。这是我表单中的相关代码。

        Shell = new Process();
        Shell.StartInfo.FileName = "cmd";

        Shell.StartInfo.UseShellExecute = false;
        Shell.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
        Shell.StartInfo.CreateNoWindow = true;

        //Shell.StartInfo.RedirectStandardInput = true;
        Shell.StartInfo.RedirectStandardOutput = true;
        Shell.StartInfo.RedirectStandardError = true;

        Shell.EnableRaisingEvents = true;
        Shell.OutputDataReceived += new DataReceivedEventHandler(Shell_OutputDataReceived);
        Shell.ErrorDataReceived += new DataReceivedEventHandler(Shell_OutputDataReceived);

        Shell.Start();

        Timer consoleReader = new Timer();
        consoleReader.Interval = 200;
        consoleReader.Tick += new EventHandler(consoleReader_Tick);
        consoleReader.Start();
    }

    void consoleReader_Tick(object sender, EventArgs e)
    {
        textArea.AppendText(Shell.StandardOutput.ReadToEnd());
    }

我也尝试过使用 Process 类中可用的异步读取方法来执行此操作,但同样,一旦我将 standardinputredirect = true 添加到组合中,它可能会在读取大约一行后挂断。

有什么想法吗?

[[编辑]] 好的,这是一个示例程序。我将此代码移至控制台应用程序中以简化操作。为什么这个坏了?

using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;

namespace TestAsConsoleApp
{
    class Program
    {
        static Process Shell;
        static void Main(string[] args)
        {
            Shell = new Process();
            Shell.StartInfo.FileName = "cmd";

            Shell.StartInfo.UseShellExecute = false;
            Shell.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
            Shell.StartInfo.CreateNoWindow = true;

            Shell.StartInfo.RedirectStandardInput = true;
            Shell.StartInfo.RedirectStandardOutput = true;
            Shell.StartInfo.RedirectStandardError = true;

            Shell.Start();

            Shell.EnableRaisingEvents = true;
            Shell.OutputDataReceived += new DataReceivedEventHandler(Shell_OutputDataReceived);
            Shell.BeginOutputReadLine();

            Shell.WaitForExit();
        }

        static void Shell_OutputDataReceived(object sender, DataReceivedEventArgs e)
        {
            if (e.Data != null)
                Console.WriteLine(e.Data);
        }
    }
}

最佳答案

修改后的程序看起来没有问题。您创建一个流程请求重定向所有流。您触发对创建的流程输出的异步读取。那你就等着吧。在您的情况下,创建的 cmd.exe 在其输入流中没有获得任何内容,因此它不会产生任何输出。可以试试下面的程序。运行它并给出一些命令,如 dir 等,它将产生输出。希望我没有误解你的问题。

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Diagnostics;

    namespace TestAsConsoleApp
    {
        class Program
        {
            static Process Shell;
            static void Main(string[] args)
            {
                Shell = new Process();
                Shell.StartInfo.FileName = "cmd";

                Shell.StartInfo.UseShellExecute = false;
                Shell.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
                Shell.StartInfo.CreateNoWindow = true;

                Shell.StartInfo.RedirectStandardInput = true;
                Shell.StartInfo.RedirectStandardOutput = true;
                Shell.StartInfo.RedirectStandardError = true;

                Shell.Start();
                //Shell.StandardInput.WriteLine("dir");

                Shell.EnableRaisingEvents = true;
                Shell.OutputDataReceived += new DataReceivedEventHandler(Shell_OutputDataReceived);
                Shell.BeginOutputReadLine();
//read input from your programs input and forward that to the created cmd 's input
                do
                {
                    string aLine = Console.ReadLine();
                    Shell.StandardInput.WriteLine(aLine);
                    if (aLine.ToLower() == "exit")
                        break;
                }while(true);

                Shell.WaitForExit();
            }

            static void Shell_OutputDataReceived(object sender, DataReceivedEventArgs e)
            {
                if (e.Data != null)
                    Console.WriteLine(e.Data);
            }
        }
    }

关于c# - 我正在为 cmd 编写包装器,但在重定向标准输入时遇到问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3486508/

有关c# - 我正在为 cmd 编写包装器,但在重定向标准输入时遇到问题的更多相关文章

  1. ruby - 在 Ruby 中编写命令行实用程序 - 2

    我想用ruby​​编写一个小的命令行实用程序并将其作为gem分发。我知道安装后,Guard、Sass和Thor等某些gem可以从命令行自行运行。为了让gem像二进制文件一样可用,我需要在我的gemspec中指定什么。 最佳答案 Gem::Specification.newdo|s|...s.executable='name_of_executable'...endhttp://docs.rubygems.org/read/chapter/20 关于ruby-在Ruby中编写命令行实用程序

  2. c# - 如何在 ruby​​ 中调用 C# dll? - 2

    如何在ruby​​中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL

  3. ruby - 用 Ruby 编写一个简单的网络服务器 - 2

    我想在Ruby中创建一个用于开发目的的极其简单的Web服务器(不,不想使用现成的解决方案)。代码如下:#!/usr/bin/rubyrequire'socket'server=TCPServer.new('127.0.0.1',8080)whileconnection=server.acceptheaders=[]length=0whileline=connection.getsheaders想法是从命令行运行这个脚本,提供另一个脚本,它将在其标准输入上获取请求,并在其标准输出上返回完整的响应。到目前为止一切顺利,但事实证明这真的很脆弱,因为它在第二个请求上中断并出现错误:/usr/b

  4. C# 到 Ruby sha1 base64 编码 - 2

    我正在尝试在Ruby中复制Convert.ToBase64String()行为。这是我的C#代码:varsha1=newSHA1CryptoServiceProvider();varpasswordBytes=Encoding.UTF8.GetBytes("password");varpasswordHash=sha1.ComputeHash(passwordBytes);returnConvert.ToBase64String(passwordHash);//returns"W6ph5Mm5Pz8GgiULbPgzG37mj9g="当我在Ruby中尝试同样的事情时,我得到了相同sha

  5. ruby-on-rails - Cucumber 是否只是 rspec 的包装器以帮助将测试组织成功能? - 2

    只是想确保我理解了事情。据我目前收集到的信息,Cucumber只是一个“包装器”,或者是一种通过将事物分类为功能和步骤来组织测试的好方法,其中实际的单元测试处于步骤阶段。它允许您根据事物的工作方式组织您的测试。对吗? 最佳答案 有点。它是一种组织测试的方式,但不仅如此。它的行为就像最初的Rails集成测试一样,但更易于使用。这里最大的好处是您的session在整个Scenario中保持透明。关于Cucumber的另一件事是您(应该)从使用您的代码的浏览器或客户端的角度进行测试。如果您愿意,您可以使用步骤来构建对象和设置状态,但通常您

  6. ruby - 将 spawn() 的标准输出/标准错误重定向到 Ruby 中的字符串 - 2

    我想使用spawn(针对多个并发子进程)在Ruby中执行一个外部进程,并将标准输出或标准错误收集到一个字符串中,其方式类似于使用Python的子进程Popen.communicate()可以完成的操作。我尝试将:out/:err重定向到一个新的StringIO对象,但这会生成一个ArgumentError,并且临时重新定义$stdxxx会混淆子进程的输出。 最佳答案 如果你不喜欢popen,这是我的方法:r,w=IO.pipepid=Process.spawn(command,:out=>w,:err=>[:child,:out])

  7. ruby-on-rails - 标准化文件名的字符串,删除重音和特殊字符 - 2

    我正在尝试找到一种方法来规范化字符串以将其作为文件名传递。到目前为止我有这个:my_string.mb_chars.normalize(:kd).gsub(/[^\x00-\x7F]/n,'').downcase.gsub(/[^a-z]/,'_')但第一个问题:-字符。我猜这个方法还有更多问题。我不控制名称,名称字符串可以有重音符、空格和特殊字符。我想删除所有这些,用相应的字母('é'=>'e')替换重音符号,并将其余的替换为'_'字符。名字是这样的:“Prélèvements-常规”“健康证”...我希望它们像一个没有空格/特殊字符的文件名:“prelevements_routin

  8. 基于C#实现简易绘图工具【100010177】 - 2

    C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.

  9. ruby - 我正在学习编程并选择了 Ruby。我应该升级到 Ruby 1.9 吗? - 2

    我完全不是程序员,正在学习使用Ruby和Rails框架进行编程。我目前正在使用Ruby1.8.7和Rails3.0.3,但我想知道我是否应该升级到Ruby1.9,因为我真的没有任何升级的“遗留”成本。缺点是什么?我是否会遇到与普通gem的兼容性问题,或者甚至其他我不太了解甚至无法预料的问题? 最佳答案 你应该升级。不要坚持从1.8.7开始。如果您发现不支持1.9.2的gem,请避免使用它们(因为它们很可能不被维护)。如果您对gem是否兼容1.9.2有任何疑问,您可以在以下位置查看:http://www.railsplugins.or

  10. ruby-on-rails - 如何为空白字段编写 rspec? [Rails3.1] - 2

    我使用rails3.1+rspec和factorygirl。我对必填字段(validates_presence_of)的验证工作正常。我如何让测试将该事实用作“成功”而不是“失败”规范是:describe"Addanindustrywithnoname"docontext"Unabletocreatearecordwhenthenameisblank"dosubjectdoind=Factory.create(:industry_name_blank)endit{shouldbe_invalid}endend但是我失败了:Failures:1)Addanindustrywithnona

随机推荐