6

I execute the ftp.exe cmd through a C# System.Diagnostics.Process type. And I use the following code to get the "ftp.exe" output after I programmatically enter a "help" command. But I can only get the first line of the result. And I never get to the "end" output part. The whole program seems blocked.

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

However, I write a simple program which only use Console.Writeline() to write some output to its StdOut stream. And I test it with the above code. It works fine. I just cannot figure out why the above code cannot work with ftp.exe? The only difference between my SimpleConsoleOutput program and the "ftp.exe" is that the ftp.exe has its own interactive command prompt.

(--------------- New Progress -----------------)

Here're some progress of my personal investigation.

I write 2 threads to write to the StdIn and read from StdOut of "ftp.exe", and the output is like this:

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
...

and the last commands list is not even complete.

It seems that the help command output is divided into two parts.

The 1st part is:

Commands may be abbreviated.  Commands are:

The 2nd part is:

!              delete          literal         prompt          send
?              debug           ls              put             status
append         dir             mdelete         pwd             trace
...

And all the 1st parts are wrtten to the StdOut stream of "ftp.exe" before all the 2nd parts. How coud this be?? Thanks for your comments.

I tested with other command of the "ftp.exe", and it seems normal except the "help" command

smwikipedia
  • 61,609
  • 92
  • 309
  • 482
  • Just out of interest why are you so interested in the output of ftp.exe if you do not intend on using it? – CResults Apr 06 '10 at 15:41
  • 1
    Hi, CResults. I am making some research about the Standard Streams of console applications. And ftp.exe is one of my experiment targets. – smwikipedia Apr 06 '10 at 16:17

6 Answers6

5

The reason why you cannot get the input and output of ftp.exe is because the built-in ftp.exe from Microsoft Windows 2000/XP/Vista uses Console Input/Output.

It is not simply a case of the ftp program not flushing its buffers.

If you replace your invocation of ftp.exe with something like cmd.exe, you'll see that it works fine. The problem is you are trying to read output where FTP is not sending it.
You cannot use the regular approach to reading and writing to a child ftp.exe. This is a consequence of the implementation of that particular ftp.exe app.


If you truly need to automate the built-in Windows ftp program, you will need to resort to pinvoke and the ReadConsoleOutput win32 function.

Your alternatives are:

  • use a different ftp program. Likely they do not resort to the console I/O approach that the MS built-in program does
  • use an FTP class, like FtpWebRequest.
  • if that's not appropriate or possible, use a low level network socket interface to FTP.

see also: http://discuss.joelonsoftware.com/default.asp?design.4.332503.5

Cheeso
  • 189,189
  • 101
  • 473
  • 713
  • 2
    Thanks very much, Cheeso. I am wondering where exactly does the ftp.exe send its output to? There's one fact that cannot be ignored, I do get the output of "help" command from the StdOut, though after quite some "latency"... – smwikipedia Apr 02 '10 at 03:24
  • Hi, Cheeso, hope you could give me some more comments about my last concern... thanks. – smwikipedia Apr 07 '10 at 06:29
  • I don't know actually; but what are you trying to do? If you want to perform FTP operations there are other ways of accomplishing that. Why the constraint that you must use ftp.exe, when it is clearly impractical when automated? – Cheeso Apr 07 '10 at 13:40
  • Hi, Cheeso. I am making some research about the Standard Streams of console applications. And ftp.exe is one of my experiment targets. – smwikipedia Apr 08 '10 at 12:47
2

I think the problem is that the output buffer is not flushed yet and hence you don't get the full output from the ftp command.

When you emit a "quit" command you should see the output of the help command.

I have no solution yet, but I'll come back later if I find anything helpful.

Dirk Vollmar
  • 172,527
  • 53
  • 255
  • 316
  • Thanks, 0xA3. a "quit" command can be a workaround. But I just want to know the difference between the ftp.exe and my SimpleConsoleOutput.exe. Why the latter one could run smootyly? – smwikipedia Mar 29 '10 at 11:12
  • @smwikipedia: I believe 0xA3 already explained that quite well in the answer -> "the output buffer is not flushed yet" – Billy ONeal Apr 01 '10 at 02:52
2

ftp.exe just keeps running. You won't get to the 'end' part, since ftp.exe doesn't end when you issue the help command, it presents a prompt and waits for another command.

If you want to read the response of the command, you need to parse the response and look for a new prompt. That is, you got the whole response when you see a line like ftp> again.

(Unless you have very,very good reasons to use ftp.exe, use the FtpWebRequest class rather)

nos
  • 223,662
  • 58
  • 417
  • 506
  • Thanks, nos. But if I won't get to the 'end' part, why my program stops just after the first line of the "help" command output? – smwikipedia Mar 29 '10 at 11:16
0

From experience (I have used command line FTP numerous times before) you would be far better off using an FTP plugin such as this one Enterprise DT FTP.

This way you will have full control over your FTP session, be able to give better feedback to your user and cope with errors in a proper way.

The last point, error handling is very important when dealing with FTP.

CResults
  • 5,100
  • 1
  • 22
  • 28
  • I thought the same, and indeed, ftp.exe /help will output to STDERR. In interactive mode however, output goes to STDOUT. – Dirk Vollmar Mar 29 '10 at 10:54
  • Ahh ok, you learn something everyday! - I will edit my answer but I still believe that running ftp.exe as an external process is a bad way to handle FTP. There are too many things that can go wrong to leave it to external code. – CResults Mar 29 '10 at 11:04
  • 2
    Yes, much better to use an FTP library or the `FtpWebRequest` class. – Dirk Vollmar Mar 29 '10 at 11:12
  • Personally I prefer FtpClient in RemObjects Internet Pack for .NET :) http://www.remobjects.com/ip.aspx – Lex Li Mar 30 '10 at 07:46
  • Nice pack. I settled with edtFTP as it was the first free one I could find :-) – CResults Mar 30 '10 at 13:26
  • Well, in fact, the point here is not to find a proper ftp utility, but to test with the StdIn and StdOut streams. Thanks anyway. – smwikipedia Apr 01 '10 at 02:49
0

Have you tried ReadLine instead of Read to read from the redirected output?

leppie
  • 115,091
  • 17
  • 196
  • 297
0

Little concerned that you are not closing down the process properly, your code for reading output from a process should look something like:

 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 

Not sure if that would resolve this specific issue though.

Also, why are you writing 'help' to the standard input, does it not work if you do

process.Arguments = "help";
Fiona - myaccessible.website
  • 14,481
  • 16
  • 82
  • 117
  • Thanks for your reply. I write the "help" command to the StdIn because I want to emulate the interactive command prompt of the "ftp.exe". – smwikipedia Mar 29 '10 at 14:12
  • Ah I see. Have you tried checking the stdout for '>ftp', and then sending "bye" to stdin? Then it should go to the WaitForExit call instead of just waiting for more input. – Fiona - myaccessible.website Mar 29 '10 at 15:25