2010-03-29 8 views
6

Ejecuto el cmd ftp.exe a través de C# System.Diagnostics.Process type. Y utilizo el siguiente código para obtener el resultado "ftp.exe" luego de ingresar programáticamente un comando de "ayuda". Pero solo puedo obtener la primera línea del resultado. Y nunca llego a la parte de salida "final". Todo el programa parece bloqueado.¿Por qué no puedo obtener el resultado de ftp.exe por código?

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

Sin embargo, os escribo un programa simple que sólo utilice Console.WriteLine() para escribir alguna salida a su flujo de salida estándar. Y lo pruebo con el código anterior. Funciona bien. Simplemente no puedo entender por qué el código anterior no puede funcionar con ftp.exe? La única diferencia entre mi programa SimpleConsoleOutput y el "ftp.exe" es que ftp.exe tiene su propio símbolo del sistema interactivo.

(--------------- Nuevo Progreso -----------------)

Acá algunos avances de mi investigación personal

escribo 2 hilos para escribir en el StdIn y leídos de StdOut de "ftp.exe", y la salida es la siguiente:

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

y la última lista de comandos no es aún completa.

Parece que la salida del comando de ayuda se divide en dos partes.

La primera parte es:

Commands may be abbreviated. Commands are: 

La segunda parte es:

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

y todas las partes están 1ª wrtten a la corriente de StdOut "ftp.exe" antes de todas las partes 2ª . ¿Cómo puede ser esto? Gracias por tus comentarios.

He probado con otro comando de la "ftp.exe", y parece normal excepto el comando "ayuda"

+0

Solo por curiosidad ¿por qué estás tan interesado en la salida del ftp.exe si no la intención de usarlo? – CResults

+1

Hola, CResults. Estoy investigando sobre las transmisiones estándar de las aplicaciones de consola. Y ftp.exe es uno de mis objetivos de experimento. – smwikipedia

Respuesta

5

La razón por qué no se puede conseguir la entrada y salida de ftp.exe es porque el ftp.exe incorporado de Microsoft Windows 2000/XP/Vista usa Console Input/Output.

No es simplemente un caso de que el programa ftp no limpie sus búfers.

Si reemplaza su invocación de ftp.exe con algo como cmd.exe, verá que funciona bien. El problema es que está tratando de leer el resultado donde FTP no lo está enviando.
No puede usar el enfoque habitual para leer y escribir en un ftp.exe hijo. Esto es consecuencia de la implementación de esa aplicación particular de ftp.exe.


Si realmente necesita para automatizar la incorporada en el programa de FTP de Windows, tendrá que recurrir a PInvoke y la función ReadConsoleOutput Win32.

Sus alternativas son:

  • uso de un programa de FTP diferente. Probablemente no recurran al enfoque de E/S de la consola que el programa incorporado de MS hace
  • usan una clase de FTP, como FtpWebRequest.
  • si eso no es apropiado o posible, use una interfaz de socket de red de bajo nivel para FTP.

ver también: http://discuss.joelonsoftware.com/default.asp?design.4.332503.5

+2

Muchas gracias, Cheeso. Me pregunto dónde exactamente el ftp.exe envía su salida a? Hay un hecho que no se puede ignorar, obtengo el resultado del comando "ayuda" del StdOut, aunque después de un poco de "latencia" ... – smwikipedia

+0

Hola, Cheeso, espero que puedas darme algunos comentarios más sobre mi última preocupación. .. Gracias. – smwikipedia

+0

No lo sé en realidad; pero, ¿qué estás tratando de hacer? Si desea realizar operaciones de FTP hay otras formas de lograr eso. ¿Por qué la restricción que debe usar ftp.exe, cuando es claramente poco práctico cuando está automatizado? – Cheeso

2

Creo que el problema es que el búfer de salida no se vacía sin embargo y por lo tanto no lo hacen obtener el resultado completo del comando ftp.

Cuando emita un comando "salir" debería ver el resultado del comando de ayuda.

Aún no tengo una solución, pero volveré más tarde si encuentro algo útil.

+0

Gracias, 0xA3. un comando "salir" puede ser una solución. Pero solo quiero saber la diferencia entre ftp.exe y mi SimpleConsoleOutput.exe. ¿Por qué este último podría correr con suavidad? – smwikipedia

+0

@smwikipedia: Creo que 0xA3 ya explicó bastante bien en la respuesta -> "el búfer de salida no se vació todavía" –

0

Por experiencia (he utilizado varias veces la línea de comando FTP), sería mucho mejor utilizar un complemento FTP como este Enterprise DT FTP.

De esta manera tendrá un control total sobre su sesión de FTP, podrá dar mejores comentarios a su usuario y manejar los errores de una manera adecuada.

El último punto, el manejo de errores es muy importante cuando se trata de FTP.

+0

Pensé lo mismo, y de hecho, ftp.exe/help dará salida a STDERR. Sin embargo, en modo interactivo, la salida va a STDOUT. –

+0

Ahh bien, ¡aprendes algo todos los días! - Editaré mi respuesta, pero sigo creyendo que ejecutar ftp.exe como un proceso externo es una mala forma de manejar el FTP. Hay demasiadas cosas que pueden salir mal para dejarlo en el código externo. – CResults

+2

Sí, es mucho mejor usar una biblioteca FTP o la clase 'FtpWebRequest'. –

2

ftp.exe sigue funcionando. No llegará a la parte 'final', ya que ftp.exe no termina en cuando emite el comando de ayuda, presenta una solicitud y espera otro comando.

Si desea leer la respuesta del comando, debe analizar la respuesta y buscar un nuevo mensaje.Es decir, tienes toda la respuesta cuando ves una línea como ftp> nuevamente.

(A menos que tenga muy, muy buenas razones para utilizar ftp.exe, utilice la clase en lugar FtpWebRequest)

+0

Gracias, nos. Pero si no voy a llegar a la parte 'final', ¿por qué mi programa se detiene justo después de la primera línea de la salida del comando "ayuda"? – smwikipedia

0

¿Ha intentado ReadLine en lugar de Read para leer desde la salida redirigida?

+0

Thansk por su respuesta. Sí, he probado ReadLine(), ReadToEnd() ... ninguno de ellos podría obtener la salida correctamente. – smwikipedia

0

poco preocupado de que no se cierre el proceso correctamente, el código para la lectura de salida de un proceso debe ser algo como:

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 

No estoy seguro si eso sería resolver este problema específico sin embargo.

Además, ¿por qué escribir 'ayuda' a la entrada estándar, qué no funciona si lo hace

process.Arguments = "help"; 
+0

Gracias por su respuesta. Escribo el comando "help" para StdIn porque quiero emular el símbolo del sistema interactivo de "ftp.exe". – smwikipedia

+0

Ah, ya veo. ¿Has intentado comprobar el stdout para '> ftp', y luego enviar 'bye' a stdin? Luego debe ir a la llamada WaitForExit en lugar de esperar a que ingrese más información. –

Cuestiones relacionadas