C#重定向输入控制台应用程序不工作

时间:2017-09-17 09:00:28

标签: c# redirect subprocess console-output

我有一个有趣的情况。我试图从命令行运行程序,我不能出于某种原因以编程方式重定向其输入。我正在运行的可执行文件被调用。的 Spideroakone.exe 即可。此可执行文件要求输入密码。当我输入密码时,可以说密码是" asd"我实际上可以看到我在纯文本中输入的内容。我收到一条错误消息:

'asd' is not recognized as an internal or external command ...

如果我像这样运行可执行文件:

cmd /c Spideroakone.exe

然后我再次看到我被要求输入密码。然后我输入asd。但我无法看到我正在输入的内容和密码是否有效,并且没有错误。

现在我要做的是编写一个将执行 Spideroak.exe 的应用程序并在标准输入上传递密码。然而,由于Spideroak的奇怪行为,我无法传递任何标准输入,也无法读取标准输出。当我尝试这样做时,我的应用程序阻止了writeline命令。我原本希望看到“#34;密码:"在stdout。我尝试了一些异步示例和多线程,但不是这样的。标准输出缓冲区始终为空。我想知道我看到的这个文字是什么"密码:"如果没有写入写入的stdout?

这是我使用的代码。 ReadToEnd()行上的哪些块。这个确切的代码适用于我制作的控制台应用程序,所以这让我觉得我尝试执行的可执行文件是以一种奇怪的方式编写的,但在命令行窗口中它可以正常工作:

Process myProcess = new Process();

myProcess.StartInfo.FileName = @"c:\windows\system32\cmd.exe";
myProcess.StartInfo.Arguments = @"/c ""C:\Program Files\SpiderOakONE\SpiderOakONE.exe"" --headless";
myProcess.StartInfo.UseShellExecute = false;
myProcess.StartInfo.RedirectStandardOutput = true;
myProcess.StartInfo.RedirectStandardInput = true;

myProcess.Start();

string s = myProcess.StandardOutput.ReadToEnd();
myProcess.WaitForExit();

这是确切的调试窗口及其阻止的行的屏幕截图:

这是我在命令行窗口中看到的:

1 个答案:

答案 0 :(得分:1)

没有人回答,同时我找到了答案。我没有找到为什么stdout和stdin没有工作的确切原因但我读了一篇文章,其他人抱怨用C语言编写的旧程序使用getch()会表现得那样。我想以更漂亮的方式做到这一点,但这就是我想出来的。基本上将击键发送到控制台窗口。我不确定这是否会起作用,因为我在任务计划程序中启动了该过程并且没有创建可视窗口但它看起来工作正常。

我在一个单独的线程中启动该过程:

new Thread(() =>
        {
        Process myProcess = new Process();

        myProcess.StartInfo.FileName = @"c:\windows\system32\cmd.exe";
        myProcess.StartInfo.Arguments = @"/c ""C:\Program Files\SpiderOakONE\SpiderOakONE.exe"" --headless";
        myProcess.StartInfo.UseShellExecute = false;
        myProcess.Start();

        myProcess.WaitForExit();
        }).Start();

然后我枚举所有窗口:

EnumWindows(EnumTheWindows, IntPtr.Zero);

然后我查找我的过程窗口并将所需的击键发送给它。中间的睡眠是必需的,没有它不起作用。我发送的示例密码是'asd'

private static bool EnumTheWindows(IntPtr hWnd, IntPtr lParam)
    {
        uint pidCurWindow;
        uint CurWindowThreadId = GetWindowThreadProcessId(hWnd, out pidCurWindow);
        int CurrentPID = System.Diagnostics.Process.GetCurrentProcess().Id;

        if (pidCurWindow == CurrentPID)
        {
            Thread.Sleep(50);
            PostMessage(hWnd, WM_KEYDOWN, VkKeyScan('a'), 0);
            Thread.Sleep(50);
            PostMessage(hWnd, WM_KEYDOWN, VkKeyScan('s'), 0);
            Thread.Sleep(50);
            PostMessage(hWnd, WM_KEYDOWN, VkKeyScan('d'), 0);
            Thread.Sleep(50);
            PostMessage(hWnd, WM_KEYDOWN, VK_RETURN, 1);
            Thread.Sleep(50);
        }
        return true;
    }

我希望这能帮助别人节省时间。