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

Bec*_*ker 0 .net c# process batch-file

我有一个按钮,单击它即可执行命令。该命令可能会提示输入一些标准输入,我需要响应该输入,问题是程序运行的方式可能每天都不同,所以我需要解释标准输出并相应地重定向标准输入。

我有这段简单的代码,可以逐行读取标准输出,当它看到密码提示时,它会发送标准输入,但是程序只是挂起,因为它从未看到密码提示,但是当我运行时批处理文件中有密码提示。

这是我调用来执行此测试的批处理文件:

@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%"
Run Code Online (Sandbox Code Playgroud)

以下是从命令行运行该批处理文件的输出:

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"
Run Code Online (Sandbox Code Playgroud)

这是我用来调用挂起的批处理文件的 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();
Run Code Online (Sandbox Code Playgroud)

这是我看到的调试标准输出,请注意,我从未看到输入密码的提示,这是为什么?它只是挂起?

This is a test of a prompt
At the prompt, Enter a response
Run Code Online (Sandbox Code Playgroud)

有没有办法可以观察标准输出的提示并做出相应的反应?

Dav*_*wen 7

您的主要问题是您正在使用流阅读器进行工作,sr.ReadLine()这是一个问题,因为输入密码的提示会停止,直到用户输入新行(输入密码后按 Enter 键)。

所以你需要一次读取流1个字符。这个例子应该可以帮助您入门。

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;
    if(haystackLength < needleLength) {
        return false;
    }

    for (int i = 0; i <= needleLength; i++)
    {
        if (haystack[haystackLength - i] != needle[needleLength - i])
        {
            return false;
        }
    }
    return true;
}
Run Code Online (Sandbox Code Playgroud)