C# 如何确定cmd.exe何时完成

C# 如何确定cmd.exe何时完成,c#,windows,cmd,C#,Windows,Cmd,我找到了一些代码。它捕获cmd.exe的输出并向其发送输入。我在我们的应用程序中的表单上使用它(经过大量修改)。它运行良好,因此我们可以对用户隐藏cmd.exe,但允许管理员使用此表单。其他好处包括收藏列表等 下面是一些代码。注意:我删除了70%的代码以简化它,因此可能会出现问题。如果有人希望运行此代码,并且他们有问题,请让我知道,我将编辑它并确保它工作正常。它所需要的只是一个带有两个文本框的表单,txtConsoleIn和txtConsoleOut加上一个计时器;tmrSelectedComm

我找到了一些代码。它捕获cmd.exe的输出并向其发送输入。我在我们的应用程序中的表单上使用它(经过大量修改)。它运行良好,因此我们可以对用户隐藏cmd.exe,但允许管理员使用此表单。其他好处包括收藏列表等

下面是一些代码。注意:我删除了70%的代码以简化它,因此可能会出现问题。如果有人希望运行此代码,并且他们有问题,请让我知道,我将编辑它并确保它工作正常。它所需要的只是一个带有两个文本框的表单,txtConsoleIn和txtConsoleOut加上一个计时器;tmrSelectedCommand

public partial class frmCommandPrompt : Form
{
    private bool CancelOutput;
    private bool FirstTime = true;
    private bool InternalCommand;
    private string InternalCommandResponse;
    private ProcessStartInfo psi;
    private Process p;
    private string SelectedCommand;
    private bool SelectedCommandExecuteNow;

    private delegate void InvokeWithString(string text);

    public frmCommandPrompt()
    {
            InitializeComponent();
    }

    private void frmCommandPrompt_Shown(object sender, EventArgs e)
    {
        this.txtConsoleIn.Select();

    }

    private void tmrSelectedCommand_Tick(object sender, EventArgs e)
    {
        tmrSelectedCommand.Enabled = false;
        if (SelectedCommand != string.Empty)
        {
            if (SelectedCommandExecuteNow)
            {
                ExecuteCommand(SelectedCommand);
            }
            else
            {
                txtConsoleIn.Text = SelectedCommand;
                txtConsoleIn.SelectionStart = txtConsoleIn.Text.Length;
                txtConsoleIn.Select();
            }
            SelectedCommand = string.Empty;
            SelectedCommandExecuteNow = false;
        }

    }

    // Sending console commands
    private void txtConsoleIn_KeyUp(object sender, KeyEventArgs e)
    {

        string Command;

        if ((int)e.KeyCode == (int)Keys.Return)
        {
            InternalCommand = false;
            Command = txtConsoleIn.Text;
            ExecuteCommand(Command);
            txtConsoleIn.Clear();
        }
    }

    private void Async_Data_Received(Object sender, DataReceivedEventArgs e)
    {
        if (this.IsHandleCreated)
        {
            this.Invoke(new InvokeWithString(Sync_Output), e.Data);
        }
    }

    private void Sync_Output(string text)
    {
        if (!InternalCommand)
        {
            if (!CancelOutput)
            {
                OutputText(text);
            }
        }
        else
        {
            if (text != String.Empty)
            {
                InternalCommandResponse = text;
                InternalCommand = false;
            }
        }

    }

    private void ExecuteRecentCommand(string Command, bool ExecuteNow)
    {
        SelectedCommand = Command;
        SelectedCommandExecuteNow = ExecuteNow;
        tmrSelectedCommand.Enabled = true;
    }

    private void ExecuteCommand(string Command)
    {
        CancelOutput = false;
        p.StandardInput.WriteLine(Command);
    }

    private void OutputText(string text)
    {
        txtConsoleOut.AppendText(text + Environment.NewLine);
        txtConsoleOut.ScrollToCaret();
    }


}
我想显示路径,比如prompt=$p$G。我可以发出命令echo%cd%并捕获输出,同时抑制该命令和输出。我 然后可以输出这个并添加一个“>”,到目前为止还不错。现在问题来了

有时命令可以更改路径。所以我需要再次检查路径,但是什么时候?如果有人输入长时间运行的命令怎么办?我怎么知道什么时候完成?为了便于使用,我更愿意使它尽可能接近原始的cmd.exe

除了写得不好的批处理文件外,cd是唯一更改路径的命令吗?如果是这样,我可以检查该命令之后的路径。但是,我必须使用一个标签,因为从根发出的像dir*txt/s这样的命令可能需要一些时间,它不仅看起来愚蠢,在该输出的中间抛出路径,而且会使表单更少使用,甚至根本不显示路径。 或者让计时器每隔20秒左右启动另一个cmd.exe实例,以获取路径并将其显示在标签中。听起来像是浪费了很多周期却没有什么收获


在这一点上,最佳选择似乎迫使用户自己检查路径。我可以添加一个按钮来获取路径,使其更简单,但我更喜欢更好的解决方案。

p.WaitForExit()您只是不知道,提示不可靠,您也不知道cmd.exe是否等待命令完成。如果started命令也接受输入,则“提前键入”不可靠。这需要以交互方式正常运行cmd.exe时的方式工作。用户只需等待程序完成,并且只有在知道安全的情况下才能提前输入。@Hans,这正是我所担心的。谢谢你的验证。为什么你需要这样的包装程序?如果我理解正确的话,您无论如何都是从包装程序启动
cmd
,可能控制台窗口是隐藏的;为什么不在控制台窗口可见的情况下启动它,让管理员以通常的方式与之交互?(顺便说一句,在大多数情况下,阻止用户直接访问命令行的安全好处是最小的。)