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

时间:2010-03-29 10:24:44

标签: 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 = 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”命令外它似乎正常

6 个答案:

答案 0 :(得分:5)

为什么无法获取ftp.exe的输入和输出的原因是因为Microsoft Windows 2000 / XP / Vista中的内置ftp.exe使用Console Input/Output

这不仅仅是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

答案 1 :(得分:2)

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

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

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

答案 2 :(得分:2)

ftp.exe一直在运行。你不会到达'结束'部分,因为ftp.exe没有结束 当您发出help命令时,它会显示一个提示并等待另一个命令。

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

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

答案 3 :(得分:0)

根据经验(我以前曾多次使用过命令行FTP),使用像这样的Enterprise DT FTP这样的FTP插件会好得多。

通过这种方式,您可以完全控制FTP会话,能够为用户提供更好的反馈并以正确的方式应对错误。

最后一点,处理FTP时错误处理非常重要。

答案 4 :(得分:0)

您是否尝试过ReadLine而不是Read来读取重定向的输出?

答案 5 :(得分:0)

很少有人担心你没有正确关闭这个过程,你从进程读取输出的代码应该是这样的:

 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";