【问题标题】:C# Interacting with CLI Process - Standard Input Not WorkingC# 与 CLI 进程交互 - 标准输入不起作用
【发布时间】:2017-01-24 21:03:36
【问题描述】:

我编写了以下代码。由于某种原因, StreamWriter / RedirectStandardInput 似乎无法正常工作。我尝试与之交互的 CLI 似乎不接受甚至接收我输入的命令。

还有一些我也不明白的奇怪的事情。我必须使用 While 循环来读取 StandardOutput 的所有行。

process.StandardOutput.ReadToEnd();

什么都不返回。只有 ReadLine(); 似乎被识别。

编辑

我现在还注意到,如果我在任何 process.StandardInput.WriteLine(""); 之后设置断点调用,断点永远不会到达。该过程永远不会返回到我的 C# 代码。

这也发生在我的 process.StandardOutput.ReadLine() 循环之后。当它到达最后一行时,它永远不会返回到我的 c# 代码。

代码如下:

        Process process = new Process();
        process.StartInfo.FileName = @"C:\Program Files (x86)\Cisco\Cisco AnyConnect Secure Mobility Client\vpncli.exe";
        process.StartInfo.RedirectStandardInput = true;
        process.StartInfo.RedirectStandardOutput = true;
        process.StartInfo.RedirectStandardError = true;
        process.StartInfo.UseShellExecute = false;
        process.StartInfo.CreateNoWindow = true;
        process.Start();


        process.StandardInput.AutoFlush = true;
        string line = string.Empty;
        while ((line = process.StandardOutput.ReadLine()) != null)
        {
            Console.WriteLine("CLI Says: " + line);
        }

        process.StandardInput.WriteLine("connect vpn.service.domain.com");

        line = string.Empty;
        while ((line = process.StandardOutput.ReadLine()) != null)
        {
            Console.WriteLine("CLI Says: " + line);
        }

        process.StandardInput.WriteLine("0");

        line = string.Empty;
        while ((line = process.StandardOutput.ReadLine()) != null)
        {
            Console.WriteLine("CLI Says: " + line);
        }

        process.StandardInput.WriteLine("MyUsername");

        line = string.Empty;
        while ((line = process.StandardOutput.ReadLine()) != null)
        {
            Console.WriteLine("CLI Says: " + line);
        }

        process.StandardInput.WriteLine("MyPassword");

        line = string.Empty;
        while ((line = process.StandardOutput.ReadLine()) != null)
        {
            Console.WriteLine("CLI Says: " + line);
        }

我在调试控制台中收到的输出是:

CLI Says: Cisco AnyConnect Secure Mobility Client (version 3.1.10010) .
CLI Says: 
CLI Says: 
CLI Says: Copyright (c) 2004 - 2015 Cisco Systems, Inc.  All Rights Reserved.
CLI Says: 
CLI Says: 
CLI Says: 
CLI Says: 
CLI Says:   >> state: Disconnected
CLI Says: 
CLI Says: 
CLI Says: VPN> 
CLI Says:   >> state: Disconnected
CLI Says: 
CLI Says: 
CLI Says: VPN> 
CLI Says:   >> notice: Ready to connect.
CLI Says: 
CLI Says: 
CLI Says: VPN> 
CLI Says:   >> registered with local VPN subsystem.
CLI Says: 
CLI Says: 
CLI Says: VPN> 

【问题讨论】:

    标签: c# asp.net .net command-line-interface cisco


    【解决方案1】:

    ReadToEnd() 直到遇到流的末尾才会返回。换一种说法,在ReadToEnd() 返回后,流处于一种状态,不再有数据从中流出(你已经到了尽头)。

    因此,您可能不想使用ReadToEnd()。根据您处理输出的方式,您可能希望使用ReadLine(),或者只使用Read()

    【讨论】:

    • 好吧,这是有道理的,但是当到达最后一行时,ReadLine() 和 Read() 仍然没有返回。似乎无法正确识别 EOF?
    • ReadLine() 只会在流结束时为空,因此我认为您的循环仍然无法读取整个流。您可能只想要没有循环的 ReadLine? (它会阻塞直到遇到新行)
    • @Michael - 如果您打开的进程永远不会自行停止(并且永远不会关闭自己的标准输出),那么任何 Read 方法都不会到达流的末尾。我认为您混淆了当前没有更多数据的流与实际关闭的流之间的区别。当流关闭时,您将继续读取任何剩余的缓冲数据,直到最后 ReadLine 返回 null,或 Read 返回指示已读取零字节。
    【解决方案2】:

    您的循环将一直持续到流结束:

        string line = string.Empty;
        while ((line = process.StandardOutput.ReadLine()) != null)
        {
            Console.WriteLine("CLI Says: " + line);
        }
    

    这将读取整个流并逐行打印出来,只有在流真正结束时才停止。 ReadLine() 函数将读取流的每个字符,直到它到达回车符,然后将它读取的所有字符作为字符串返回。它只会在流结束时返回 null。

    您需要做的是处理每一行并弄清楚您想用它做什么,也就是将逻辑放入读取循环中,如下所示:

        enum State {
            Initial,
            Connecting,
            ..
        }
    
        string line = string.Empty;
        State state = State.Initial;
        while ((line = process.StandardOutput.ReadLine()) != null)
        {
            Console.WriteLine("CLI Says: " + line);
            if(line == string.Empty) continue; // skip blank lines
            if(line.StartsWith("VPN>")
            {
                switch(state) 
                { 
                   case State.Initial: 
                       SendConnect(); 
                       state = State.Connecting;
                       break;
                   ..
                }
            }
            else // check what is being printed by vpn is correct, no errors, etc.
        }
    

    然后,您可以扩展 switch 语句,随时推进状态并发送不同的输入等。

    【讨论】:

    • 不幸的是,这不是问题所在。我在 process.StandardInput.WriteLine() 之前和之后以及在 StandardOutput 循环之后插入了断点。当我进入 process.StandardInput.WriteLine() 时,代码立即停止执行,焦点返回到我的主窗体(winform)。 process.StandardInput.WriteLine() 之后的断点(或任何其他代码)永远不会执行。在循环中调用最后一个 process.StandardOutput.WriteLine() 时也会发生同样的事情。
    猜你喜欢
    • 2013-11-12
    • 1970-01-01
    • 2017-02-03
    • 1970-01-01
    • 1970-01-01
    • 2013-03-18
    • 1970-01-01
    • 2015-12-16
    • 1970-01-01
    相关资源
    最近更新 更多