输入用户名到cmd进程

发布于 2024-10-20 17:53:59 字数 7084 浏览 2 评论 0原文

在我的 Winform 应用程序中,我使用 cmd Process 执行一个 exe 文件。 exe文件需要在“Enter Username”行输入用户名和密码“输入密码”。我无法输入用户名和密码,不知何故,该过程仅退出并且仅不起作用。我还添加了 ThreadState 和 WaitReason 的检查,但 process.Threads 中没有线程。我也需要输出。如果我在输入过程之前输入输出,那么直到输入之前它不会到达,如果我将输入放在输出之前,那么输入也不会被接受等等。始终接收相同的输出。这是代码:

        public bool StartOpenVPN()
    {
        bool installed = false;
        ProcessStartInfo processInfo = null;
        Process process = null;
        try
        {
            string command = "files\\openvpn --config files\\client.ovpn";
            Console.WriteLine("Command = " + command);

            processInfo = new ProcessStartInfo("cmd.exe", "/C " + command);
            processInfo.UseShellExecute = false;
            processInfo.RedirectStandardInput = true;
            processInfo.RedirectStandardOutput = true;
            Console.WriteLine("Opening cmd");

            process = new Process();
            process.StartInfo = processInfo;
            process.Start();

            StreamWriter sw = process.StandardInput;
            sw.WriteLine("foo");
            sw.WriteLine("*baa");
            sw.Flush();
            sw.Close();

            process.BeginOutputReadLine();
            process.OutputDataReceived += new DataReceivedEventHandler(Process_OutputDataReceived);

            Console.WriteLine("Finished cmd");
        }
        catch (Exception e)
        {
            Console.WriteLine("Errror Installing Tap Adapter : " + e.Message);
            Console.WriteLine(e.StackTrace);
        }
        finally
        {
            processInfo = null;
            if (process != null)
            {
                process.Close();
                process = null;
            }
        }
        return installed;
    }

    private void Process_OutputDataReceived(object sender, DataReceivedEventArgs e)
    {
        string d = e.Data;

        if (!string.IsNullOrEmpty(d))
        {
            Console.WriteLine("Line = " + d);
        }
    }

我得到的唯一输出是:

Line = Wed Mar 09 12:33:00 2011 OpenVPN 2.1.1 i686-pc-mingw32 [SSL] [LZO2] [PKCS11] built on Feb 17 2010
Line = Wed Mar 09 12:33:00 2011 ERROR: could not read Auth username from stdin
Line = Wed Mar 09 12:33:00 2011 Exiting

为什么它不接受输入,甚至在输出中显示“输入用户名”行?我不知道我哪里出了问题,但似乎某个地方出了问题。请帮助我解决这个问题,我陷入了困境,并尝试了很多次,并且在此之后花费了很多时间。

非常感谢任何帮助。

谢谢

@Fun Mun:这是更新的代码。它只是在获取任何流输入/输出时转到 process_Exited :

        private void initProcess()
    {
        processInfo = new ProcessStartInfo("cmd.exe", "/C " + command);
        processInfo.UseShellExecute = false;
        processInfo.RedirectStandardInput = true;
        processInfo.RedirectStandardOutput = true;
        processInfo.WindowStyle = ProcessWindowStyle.Normal;

        process = new Process();
        process.StartInfo = processInfo;
        process.Exited += new EventHandler(process_Exited);
        return;
    }

    void process_Exited(object sender, EventArgs e)
    {
        Console.WriteLine("Into process_Exited....");
        processInfo = null;
        if (process != null)
        {
            sw = null;
            process.Close();
            process = null;
        }
    }

    public bool StartOpenVPN()
    {
        bool installed = false;
        try
        {
            Console.WriteLine("Command = " + command);

            Console.WriteLine("Opening cmd");

            initProcess();
            process.Start();

            sw = process.StandardInput;
            Console.WriteLine("Has Exited after SW = " + process.HasExited.ToString()); // RETURS FALSE BUT GOES TO process_Exited & for next line results is NullPointerException
            sw.WriteLine("foo");
            sw.WriteLine("*baa");
             //sw.Flush();
            //sw.Close();

            //process.BeginOutputReadLine();
            //process.OutputDataReceived += new DataReceivedEventHandler(Process_OutputDataReceived);
             while (process.HasExited == false)
             {
                 string d = process.StandardOutput.ReadLine();
                 Console.WriteLine("Line = " + d);
             }

            process.WaitForExit();
            Console.WriteLine("Finished cmd");
        }
        catch (Exception e)
        {
            Console.WriteLine("Errror Opening : " + e.Message);
            Console.WriteLine(e.StackTrace);
        }

        return installed;
    }

直到 process.BeginOutputReadLine(); &输出处理程序没有被删除,它一直在等待(可能是为了进入),就像挂在外面一样。当删除这 2 条输出线并添加 while 循环时,进程就会在任何流调用上退出,即 process.StandardOutput; OR StandardInput,以下一个出现的为准并抛出 NullPointerException。 我按照您的指示在代码中犯了任何错误吗?


@Fun Mum:即使在使用和更新了您编辑的代码版本之后,我最终还是一样。我更新了你的代码,对其进行了一些修改,发现在第一行输出之后,openvpn 要求输入用户名,然后输入密码,然后他们就没有输入。我得到了正确的控制台输出,但结果不符合预期。这是代码:

        public bool StartOpenVPN()
    {
        bool installed = false;
        int lineNo = 0;
        try
        {
            Console.WriteLine("Command = " + command + "\nOpening cmd");

            initProcess();
            process.Start();

            sw = process.StandardInput;
            Console.WriteLine("Has Exited after SW = " + process.HasExited.ToString());
            //sw.WriteLine("123b5df33f");
            //sw.WriteLine("*3FgYxyt");
            //Console.WriteLine("Has Exited after writing data = " + process.HasExited.ToString());

             while (process.HasExited == false)
             {
                 string d = process.StandardOutput.ReadLine();
                 Console.WriteLine("Line = " + d);
                 lineNo++;
                 if (lineNo == 1)
                 {
                     Console.WriteLine("Writing Details");
                     sw.WriteLine("foo");
                     sw.Flush();
                     Console.WriteLine("Wrote Username");
                     sw.WriteLine("*baa");
                     sw.Flush();
                     Console.WriteLine("Wrote Password");
                 }
             }

             process.Close();
             process = null;
            Console.WriteLine("Finished cmd");
        }
        catch (Exception e)
        {
            Console.WriteLine("Errror Installing Tap Adapter : " + e.Message);
            Console.WriteLine(e.StackTrace);
        }

        return installed;
    }

输出是:

Command = files\openvpn --config files\client.ovpn

打开cmd SW = False 后已退出 线路 = 2011 年 3 月 11 日星期五 18:10:06 OpenVPN 2.1.1 i686-pc-mingw32 [SSL] [LZO2] [PKCS11] 建于 2010 年 2 月 17 日 写入细节 // 在第一行之后,它正在尝试写入 写了用户名 写入密码 行 = 2011 年 3 月 11 日星期五 18:10:06 错误:无法从标准输入读取身份验证用户名 线路 = 2011 年 3 月 11 日星期五 18:10:06 退出 线= 已完成 cmd

无法确定应用程序是否无法正确将输入发送到 stdin 或者 openvpn 无法接受它。我还尝试了 sw.WriteLine("foo" + ConsoleKey.Enter);,也产生了相同的结果。想知道&尝试在执行/调试时查看cmd窗口以了解确切的结果,但也看不到。

如果我们通过命令提示符正常运行 openvpn,我们得到的是:

D:\>files\\openvpn --config files\\client.ovpn

Fri Mar 11 18:03:48 2011 OpenVPN 2.1.1 i686-pc-mingw32 [SSL] [LZO2] [PKCS11] bui 于 2010 年 2 月 17 日 输入身份验证用户名:

真的对此感到困惑。

In my Winform app, I execute a exe file using cmd Process. The exe file needs to input username and passowrd on line "Enter Username" & "Enter Password". I am not able to input the username and password, somehow the process gets exited only and doesn't work out only. I added checking of ThreadState and WaitReason also, but there are no threads in process.Threads. I also need the output. If I type output before input process, then it doesn't reach till input and if I put input before output, then also the input is not accepeted or so. Just receive the output same all time. Here is the code :

        public bool StartOpenVPN()
    {
        bool installed = false;
        ProcessStartInfo processInfo = null;
        Process process = null;
        try
        {
            string command = "files\\openvpn --config files\\client.ovpn";
            Console.WriteLine("Command = " + command);

            processInfo = new ProcessStartInfo("cmd.exe", "/C " + command);
            processInfo.UseShellExecute = false;
            processInfo.RedirectStandardInput = true;
            processInfo.RedirectStandardOutput = true;
            Console.WriteLine("Opening cmd");

            process = new Process();
            process.StartInfo = processInfo;
            process.Start();

            StreamWriter sw = process.StandardInput;
            sw.WriteLine("foo");
            sw.WriteLine("*baa");
            sw.Flush();
            sw.Close();

            process.BeginOutputReadLine();
            process.OutputDataReceived += new DataReceivedEventHandler(Process_OutputDataReceived);

            Console.WriteLine("Finished cmd");
        }
        catch (Exception e)
        {
            Console.WriteLine("Errror Installing Tap Adapter : " + e.Message);
            Console.WriteLine(e.StackTrace);
        }
        finally
        {
            processInfo = null;
            if (process != null)
            {
                process.Close();
                process = null;
            }
        }
        return installed;
    }

    private void Process_OutputDataReceived(object sender, DataReceivedEventArgs e)
    {
        string d = e.Data;

        if (!string.IsNullOrEmpty(d))
        {
            Console.WriteLine("Line = " + d);
        }
    }

The only output I get is :

Line = Wed Mar 09 12:33:00 2011 OpenVPN 2.1.1 i686-pc-mingw32 [SSL] [LZO2] [PKCS11] built on Feb 17 2010
Line = Wed Mar 09 12:33:00 2011 ERROR: could not read Auth username from stdin
Line = Wed Mar 09 12:33:00 2011 Exiting

Why it doesn't accept the input or even show the line "Enter Username" in output ? I can't makeout where am I going wrong, but it seems am going wrong somewhere. Kindly help me with this issue am stuck badly and have tried many times and things and have spent lots of time after this.

Any help is highly appreciated.

Thanks

@Fun Mun : here is the updated code. It just goes to process_Exited on getting any stream input/output :

        private void initProcess()
    {
        processInfo = new ProcessStartInfo("cmd.exe", "/C " + command);
        processInfo.UseShellExecute = false;
        processInfo.RedirectStandardInput = true;
        processInfo.RedirectStandardOutput = true;
        processInfo.WindowStyle = ProcessWindowStyle.Normal;

        process = new Process();
        process.StartInfo = processInfo;
        process.Exited += new EventHandler(process_Exited);
        return;
    }

    void process_Exited(object sender, EventArgs e)
    {
        Console.WriteLine("Into process_Exited....");
        processInfo = null;
        if (process != null)
        {
            sw = null;
            process.Close();
            process = null;
        }
    }

    public bool StartOpenVPN()
    {
        bool installed = false;
        try
        {
            Console.WriteLine("Command = " + command);

            Console.WriteLine("Opening cmd");

            initProcess();
            process.Start();

            sw = process.StandardInput;
            Console.WriteLine("Has Exited after SW = " + process.HasExited.ToString()); // RETURS FALSE BUT GOES TO process_Exited & for next line results is NullPointerException
            sw.WriteLine("foo");
            sw.WriteLine("*baa");
             //sw.Flush();
            //sw.Close();

            //process.BeginOutputReadLine();
            //process.OutputDataReceived += new DataReceivedEventHandler(Process_OutputDataReceived);
             while (process.HasExited == false)
             {
                 string d = process.StandardOutput.ReadLine();
                 Console.WriteLine("Line = " + d);
             }

            process.WaitForExit();
            Console.WriteLine("Finished cmd");
        }
        catch (Exception e)
        {
            Console.WriteLine("Errror Opening : " + e.Message);
            Console.WriteLine(e.StackTrace);
        }

        return installed;
    }

Untill process.BeginOutputReadLine(); & output handler was not removed, it kept waiting (may be for entry)like hanged out. The moment removed those 2 output lines and added while loop, process just gets exit on any stream call i.e. process.StandardOutput; OR StandardInput whichever comes the next and throws NullPointerException.
Have I made any mistake in the code as instructed by you ?


@Fun Mum : Even after using and updating your edited version of the code, I end up the same. I updated your code, modified it a bit seeing that after 1st line output the openvpn asks for username and then passowrd, then their is no input. I get proper console outputs but the results not as expected. Here is the code :

        public bool StartOpenVPN()
    {
        bool installed = false;
        int lineNo = 0;
        try
        {
            Console.WriteLine("Command = " + command + "\nOpening cmd");

            initProcess();
            process.Start();

            sw = process.StandardInput;
            Console.WriteLine("Has Exited after SW = " + process.HasExited.ToString());
            //sw.WriteLine("123b5df33f");
            //sw.WriteLine("*3FgYxyt");
            //Console.WriteLine("Has Exited after writing data = " + process.HasExited.ToString());

             while (process.HasExited == false)
             {
                 string d = process.StandardOutput.ReadLine();
                 Console.WriteLine("Line = " + d);
                 lineNo++;
                 if (lineNo == 1)
                 {
                     Console.WriteLine("Writing Details");
                     sw.WriteLine("foo");
                     sw.Flush();
                     Console.WriteLine("Wrote Username");
                     sw.WriteLine("*baa");
                     sw.Flush();
                     Console.WriteLine("Wrote Password");
                 }
             }

             process.Close();
             process = null;
            Console.WriteLine("Finished cmd");
        }
        catch (Exception e)
        {
            Console.WriteLine("Errror Installing Tap Adapter : " + e.Message);
            Console.WriteLine(e.StackTrace);
        }

        return installed;
    }

The output is :

Command = files\openvpn --config files\client.ovpn

Opening cmd
Has Exited after SW = False
Line = Fri Mar 11 18:10:06 2011 OpenVPN 2.1.1 i686-pc-mingw32 [SSL] [LZO2] [PKCS11] built on Feb 17 2010
Writing Details // AFTER 1ST LINE IT IS TRYNG TO WRITE
Wrote Username
Wrote Password
Line = Fri Mar 11 18:10:06 2011 ERROR: could not read Auth username from stdin
Line = Fri Mar 11 18:10:06 2011 Exiting
Line =
Finished cmd

Couldn't make out if application is not able to throw input to stdin properly or openvpn is not able to accept it. I also tried sw.WriteLine("foo" + ConsoleKey.Enter);, that also produced same results. Was wondering & trying to see the cmd window on while executing/debugging to know the exact results, but couldn't see that also.

If we run openvpn via command prompt normally, we get is :

D:\>files\\openvpn --config files\\client.ovpn

Fri Mar 11 18:03:48 2011 OpenVPN 2.1.1 i686-pc-mingw32 [SSL] [LZO2] [PKCS11] bui
lt on Feb 17 2010
Enter Auth Username:

Puzzled out with this, really.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

断肠人 2024-10-27 17:53:59

实际上,您在finally 块中关闭了进程。尝试在 Console.WriteLine("Finished cmd"); 之前添加 process.WaitForExit();

或者,您可以替换 process.BeginOutputReadLine(); > with:

while (!process.HasExited)
{
    string d = process.StandardOutput.ReadLine();
    Console.WriteLine("Line = {0}", d);
}

更好的方法是将 make process 放在成员变量而不是局部变量中。简单地将finally 块中的代码移至进程退出处理程序:

void process_Exited(object sender, EventArgs e)
{
    // Code from finally here
}

但是您必须记住添加退出处理程序:

process.Exited += new EventHandler(process_Exited);

另一方面,关闭输入流可能会导致一些问题。尝试删除以下 2 行,看看会发生什么

sw.Flush();
sw.Close();

以下是代码的编辑版本:

private void initProcess()
{
    processInfo = new ProcessStartInfo("cmd.exe", "/C " + command);
    processInfo.UseShellExecute = false;
    processInfo.RedirectStandardInput = true;
    processInfo.RedirectStandardOutput = true;
    processInfo.WindowStyle = ProcessWindowStyle.Normal;

    process = new Process();
    process.StartInfo = processInfo;
    //process.Exited += new EventHandler(process_Exited); // Actually no longer required, since HasExited will test for it
    // return; // return not required
}

// No longer need Exited, since HasExited checks for it
/*
void process_Exited(object sender, EventArgs e)
{
    Console.WriteLine("Into process_Exited....");
    processInfo = null;
    if (process != null)
    {
        sw = null;
        // Do not close here. Closing here will prevent "process.WaitForExit()" and "process.HasExited" from working
        //process.Close();
        //process = null;
    }
}
*/

public bool StartOpenVPN()
{
    bool installed = false;
    try
    {
        Console.WriteLine("Command = " + command);

        Console.WriteLine("Opening cmd");

        initProcess();
        process.Start();

        sw = process.StandardInput;
        Console.WriteLine("Has Exited after SW = " + process.HasExited.ToString()); // RETURS FALSE BUT GOES TO process_Exited & for next line results is NullPointerException
        sw.WriteLine("foo");
        sw.WriteLine("*baa");
         //sw.Flush();
        //sw.Close();

        //process.BeginOutputReadLine();
        //process.OutputDataReceived += new DataReceivedEventHandler(Process_OutputDataReceived);
         while (process.HasExited == false)
         {
             string d = process.StandardOutput.ReadLine();
             Console.WriteLine("Line = " + d);
         }

        // process.WaitForExit(); // Not required, since HasExited already check whether process has exited
        // Added here from Exited, so that it only close after exit
        process.Close();
        process = null;
        Console.WriteLine("Finished cmd");
    }
    catch (Exception e)
    {
        Console.WriteLine("Errror Opening : " + e.Message);
        Console.WriteLine(e.StackTrace);
    }

    return installed;
}

You actually close your process in the finally block. Try adding process.WaitForExit(); before Console.WriteLine("Finished cmd");

Alternatively, you may replace process.BeginOutputReadLine(); with:

while (!process.HasExited)
{
    string d = process.StandardOutput.ReadLine();
    Console.WriteLine("Line = {0}", d);
}

An even better approach is to put make process a member variable rather than a local variable. Simple move the code in the finally block to the process exited handler:

void process_Exited(object sender, EventArgs e)
{
    // Code from finally here
}

But you must remember to add the exited handler:

process.Exited += new EventHandler(process_Exited);

On another note, closing the input stream may cause some problem. Try removing the following 2 lines to see what happens

sw.Flush();
sw.Close();

The following is an edited version of your code:

private void initProcess()
{
    processInfo = new ProcessStartInfo("cmd.exe", "/C " + command);
    processInfo.UseShellExecute = false;
    processInfo.RedirectStandardInput = true;
    processInfo.RedirectStandardOutput = true;
    processInfo.WindowStyle = ProcessWindowStyle.Normal;

    process = new Process();
    process.StartInfo = processInfo;
    //process.Exited += new EventHandler(process_Exited); // Actually no longer required, since HasExited will test for it
    // return; // return not required
}

// No longer need Exited, since HasExited checks for it
/*
void process_Exited(object sender, EventArgs e)
{
    Console.WriteLine("Into process_Exited....");
    processInfo = null;
    if (process != null)
    {
        sw = null;
        // Do not close here. Closing here will prevent "process.WaitForExit()" and "process.HasExited" from working
        //process.Close();
        //process = null;
    }
}
*/

public bool StartOpenVPN()
{
    bool installed = false;
    try
    {
        Console.WriteLine("Command = " + command);

        Console.WriteLine("Opening cmd");

        initProcess();
        process.Start();

        sw = process.StandardInput;
        Console.WriteLine("Has Exited after SW = " + process.HasExited.ToString()); // RETURS FALSE BUT GOES TO process_Exited & for next line results is NullPointerException
        sw.WriteLine("foo");
        sw.WriteLine("*baa");
         //sw.Flush();
        //sw.Close();

        //process.BeginOutputReadLine();
        //process.OutputDataReceived += new DataReceivedEventHandler(Process_OutputDataReceived);
         while (process.HasExited == false)
         {
             string d = process.StandardOutput.ReadLine();
             Console.WriteLine("Line = " + d);
         }

        // process.WaitForExit(); // Not required, since HasExited already check whether process has exited
        // Added here from Exited, so that it only close after exit
        process.Close();
        process = null;
        Console.WriteLine("Finished cmd");
    }
    catch (Exception e)
    {
        Console.WriteLine("Errror Opening : " + e.Message);
        Console.WriteLine(e.StackTrace);
    }

    return installed;
}
空袭的梦i 2024-10-27 17:53:59

不要尝试通过命令行传递用户名和密码,而是使用 OpenVPN 的 --auth-user-pass [file] 开关,其中 [file] 是所有两行:

用户
秘密密码

我从未尝试过,但这是文档所说的。

所以你的开头行应该是这样的:

string command = "files\\openvpn --config files\\client.ovpn --auth-user-pass files\\TEMP-AUTH";

只要记住在完成后立即删除 TEMP-AUTH 即可。

Instead of trying to pass the username and password via the command line use OpenVPN's --auth-user-pass [file] switch, where [file] is all two lines:

user
secretPassword

I've never tried it, but its what the docs say.

So you opening line would be something like:

string command = "files\\openvpn --config files\\client.ovpn --auth-user-pass files\\TEMP-AUTH";

Just remember to delete TEMP-AUTH as soon as you're done with it.

述情 2024-10-27 17:53:59

这个查询对我来说无法解析,因为 openvpn 不支持从应用程序接受标准输入。

感谢大家的帮助以及想法和建议。

谢谢。

This query has been unresolvable for me as openvpn didn't support accepting stdin from the application.

Thanks for everybody help and ideas and suggestions.

Thanks.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文