La salida del programa se pierde cuando se pasa a través de PsExec

(Esta es una pregunta que mi compañero de trabajo publicóen otra parte, pero pensé que lo publicaría aquí para ver si podía golpear a otra audiencia.)

Hola a todos, estoy probando la posibilidad de escribir una pequeña aplicación Java que utilizará Psexec para iniciar trabajos remotos. En el curso de las pruebas de vinculación de la entrada estándar y la salida estándar de un programa java para psexec me encontré con un error extraño.

Mi programa de prueba es un programa básico de eco. Inicia un hilo para leer desde stdin y luego canaliza la salida de lectura directamente a stdout. Cuando se ejecuta en la máquina local, no desde psexec, funciona a la perfección. Exactamente como debe ser.

Sin embargo, cuando lo llamo desde PsExec la primera vez que la entrada se canaliza directamente a la salida estándar, se pierde. Lo que hace que el error sea realmente bizzare es que es solo la primera vez que la entrada se canaliza directamente a la salida estándar que se pierde. Si la cadena de entrada se agrega a otra cadena, funciona bien. Ya sea un literal de cadena o una variable de cadena. Sin embargo, si la cadena de entrada se envía directamente a la salida estándar, no se realiza. La segunda vez que se envía a la salida estándar, pasa bien, y cada vez que se va después.

Estoy completamente perdido en cuanto a lo que está pasando aquí. He intentado probar cada error posible que se me pueda ocurrir. Me he quedado sin ideas. ¿Perdí uno o es solo algo dentro de psexec?

Aquí está el código en cuestión, está en tres clases (una de las cuales implementa una interfaz que es una única función interace).

La clase principal:

public class Main {
    public static void main(String[] args) {
        System.out.println("Starting up.");

        CReader input = new CReader(new BufferedReader(
            new InputStreamReader(System.in)));
        CEcho echo = new CEcho();

        input.addInputStreamListener(echo);
        input.start();

        System.out.println("Successfully started up.  Awaiting input.");
    }
}

La clase CReader, que es el hilo que lee desde stdin:

public class CReader extends Thread {
    private ArrayList<InputStreamListener> listeners = 
        new ArrayList<InputStreamListener>();
    private boolean exit = false;
    private Reader in;

    public CReader(Reader in) {
        this.in = in;
    }

    public void addInputStreamListener(InputStreamListener listener) {
        listeners.add(listener);
    }

    public void fireInputRecieved(String input) {

        if(input.equals("quit"))
        exit = true;

        System.out.println("Input string has made it to fireInputRecieved: "
            + input);

        for(int index = 0; index < listeners.size(); index++)
            listeners.get(index).inputRecieved(input);
    }

    @Override
    public void run() {

        StringBuilder sb = new StringBuilder();
        int current = 0, last = 0;

        while (!exit) {
            try {
                current = in.read();
            }
            catch (IOException e) {
                System.out.println("Encountered IOException.");
            }

            if (current == -1) {
                break;
            }

            else if (current == (int) '\r') {
                if(sb.toString().length() == 0) {
                    // Extra \r, don't return empty string.
                    continue;
                }
                fireInputRecieved(new String(sb.toString()));
                sb = new StringBuilder();
            }

            else if(current == (int) '\n') {
                if(sb.toString().length() == 0) {
                    // Extra \n, don't return empty string.
                    continue;
                }
                fireInputRecieved(new String(sb.toString()));
                sb = new StringBuilder();
            }
            else {
                System.out.println("Recieved character: " + (char)current);
                sb.append((char) current);
                last = current;
            }
        }       
    }
}

La clase CEcho, que es la clase que lo canaliza de nuevo a la salida estándar:

public class CEcho implements InputStreamListener {
    public void inputRecieved(String input) {
        System.out.println("\n\nSTART INPUT RECIEVED");
        System.out.println("The input that has been recieved is: "+input);
        System.out.println("It is a String, that has been copied from a " +
            "StringBuilder's toString().");
        System.out.println("Outputting it cleanly to standard out: ");
        System.out.println(input);
        System.out.println("Outputting it cleanly to standard out again: ");
        System.out.println(input);
        System.out.println("Finished example outputs of input: "+input);
        System.out.println("END INPUT RECIEVED\n\n");
    }
}

Y finalmente, aquí está la salida del programa:

>psexec \\remotecomputer "C:\Program Files\Java\jre1.6.0_05\bin\java.exe" -jar "C:\Documents and Settings\testProram.jar"

PsExec v1.96 - Execute processes remotely
Copyright (C) 2001-2009 Mark Russinovich
Sysinternals - www.sysinternals.com


Starting up.
Successfully started up.  Awaiting input.
Test
Recieved character: T
Recieved character: e
Recieved character: s
Recieved character: t
Input string has made it to fireInputRecieved: Test


START INPUT RECIEVED
The input that has been recieved is: Test
It is a String, that has been copied from a StringBuilder's toString().
Outputting it cleanly to standard out:

Outputting it cleanly to standard out again:
Test
Finished example outputs of input: Test
END INPUT RECIEVED

Respuestas a la pregunta(13)

Su respuesta a la pregunta