Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.1k views
in Technique[技术] by (71.8m points)

.net - 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:ProjectsSPPMOSSTesterSPPTesterinDebug>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:

    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?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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).

So you need to read the stream 1 character at a time. 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;
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...