在我的Winform应用程序中,我使用cmd Process执行exe文件。 exe文件需要在“输入用户名”和“输入用户名”上输入用户名和密码。 “输入密码”。我无法输入用户名和密码,不知何故该进程只退出并且不能解决。我还添加了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(); &安培;输出处理程序没有被删除,它一直在等待(可能是为了进入)就像被绞死一样。这一刻删除了那两个输出行并添加了while循环,进程只是在任何流调用上退出,即process.StandardOutput;或StandardInput以下一个为准,并抛出NullPointerException。 我是否按照您的指示在代码中犯了错误?
@Fun Mum:即使在使用和更新您编辑的代码版本后,我也会这样做。我更新了你的代码,修改了一下,看到在第一行输出后openvpn要求输入用户名然后是passowrd,那么他们就没有输入了。我得到适当的控制台输出,但结果不如预期。这是代码:
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之后退出 Line = Fri Mar 11 18:10:06 2011 OpenVPN 2.1.1 i686-pc-mingw32 [SSL] [LZO2] [PKCS11]建于2010年2月17日 写详细信息//在第1行之后是TRYNG写的 写了用户名 写了密码 Line = Fri Mar 11 18:10:06 2011 ERROR:无法从stdin读取Auth用户名 Line = Fri Mar 11 18:10:06 2011退出 线= 完成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日 输入验证用户名:
真的很困惑。
答案 0 :(得分:1)
您实际上是在finally
块中关闭了您的流程。尝试在process.WaitForExit();
Console.WriteLine("Finished cmd");
或者,您可以将process.BeginOutputReadLine();
替换为:
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;
}
答案 1 :(得分:0)
不要试图通过命令行传递用户名和密码,而是使用OpenVPN的--auth-user-pass [file]开关,其中[file]是两行:
用户 secretPassword的
我从未尝试过,但它是文档所说的。
所以你打开的行就像是:
string command = "files\\openvpn --config files\\client.ovpn --auth-user-pass files\\TEMP-AUTH";
请记得在完成后立即删除TEMP-AUTH。
答案 2 :(得分:0)
此查询对我来说无法解析,因为openvpn不支持从应用程序接受stdin。
感谢大家的帮助,意见和建议。
感谢。