简体   繁体   English

C#流程调用,与标准输入和标准输出交互

[英]C# Process Call, Interact with Standard Input and Standard Output

I have a button I click that executes a command. 我单击一个按钮即可执行命令。 The command may prompt for some standard input and I need to respond to that input, the problem is the way the program runs may be different from day to day so I need to interpret the standard output and redirect standard input accordingly. 该命令可能会提示您输入一些标准输入,而我需要响应该输入,问题是程序的运行方式可能每天都不同,因此我需要解释标准输出并相应地重定向标准输入。

I have this simple piece of code that reads the standard output line by line and when it sees a prompt for password, it'll send standard input, however the program just hangs since it never sees the prompt for the password, but when I run the batch file the password prompt is there. 我有一段简单的代码,它逐行读取标准输出,当它看到输入密码的提示时,它将发送标准输入,但是该程序挂起了,因为它从未看到输入密码的提示,但是当我运行时批处理文件中会出现密码提示。

Here is the batch file I am calling to execute this test: 这是我要执行此测试的批处理文件:

@echo off
echo This is a test of a prompt
echo At the prompt, Enter a response
set /P p1=Enter the Password: 
echo you entered "%p1%"

Here is the output of that batch file when run from the command line: 这是从命令行运行时该批处理文件的输出:

C:\Projects\SPP\MOSSTester\SPPTester\bin\Debug>test4.bat
This is a test of a prompt
At the prompt, Enter a response
Enter the Password: Test1
you entered "Test1"

Here is the C# snippet I am using to call the batch file that is hanging: 这是我用来调用挂起的批处理文件的C#代码段:

    var proc = new Process();
    proc.StartInfo.FileName = "cmd.exe";
    proc.StartInfo.Arguments = "/c test4.bat";
    proc.StartInfo.RedirectStandardOutput = true;
    proc.StartInfo.RedirectStandardError = true;
    proc.StartInfo.RedirectStandardInput = true;
    proc.StartInfo.UseShellExecute = false;
    proc.StartInfo.CreateNoWindow = true;
    proc.Start();
    //read the standard output and look for prompt for password
    StreamReader sr = proc.StandardOutput;
    while (!sr.EndOfStream)
    {
        string line = sr.ReadLine();
        Debug.WriteLine(line);
        if (line.Contains("Password"))
        {
            Debug.WriteLine("Password Prompt Found, Entering Password");
            proc.StandardInput.WriteLine("thepassword");
        }
    }
    sr.Close();
    proc.WaitForExit();

Here is the debug standard output I see, notice that I never see the prompt for the password, why is this? 这是我看到的调试标准输出,请注意,我从未看到输入密码的提示,这是为什么? it just hangs? 它只是挂?

This is a test of a prompt
At the prompt, Enter a response

Is there a way I can watch the standard output for prompting and react to it accordingly? 有什么方法可以观察标准输出的提示并做出相应的反应?

Your main problem is that you are working through the stream reader using sr.ReadLine() this is an issue because the prompt for a password halts until the user enters a new line (hits enter after typing the password). 您的主要问题是您正在使用sr.ReadLine()浏览流阅读器,这是一个问题,因为在用户输入新行之前,直到您输入新行时,密码提示才会停止(在输入密码后按回车键)。

So you need to read the stream 1 character at a time. 因此,您需要一次读取流1字符。 This example should help you get started. 此示例应帮助您入门。

while (!sr.EndOfStream)
{
    var inputChar = (char)sr.Read();
    input.Append(inputChar);
    if (StringBuilderEndsWith(input, Environment.NewLine))
    {
        var line = input.ToString();
        input = new StringBuilder();
        Debug.WriteLine(line);
    }
    else if (StringBuilderEndsWith(input, "Password:"))
    {
        Debug.WriteLine("Password Prompt Found, Entering Password");
        proc.StandardInput.WriteLine("thepassword");
        var line = input.ToString();
        input = new StringBuilder();
        Debug.WriteLine(line);
    }
}

private static bool StringBuilderEndsWith(StringBuilder haystack, string needle)
{
    var needleLength = needle.Length - 1;
    var haystackLength = haystack.Length - 1;
    for (int i = 0; i < needleLength; i++)
    {
        if (haystack[haystackLength - i] != needle[needleLength - i])
        {
            return false;
        }
    }
    return true;
}

With the process class you can run the batch file directly. 使用流程类,您可以直接运行批处理文件。 The standard I/O might not be getting through since it has to go through cmd first 标准I / O可能无法通过,因为它必须先通过cmd

proc.StartInfo.FileName = "test4.bat";
proc.StartInfo.Arguments = "";

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM