Windows jak przekierować parametr pliku na standardowe wyjście? (Windowsowy odpowiednik `/ dev / stdout`)


13

Konsola Windows:

  • Narzędzie A może zapisywać dane binarne do pliku, ale nie ma opcji nakazującej użycie standardowego wyjścia.
  • Narzędzie B może odczytywać dane binarne ze standardowego wejścia i przetwarzać zawarte w nim informacje.

Jak mogę uzyskać dane wyjściowe z potoku A przez B bez użycia pliku pośredniego?

Innymi słowy: co to jest odpowiednik systemu Windows /dev/stdout?

--jeroen

Odpowiedzi:


20

Windows ma analogiczny dla / dev / stdout, CON:

Wyobrażam sobie, że nadal działa, biorąc pod uwagę trwający program Microsoftu „starszej zgodności”.

Ach .. znalazłem to. Pomoc techniczna Microsoft zawiera listę zastrzeżonych nazw. Nazw tych plików nie można nazwać, a mają one specjalne znaczenie, gdy są używane jako dane wejściowe lub wyjściowe.

MOŻESZ być w stanie użyć CON jako urządzenia wyjściowego do wysyłania na standardowe wyjście.

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

2
Dzięki, to naprawdę działa (nawet w Win 8.1). Prowadzimy budować z Jedności, w trybie wsadowym: Unity.exe -batchmode -projectPath C:\***\Application -logFile -buildWebPlayer web -quit. Bez argumentu (nazwa pliku) do -logFile- musi wypisać dane wyjściowe na konsolę, ale nie robi tego. Po dodaniu CON (tj. -logFile CON) - robi :-)
ustawia

@setevoy to faktycznie działa dla Ciebie z Unity w systemie Windows? Czy możesz podać więcej szczegółów? Po prostu powoduje awarię Unity dla mnie w Windows 7 i 10 przy użyciu Unity.exe -batchmode -quit -projectPath "%cd%" -logFile CON -buildWindows64Player ".\GameBuild\Generic.exe". Polecenie działa poprawnie bez pliku dziennika, ale nie otrzymuję danych wyjściowych kompilacji.
bbodenmiller

@bbodenmiller Przepraszamy, ale nie mogę podać więcej informacji - ten projekt został ukończony prawie 2 lata temu :-)
setevoy

1
@bbodenmiller Wygląda na to, że wyjście pliku dziennika na standardowe wyjście jest w tej chwili zepsute. Zobacz: Issuetracker.unity3d.com/issues/…
Verox

2
Odpowiedź jest zła. Wyświetlane jest urządzenie CON. Zapis do CON nie może być przekierowany (jak w program > file.txt) ani użyty w potoku (do przekazania danych do standardowego wejścia innego programu jak w program | another_program). Dane wyjściowe zapisane w CON zawsze są wyświetlane. Prawidłowa odpowiedź to „Windows nie ma odpowiednika / dev / stdout”
Egor Skriptunoff,

5

Windows nie ma bezpośredniego odpowiednika /dev/stdout.


Oto moja próba napisania programu w języku C #, który tworzy nazwany potok , który można podać programowi A jako nazwę pliku. Wymaga .NET v4.

(C #, ponieważ kompilator jest wyposażony w środowisko uruchomieniowe .NET, a który komputer nie ma obecnie .NET?)

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

Połącz z:

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

csc może być znaleziony w %SystemRoot%\Microsoft.NET\Framework64\<version>\csc.exe

Na przykład za pomocą .NET Client Profile v4.0.30319 w 32-bitowym systemie Windows XP:

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

Biegać:

PipeServer foo in | programtwo

w pierwszym oknie i:

programone \\.\pipe\foo

w oknie drugim.


+1 Teraz to fajne rozwiązanie! Spróbuję to wkrótce i dam znać. Teraz najpierw trochę Zzzzzzz :-)
Jeroen Wiert Pluimers

Jeszcze jedna myśl przed zrobieniem Zzzza: co powiesz na zamknięcie rury? Zastanowię się, jaki jest najlepszy mechanizm sygnalizacyjny, programoneaby powiedzieć pipe, że jest to zrobione\\.\pipe\foo
Jeroen Wiert Pluimers

@Jeroen: Po zakończeniu programonewysyłania danych, po prostu zamknie plik wyjściowy, którego używał. (Od strony klienta potoki działają tak samo jak zwykłe pliki.) Gdy to zrobi, pipe.exe- a dokładniej pipe.CopyTo(...)- osiągnie EOF i po prostu zakończy działanie.
user1686

@Jeroen: Jest jeszcze jedna rzecz, której nie zrozumiałem: kiedy używasz narzędzia w przeciwnym outkierunku () (kopiuj standardowe wejście na potok), umiera z błędem „Broken pipe” po pierwszym 1 kB. Nie dzieje się to jednak podczas kopiowania potoku do stdout ( in), więc nie powinno to wpływać na twój program. (Jak mówią, łatki są mile widziane. )
user1686

dzięki spróbuję tego później w przyszłym tygodniu, coś w projekcie wymyśliło wyższe prio (nie kochasz projektów IT <g>)
Jeroen Wiert Pluimers

4

Na podstawie odpowiedzi grawity stworzyłem rozszerzoną wersję, która umożliwia bezpośrednie uruchomienie procesu bez konieczności używania wielu okien terminala.

Ogólne zastosowanie:

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

Ciąg „{pipe}” jest następnie zastępowany ścieżką przekierowania.

Przykład ze świata rzeczywistego:

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

Ten wiersz poleceń można wstawić bezpośrednio do, na przykład, Eclipse, aby przekierować dziennik kompilacji określonego zewnętrznego konstruktora do StdOut.

To chyba najlepsze, co może ...

Połączyć

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.