C# 为什么我不能通过代码获取ftp.exe的输出?
我通过C#System.Diagnostics.Process类型执行ftp.exe cmd。在以编程方式输入“help”命令后,我使用以下代码获得“ftp.exe”输出。但我只能得到结果的第一行。而且我从来没有到达“结束”输出部分。整个计划似乎被封锁了C# 为什么我不能通过代码获取ftp.exe的输出?,c#,command-line,C#,Command Line,我通过C#System.Diagnostics.Process类型执行ftp.exe cmd。在以编程方式输入“help”命令后,我使用以下代码获得“ftp.exe”输出。但我只能得到结果的第一行。而且我从来没有到达“结束”输出部分。整个计划似乎被封锁了 Process p = new Process(); p.StartInfo.FileName = @"C:\Windows\System32\ftp.exe"; p.StartInfo.CreateNoWindow =
Process p = new Process();
p.StartInfo.FileName = @"C:\Windows\System32\ftp.exe";
p.StartInfo.CreateNoWindow = true;
p.StartInfo.RedirectStandardInput = true;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardError = true;
p.StartInfo.UseShellExecute = false;
p.Start();
p.StandardInput.WriteLine("help");
Int32 c_int = p.StandardOutput.Read();
while (c_int != -1)
{
Char c = (Char)c_int;
Console.Write(c);
c_int = p.StandardOutput.Read();
}
Console.WriteLine("end");
但是,我编写了一个简单的程序,它只使用Console.Writeline()将一些输出写入其标准输出流。我用上面的代码测试它。它很好用。我就是不明白为什么上面的代码不能与ftp.exe一起工作?SimpleConsoleOutput程序与“ftp.exe”之间的唯一区别在于ftp.exe有自己的交互式命令提示符
(---------新进展----------------)
这是我个人调查的一些进展
我写了两个线程来写入StdIn,从“ftp.exe”的StdOut读取,输出如下:
Commands may be abbreviated. Commands are:
Commands may be abbreviated. Commands are:
Commands may be abbreviated. Commands are:
....(exactly 16 times of above lines and then exactly 16 times of the following cmds list)
! delete literal prompt send
? debug ls put status
append dir mdelete pwd trace
...
最后的命令列表甚至还不完整
帮助命令输出似乎分为两部分
第一部分是:
Commands may be abbreviated. Commands are:
第二部分是:
! delete literal prompt send
? debug ls put status
append dir mdelete pwd trace
...
所有的第一部分在所有的第二部分之前被写入“ftp.exe”的标准数据流。
这怎么可能??谢谢你的评论
我使用“ftp.exe”的其他命令进行了测试,除了“help”命令之外,这似乎很正常。我认为问题在于输出缓冲区尚未刷新,因此您无法从ftp命令获得完整的输出 当您发出“退出”命令时,您应该会看到help命令的输出 我还没有解决方案,但如果我发现有什么有用的,我会稍后再回来。根据经验(我以前多次使用命令行FTP),您最好使用像这样的FTP插件 通过这种方式,您将完全控制FTP会话,能够向用户提供更好的反馈,并以适当的方式处理错误
最后一点,在处理FTP时,错误处理非常重要。FTP.exe只是保持运行。由于ftp.exe没有结束,因此您无法进入“结束”部分 发出help命令时,它将显示提示并等待另一个命令 如果要读取命令的响应,则需要解析响应并查找新的提示。也就是说,当您再次看到像
ftp>
这样的行时,您得到了整个响应
(除非您有非常非常充分的理由使用ftp.exe,否则请改用FtpWebRequest类)您是否尝试了
ReadLine
而不是Read
来读取重定向的输出?不担心您没有正确关闭进程,用于读取进程输出的代码应该如下所示:
process.Start();
output = process.StandardOutput.ReadToEnd(); // read the output here...
process.WaitForExit(); // ...then wait for exit, as after exit, it can't read the output
returnCode = process.ExitCode;
process.Close(); // once we have read the exit code, can close the process
但不确定这是否能解决这个具体问题
另外,为什么要在标准输入中写入“帮助”,如果这样做,它会不起作用吗
process.Arguments = "help";
无法获取ftp.exe的输入和输出的原因是,来自Microsoft Windows 2000/XP/Vista的内置ftp.exe使用
这不仅仅是ftp程序不刷新其缓冲区的情况
如果将ftp.exe的调用替换为cmd.exe之类的调用,您将看到它工作正常。问题是您试图读取FTP未发送的输出。不能使用常规方法读取和写入子ftp.exe。这是特定ftp.exe应用程序实现的结果
如果您确实需要自动化内置的Windows ftp程序,则需要借助pinvoke和win32函数 你的选择是:
- 使用不同的ftp程序。他们可能不会像MS内置程序那样使用控制台I/O方法
- 使用FTP类,如FtpWebRequest
- 如果这不合适或不可能,请使用低级别的网络套接字接口进行FTP李>
另请参见:我也这么认为,事实上,ftp.exe/help将输出到STDERR。然而,在交互模式下,输出到标准输出。啊,好吧,你每天都能学到一些东西我将编辑我的答案,但我仍然认为,将ftp.exe作为外部进程运行是处理ftp的一种糟糕方式。有太多的事情可能会出错,让它留给外部代码。是的,使用FTP库或
FtpWebRequest
类要好得多。就个人而言,我更喜欢.NET:)的RemObjects Internet Pack中的FtpClient。我决定使用edtFTP,因为这是我能找到的第一个免费的:-)谢谢,0xA3。“退出”命令可以是一种变通方法。但我只想知道ftp.exe和SimpleConsoleOutput.exe之间的区别。为什么后一个可以运行smootyly?@smwikipedia:我相信0xA3已经在回答中很好地解释了->“输出缓冲区还没有刷新”谢谢,没有。但是如果我不能到达“结束”部分,为什么我的程序在“帮助”命令输出的第一行之后停止?谢谢你的回答。是的,我试过ReadLine(),ReadToEnd()…没有一个能正确获得输出。谢谢你的回复。我将“help”命令写入StdIn,因为我想模拟“ftp.exe”的交互式命令提示符。你有没有试着检查一下标准输出的ftp文件,然后向标准输入发送“再见”?然后它应该转到WaitForExit调用,而不是仅仅等待更多的输入。非常感谢,Cheeso。我想知道ftp.exe的输出到底发送到哪里?有一个不可忽视的事实,我确实从标准输出中得到了“help”命令的输出,尽管经过了相当长的“延迟”…嗨,Cheeso,希望你能对我最后的担忧给我更多的评论。。。谢谢。其实我不知道;但是你想做什么呢?如果您想执行FTP操作,还有其他方法可以实现。为什么要限制你必须使用ftp.exe,当它被自动化时显然是不切实际的?嗨,Cheeso。我正在做一些关于斯坦的研究