【问题标题】:Console app only terminates when holding key down while running batch script控制台应用程序仅在运行批处理脚本时按住键时终止
【发布时间】:2019-03-28 10:58:31
【问题描述】:

我正在尝试创建一个 C# 控制台应用程序,该应用程序重复运行 .bat 文件并将输出保存到一个变量中以供以后修改。该脚本旨在使用adb.exe 在已连接设备上获取打开的 TCP 连接。

我希望应用程序在按下 Esc 键时退出(一次)。为了做到这一点,我遵循this answer 并像这样实现它:

Program.cs

static void Main(string[] args)
{
    Console.WriteLine("Press escape to quit");
    do
    {
        while (!Console.KeyAvailable)
        {
            // Console.WriteLine("Application is running");
            RunBatch();
        }
    } while (Console.ReadKey(true).Key != ConsoleKey.Escape);
    Console.WriteLine("While loop was exited");
    Console.ReadLine();
}

static void RunBatch()
{
    Process p = new Process();
    p.StartInfo.UseShellExecute = false;
    p.StartInfo.RedirectStandardOutput = true;
    p.StartInfo.FileName = @"C:\Dev\Batch\GetTcpConnections.bat";
    p.Start();

    string output = p.StandardOutput.ReadToEnd();

    p.WaitForExit();
    Console.WriteLine(output);
}

GetTcpConnections.bat

@echo off
echo %time%
adb.exe shell cat /proc/net/tcp
timeout /t 1 /nobreak>nul

预期的结果是,控制台应用程序退出循环并在按下 Esc 时直接打印While loop was exited。当我评论 RunBatch() 和取消评论 Console.WriteLine("Application is running" 时,它的工作原理是这样的。但是,当我运行批处理脚本时,我需要在程序退出 while 循环之前按住 Esc 大约一两秒,而不是立即退出。

一开始我以为输入可能被批处理脚本中的timeout /t 1 /nobreak>nul 屏蔽了,但是去掉这行并没有什么区别。我是否在这里遗漏了其他可能会阻止输入的内容?

【问题讨论】:

    标签: c# batch-file console-application


    【解决方案1】:

    一旦您的控制台应用程序启动adb.exe,它就会失去焦点。当应用程序没有焦点时,它不会接收任何键盘输入,因为键盘输入会转到另一个焦点应用程序。

    您可以通过在adb.exe 正在运行时用鼠标选择控制台应用程序来收回焦点,然后按ESC。但我想这不是你想要的。

    我看到了几个“解决方案”:

    • 您可以找到一种方法让您的控制台应用程序始终成为顶级应用程序。
    • 使它成为一个桌面/Winform-应用程序,它有一个错误“退出”按钮。

    【讨论】:

    • 我明白了。这就说得通了。然后,当“adb.exe”完成时,焦点会返回到控制台应用程序,提供一个用于注册“删除”的窗口。我尝试按照您的建议单击控制台应用程序以获取焦点,然后按退出键。然而,这仍然没有注册。我会考虑让它始终是顶级应用程序,winform 应用程序确实可以工作。但首先要尝试让它作为控制台应用程序运行。感谢您的建议!
    • 我没有测试它,但我可以想象即使你的控制台应用程序有焦点,GetTcpConnections.bat 的控制台东西是当前正在运行的接收击键的应用程序。如果adb.exe 也在控制台窗口内运行,则该应用程序将接收击键。
    【解决方案2】:

    下面的代码应该可以解决您的问题。请注意,我已将超时从批处理文件中移开,并将其放在 while 循环中。

    Program.cs

    private static void Main(string[] args)
    {
        Console.WriteLine("Press escape to quit");
    
        do
        {
            while (!Console.KeyAvailable)
            {
                RunBatch();
                Thread.Sleep(1000);
            }
        } while (Console.ReadKey(true).Key != ConsoleKey.Escape);
    
        Console.WriteLine("While loop has exited");
        Console.ReadLine();
    }
    
    private static void RunBatch()
    {
        var process = new Process
        {
            StartInfo =
            {
                UseShellExecute = false,
                RedirectStandardOutput = true,
                FileName = @"C:\Dev\Batch\GetTcpConnections.bat"
            }
        };
    
        process.Start();
        Console.WriteLine(process.StandardOutput.ReadToEnd());
    }
    

    GetTcpConnections.bat

    @echo off
    echo %time%
    adb.exe shell cat /proc/net/tcp
    

    【讨论】:

    • 像魅力一样工作! “奇怪”的事情是,如果没有Thread.Sleep(1000);(正如我之前尝试过的那样),这是行不通的。但这可能是因为 Martin 在他的回答中解释说,“adb.exe”一直处于控制之中,并且控制台应用程序的“窗口太小”无法在运行之间捕获转义键。显然,它会在退出之前等待完整的Thread.Sleep。但这是可以预料的。非常感谢。
    猜你喜欢
    • 1970-01-01
    • 2021-11-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-14
    • 1970-01-01
    相关资源
    最近更新 更多