为什么我无法通过代码获取ftp.exe的输出?

我通过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 = 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()将一些输出写入其StdOut流。 我用上面的代码测试它。 它工作正常。 我只是想不通为什么上面的代码不能用于ftp.exe? 我的SimpleConsoleOutput程序和“ftp.exe”之间的唯一区别是ftp.exe有自己的交互式命令提示符。

(—————新进展—————–)

以下是我个人调查的一些进展。

我写两个线程写入StdIn并从StdOut读取“ftp.exe”,输出如下:

 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”的StdOut流中。 这怎么样? 感谢您的意见。

我使用“ftp.exe”的其他命令进行了测试,除了“help”命令外,它似乎正常

您无法获取ftp.exe的输入和输出的原因是因为Microsoft Windows 2000 / XP / Vista中的内置ftp.exe使用控制台输入/输出 。

这不仅仅是ftp程序没有刷新缓冲区的情况。

如果用cmd.exe替换你的ftp.exe调用,你会发现它工作正常。 问题是你正在尝试读取FTP没有发送它的输出。
您不能使用常规方法来读取和写入子ftp.exe。 这是特定ftp.exe应用程序实现的结果。


如果您确实需要自动化内置的Windows ftp程序,则需要使用pinvoke和ReadConsoleOutput win32函数。

您的替代方案是:

  • 使用不同的ftp程序。 可能他们没有采用MS内置程序所做的控制台I / O方法
  • 使用FTP类,如FtpWebRequest。
  • 如果这不合适或不可能,请使用FTP的低级网络套接字接口。

另见: http : //discuss.joelonsoftware.com/default.asp?design.4.332503.5

我认为问题是输出缓冲区尚未刷新,因此您无法从ftp命令获得完整输出。

当您发出“退出”命令时,您应该看到help命令的输出。

我还没有解决方案,但如果我发现任何有用的东西,我会稍后回来。

http://ftp.exe一直在运行。 您将无法访问“结束”部分,因为当您发出帮助命令时,ftp.exe不会结束,它会显示提示并等待另一个命令。

如果要读取命令的响应,则需要解析响应并查找新提示。 也就是说,当你再次看到像ftp>这样的行时,你得到了整个响应。

(除非你有非常好的理由使用ftp.exe,否则请使用FtpWebRequest类)

根据经验(我以前曾多次使用过命令行FTP),使用FTP插件(例如一台Enterprise DT FTP )会好得多。

这样您就可以完全控制您的FTP会话,能够为您的用户提供更好的反馈,并以适当的方式应对错误。

最后一点,处理FTP时error handling非常重要。

您是否尝试过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";