Windows cómo redirigir el parámetro del archivo a stdout? (Windows equivalente a `/ dev / stdout`)

12

Consola de Windows:

  • La herramienta A puede escribir datos binarios en un archivo, pero no tiene la opción de decirle que use stdout.
  • La herramienta B puede leer datos binarios de stdin y procesar la información que contiene.

¿Cómo puedo obtener la salida de A canalizada a través de B sin usar un archivo intermedio?

En otras palabras: ¿cuál es el equivalente de Windows /dev/stdout?

--jeroen

Jeroen Wiert Pluimers
fuente

Respuestas:

18

Windows tiene un análogo para / dev / stdout, CON:

Me imagino que todavía funciona, considerando el programa de "compatibilidad heredada" de Microsoft.

Ah ... lo encontré. El soporte de Microsoft proporciona una lista de nombres reservados. No puede nombrar un archivo con estos nombres, y tienen significados especiales cuando se usan como entradas o salidas.

PODRÍAS poder usar CON como dispositivo de salida para enviar a stdout.

La lista:

   Name    Function
   ----    --------
   CON     Keyboard and display
   PRN     System list device, usually a parallel port
   AUX     Auxiliary device, usually a serial port
   CLOCK$  System real-time clock
   NUL     Bit-bucket device
   A:-Z:   Drive letters
   COM1    First serial communications port
   LPT1    First parallel printer port
   LPT2    Second parallel printer port
   LPT3    Third parallel printer port
   COM2    Second serial communications port
   COM3    Third serial communications port
   COM4    Fourth serial communications port
lornix
fuente
1
Gracias, realmente funciona (incluso en Win 8.1). Corremos acumulación con Unity, en modo batch: Unity.exe -batchmode -projectPath C:\***\Application -logFile -buildWebPlayer web -quit. Sin argumento (nombre de archivo) para -logFile- debe imprimir la salida a la consola, pero no lo hace. Después de agregar CON (es decir, - -logFile CON) - lo hace :-)
setevoy
@setevoy, ¿esto realmente funciona para usted con Unity en Windows? ¿Puedes dar más detalles? Solo causa que Unity se bloquee en Windows 7 y 10 usando Unity.exe -batchmode -quit -projectPath "%cd%" -logFile CON -buildWindows64Player ".\GameBuild\Generic.exe". El comando funciona bien sin el archivo de registro, pero no obtengo salida de compilación.
bbodenmiller
@bbodenmiller Lo sentimos, pero no puedo proporcionar más información: este proyecto se terminó hace casi 2 años :-)
setevoy
1
@bbodenmiller Parece que la salida del archivo de registro a stdout está rota en este momento. Ver: issuetracker.unity3d.com/issues/…
Verox
2
La respuesta es incorrecta. El dispositivo CON se muestra. Escribir en CON no puede ser redirigido (como en program > file.txt) ni utilizado en una tubería (para pasar datos al stdin de otro programa como en program | another_program). La salida escrita en CON siempre se muestra. La respuesta correcta es "Windows no tiene el equivalente de / dev / stdout"
Egor Skriptunoff
5

Windows no tiene equivalente directo a /dev/stdout.


Aquí está mi intento de escribir un programa C # que cree una tubería con nombre , que se puede asignar al programa A como nombre de archivo. Requiere .NET v4.

(C # porque el compilador viene con .NET runtime, y ¿qué computadora no tiene .NET en estos días?)

PipeServer.cs

using System;
using System.IO;
using System.IO.Pipes;

class PipeServer {
    static int Main(string[] args) {
        string usage = "Usage: PipeServer <name> <in | out>";
        if (args.Length != 2) {
            Console.WriteLine(usage);
            return 1;
        }

        string name = args[0];
        if (String.Compare(args[1], "in") == 0) {
            Pipe(name, PipeDirection.In);
        }
        else if (String.Compare(args[1], "out") == 0) {
            Pipe(name, PipeDirection.Out);
        }
        else {
            Console.WriteLine(usage);
            return 1;
        }
        return 0;
    }

    static void Pipe(string name, PipeDirection dir) {
        NamedPipeServerStream pipe = new NamedPipeServerStream(name, dir, 1);
        pipe.WaitForConnection();
        try {
            switch (dir) {
                case PipeDirection.In:
                    pipe.CopyTo(Console.OpenStandardOutput());
                    break;
                case PipeDirection.Out:
                    Console.OpenStandardInput().CopyTo(pipe);
                    break;
                default:
                    Console.WriteLine("unsupported direction {0}", dir);
                    return;
            }
        } catch (IOException e) {
            Console.WriteLine("error: {0}", e.Message);
        }
    }
}

Compilar con:

csc PipeServer.cs /r:System.Core.dll

csc se puede encontrar en %SystemRoot%\Microsoft.NET\Framework64\<version>\csc.exe

Por ejemplo, usando .NET Client Profile v4.0.30319 en un Windows XP de 32 bits:

"C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\csc.exe" PipeServer.cs /r:System.Core.dll

Correr:

PipeServer foo in | programtwo

en la ventana uno, y:

programone \\.\pipe\foo

en la ventana dos.

usuario1686
fuente
+1 ¡Esa es una solución genial! Lo intentaré pronto y te lo haré saber. Ahora primero un poco de Zzzzzzz :-)
Jeroen Wiert Pluimers
Un pensamiento más antes de hacer Zzzz: ¿qué hay de cerrar la tubería? Voy a pensar en cuál es el mejor mecanismo de señalización para programonecontar pipe, que se hace con\\.\pipe\foo
Jeroen Wiert Pluimers
@Jeroen: cuando termine de generar programonedatos, simplemente cerrará el archivo de salida que estaba usando. (Desde el lado del cliente, las canalizaciones funcionan de la misma manera que los archivos normales). Cuando lo hace, pipe.exemás precisamente, pipe.CopyTo(...)alcanzará EOF y simplemente saldrá.
user1686
@Jeroen: Además, hay una cosa que no he descubierto: cuando uso la herramienta en la outdirección opuesta ( ) (copiar stdin al tubo), muere con el error "Tubo roto" después de los primeros 1 kB. inSin embargo, no ocurre al copiar una tubería en stdout ( ), por lo que no debería afectar su programa. (Como dicen, los parches son bienvenidos. )
user1686
gracias intentaré esto más tarde la próxima semana, algo en el proyecto surgió con un prio más alto (¿no te gustan los proyectos de TI <g>)
Jeroen Wiert Pluimers
4

Basado en la respuesta de Grawity , he creado una versión extendida que permite iniciar un proceso directamente sin tener que usar múltiples ventanas de terminal.

Uso general:

PipeServer [in|out] [process name] [argument 1] [argument 2] [...]

La cadena "{pipe}" se reemplaza por la ruta de redireccionamiento.

Ejemplo del mundo real:

PipeServer.exe in "C:\Keil\UV4\Uv4.exe" -b "C:\Project\Project.uvproj" -j0 -o "{pipe}"

Esta línea de comandos se puede insertar directamente, por ejemplo, en Eclipse para redirigir el registro de compilación de un determinado generador externo a StdOut.

Esto es probablemente lo mejor que obtiene ...

Enlace

ntninja
fuente