简体   繁体   English

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

[英]C# redirect input console application not working

I have an interesting situation. 我有一个有趣的情况。 I am trying to run a program from the command line and I cannot programatically redirect its input for some reason. 我正在尝试从命令行运行程序,由于某种原因,我无法以编程方式重定向其输入。 The executable I am running is called. 我正在运行的可执行文件称为。 Spideroakone.exe . Spideroakone.exe This executable asks for a password. 该可执行文件要求输入密码。 When I type the password lets say the password is "asd" I can actually see what I am typing in plain text. 当我输入密码时,可以说密码是“ asd”,实际上我可以看到以纯文本形式输入的内容。 I get an error message: 我收到一条错误消息:

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

If I run the executable like that : 如果我像这样运行可执行文件:

cmd /c Spideroakone.exe

then again I see the same I am asked for a password. 然后再次看到相同的密码。 Then I type asd. 然后我输入asd。 But I can't see what I am typing and the password works and there is no error. 但是我看不到我输入的内容,并且密码有效并且没有错误。

Now what I want to do is write an app that will execute Spideroak.exe and pass the password on the standard input. 现在我要做的是编写一个应用程序,该程序将执行Spideroak.exe并在标准输入中传递密码。 However because of the weird behaviour of Spideroak I am unable to pass any standard input to it nor I am able to read the standard output. 但是,由于Spideroak的行为异常,我无法将任何标准输入传递给它,也无法读取标准输出。 When try to do that my app blocks on the writeline command. 当尝试这样做时,我的应用程序在writeline命令上被阻止。 I would have expected to see the word "Password:" in the stdout. 我本来希望在标准输出中看到“ Password:”一词。 I have tried some async examples and multithreading but non of that works. 我已经尝试了一些异步示例和多线程,但是没有一个可行。 The standard output buffer is always empty. 标准输出缓冲区始终为空。 I wonder what is this text I am seeing "Password:" if it is not written to the stdout where it is written? 我想知道我看到的是“ Password:”(密码:)这句话是什么,如果它没有写到标准输出上的话?

this is the code I use. 这是我使用的代码。 Which blocks on the ReadToEnd() line. ReadToEnd()行上的哪个块。 This exact code works fine with a console app that I made so this makes me think the executable I am trying to execute is written in a weird way, but in a command line window it works fine: 这个确切的代码在我制作的控制台应用程序中可以很好地工作,因此这让我觉得我尝试执行的可执行文件是用怪异的方式编写的,但是在命令行窗口中它可以正常工作:

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();

This is the screenshot of the exact debug window and the line it blocks on: 这是确切的调试窗口及其阻塞行的屏幕截图:

This is what I see in the command line window: 这是我在命令行窗口中看到的:

Well no one responded and in the mean time I found the answer. 好吧,没人回应,与此同时,我找到了答案。 I did not find the exact reason why stdout and stdin are not working but I read an article that someone else was complaining that old programs written in C using getch() will behave that way. 我没有找到stdout和stdin无法正常工作的确切原因,但是我读到一篇文章,当时有人在抱怨用getch()用C编写的旧程序会表现这种方式。 I wanted to do it in a more pretty way but this is what I came up with. 我想用一种更漂亮的方式做到这一点,但这就是我想出的。 Basically sending key strokes to the console window. 基本上将按键发送到控制台窗口。 I wasn't sure if this will work because I am starting the process in Task Scheduler and there is no visual window created but it seems working fine. 我不确定这是否行得通,因为我正在Task Scheduler中启动该过程,并且没有创建可视窗口,但看起来工作正常。

I start the process in a separate thread: 我在一个单独的线程中启动该过程:

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();

Then I enumerate all windows: 然后,我列举所有窗口:

EnumWindows(EnumTheWindows, IntPtr.Zero);

Then I look for the window of my process and send the desired key strokes to it. 然后,我寻找过程的窗口并向其发送所需的击键。 The Sleep in between is required without it is not working. 需要两次之间的休眠,否则它无法正常工作。 The sample password I am sending is 'asd' 我发送的示例密码是“ 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;
    }

I hope this will help someone save time. 我希望这可以帮助某人节省时间。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM