Windows では、コマンド ラインで stdout を (名前付き) パイプにリダイレクトできますか?

Windows では、コマンド ラインで stdout を (名前付き) パイプにリダイレクトできますか?

リダイレクトする方法はありますか?標準出力プロセスのWin32 コンソール名前付きパイプ名前付きパイプは Windows に組み込まれており、便利な概念ではありますが、コマンド ラインから使用されているのを見たことがありません。

つまり、次のようになりますexample.exe >\\.\mypipe。(この構文は正しくないかもしれませんが、要点はわかります。)リダイレクトできるようにしたいです。標準出力そして標準エラー出力同時に異なるパイプに接続します。

IO の遅さ、IO バッファ、ファイル ロック、アクセス権、使用可能なハード ディスク領域、上書きの決定、意図しない永続性などの処理を回避するために、物理ファイルを代替として使用することは避けたいと思います。

もう1つの理由は、従来のWindowsツールセット(テキスト)ファイルベースの哲学に基づいて設計されていないUnixの場合また、名前付きパイプは Windows では簡単にマウントできませんでした。

最後に、優れたコンセプトを有効に活用できるかどうかという好奇心があります。

答え1

なぜファイルにリダイレクトしたくないのかわかりません。ここでは 2 つの方法を紹介します。1 つはファイルにリダイレクトして読み取る方法で、もう 1 つは一連のプログラムです。


名前付きパイプ

私がやったことは、.NET 4 用の 2 つのプログラムを書くことでした。1 つは名前付きパイプに出力を送信し、もう 1 つはこのパイプから読み取り、コンソールに表示します。使い方は非常に簡単です。

asdf.exe | NamedPipeServer.exe "APipeName"

別のコンソール ウィンドウで:

NamedPipeClient.exe "APipeName"

残念ながら、Windows コマンド プロンプトのパイプ演算子 ( ) の制限により、これはリダイレクトstdout(またはstdin、または組み合わせ) のみ可能で、単独ではできません。パイプ演算子を介して送信する方法がわかれば、機能するはずです。または、サーバーを変更してプログラムを起動し、 を具体的にリダイレクトすることもできます。必要な場合は、コメントでお知らせください (または自分で実行してください)。C# および .NET の「プロセス」ライブラリの知識があれば、それほど難しくはありません。stderr|stderrstderr

ダウンロードできますサーバそしてそのクライアント

接続後にサーバーを閉じると、クライアントもすぐに閉じます。接続後にクライアントを閉じると、サーバーを介して何かを送信しようとするとすぐにサーバーが閉じます。壊れたパイプを再び接続することはできません。主な理由は、今そのような複雑なことをする気にはなれないからです。また、サーバーごとに1つのクライアント

ソースコード

これらはC#で書かれています。説明してもあまり意味がありません。.NETを使用しています。名前付きパイプサーバーストリームそして名前付きパイプクライアントストリーム

サーバー:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO.Pipes;
using System.IO;

namespace NamedPipeServer
{
    class Program
    {
        static void Main(string[] args)
        {
            if (args == null || args.Length == 0)
            {
                Console.Error.WriteLine("[NamedPipeServer]: Need pipe name.");
                return;
            }
            
            NamedPipeServerStream PipeServer = new NamedPipeServerStream(args[0], System.IO.Pipes.PipeDirection.Out);
            PipeServer.WaitForConnection();
            StreamWriter PipeWriter = new StreamWriter(PipeServer);
            PipeWriter.AutoFlush = true;

            string tempWrite;

            while ((tempWrite = Console.ReadLine()) != null)
            {
                try
                {
                    PipeWriter.WriteLine(tempWrite);
                }
                catch (IOException ex)
                {
                    if (ex.Message == "Pipe is broken.")
                    {
                        Console.Error.WriteLine("[NamedPipeServer]: NamedPipeClient was closed, exiting");
                        return;
                    }
                }
            }

            PipeWriter.Close();
            PipeServer.Close();
        }
    }
}

クライアント:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO.Pipes;
using System.IO;

namespace NamedPipeClient
{
    class Program
    {
        static void Main(string[] args)
        {
            if (args == null || args.Length == 0)
            {
                Console.Error.WriteLine("[NamedPipeClient]: Need pipe name.");
                return;
            }

            NamedPipeClientStream PipeClient = new NamedPipeClientStream(".", args[0], System.IO.Pipes.PipeDirection.In);
            PipeClient.Connect();
            StreamReader PipeReader = new StreamReader(PipeClient);

            string tempRead;

            while ((tempRead = PipeReader.ReadLine()) != null)
            {
                Console.WriteLine(tempRead);
            }

            PipeReader.Close();
            PipeClient.Close();
        }
    }
}

ファイルへのリダイレクト

type NUL>StdErr.temp
start powershell -c Get-Content StdErr.temp -Wait
MyExecutable.exe 2>StdErr.temp
  1. 空のファイルを作成する
  2. ファイルを監視する新しいコンソールウィンドウを起動します
  3. 実行ファイルを実行し、stderr出力をそのファイルにリダイレクトする

stdoutこれにより、 を監視するコンソール ウィンドウが 1 つ(および を提供stdin)、 を監視するコンソール ウィンドウがもう 1 つという望ましい効果が得られますstderr

模倣するものなら何でもtail使えます。PowerShell メソッドは Windows でネイティブに動作しますが、少し遅いかもしれません (つまり、ファイルへの書き込みと画面への表示の間に遅延があります)。このStackOverflowの質問tail他の選択肢については。

唯一の問題は、一時ファイルが非常に大きくなる可能性があることです。回避策としては、ファイルにコンテンツがある場合にのみ印刷し、その後すぐにファイルをクリアするループを実行することが考えられますが、競合状態が発生します。

答え2

この質問にまだ正しく答えられていないことに驚きました。確かにUNC パスシステムによって名前付きパイプに割り当てられ、ネットワーク内のどのマシンからでもアクセス可能で、通常のファイルのように使用できます。

program.exe >\\.\pipe\StdOutPipe 2>\\.\pipe\StdErrPipe

このマシンに「StdOutPipe」および「StdErrPipe」という名前のパイプが存在すると仮定して、それらのパイプに接続して書き込みを試みます。 のpipe部分は、名前付きパイプが必要であることを指定する部分です。

答え3

サーバーからクライアントの DOS ウィンドウにデータをすぐにまたは後で Windows パイプで送信したいという要望は、小さな RAM ドライブで満たされるかもしれません。同じメモリがデータ用に割り当てられ、ファイル システムのような名前で書き込み/読み取りが行われます。クライアントは、使い果たしたファイルを削除して別のファイルを待つか、コンピューターのシャットダウン時に消えるようにそのままにしておきます。

関連情報