Win32コンソール のプロセスの 標準出力 を 名前付きパイプ にリダイレクトする方法はありますか?名前付きパイプはWindowsに組み込まれており、便利なコンセプトですが、コマンドラインから使用されることはありません。
つまり。お気に入り example.exe >\\.\mypipe
。 (この構文は正しくないかもしれませんが、要点はわかります。)stdoutおよびstderrを同時に別のパイプにリダイレクトできるようにしたいと思います。
IO slowness、IO buffers、file locks、access rights、available hard disk space)を回避するために、物理ファイルを代替として使用しない、上書きする決定、意味のない永続性など。
もう1つの理由は、従来のWindows ツールのセット が(テキスト)ファイルベースの哲学に基づいて設計されていないためです nixの場合と同様 。また、名前付きパイプをWindowsにマウントすることはできません。
最後に、優れたコンセプトをうまく活用できるかどうかは好奇心です。
ファイルにリダイレクトしたくない理由がわかりません。ここで提供する方法は2つあります。 1つはファイルへのリダイレクトとファイルからの読み取り、もう1つは一連のプログラムです。
私がしたことは、.NET 4用の2つのプログラムを作成することでした。1つは出力を名前付きパイプに送信し、もう1つはこのパイプから読み取り、コンソールに表示します。使い方は非常に簡単です:
asdf.exe | NamedPipeServer.exe "APipeName"
別のコンソールウィンドウで:
NamedPipeClient.exe "APipeName"
残念ながら、これはstdout
(またはstdin
またはそれらの組み合わせ)のみをリダイレクトでき、stderr
自体はリダイレクトできません。これは、パイプ演算子(|
)(Windowsコマンドプロンプト)。そのパイプ演算子を介してstderr
を送信する方法を理解した場合、それは機能するはずです。または、サーバーを変更してプログラムを起動し、stderr
をリダイレクトすることもできます。それが必要な場合は、コメントで知らせてください(または自分で行ってください)。 C#と.NETの「プロセス」ライブラリに関する知識があれば、それほど難しくありません。
server および client をダウンロードできます。
接続後にサーバーを閉じると、クライアントはすぐに閉じます。接続後にクライアントを閉じると、それを介して何かを送信しようとするとすぐにサーバーが閉じます。壊れたパイプを再接続することはできません。今はとても複雑なもの。また、サーバーごとに1つのクライアントに制限されます。
これらはC#で記述されています。それを説明しようとしてもあまり意味がありません。 .NET NamedPipeServerStream および NamedPipeClientStream を使用します。
サーバー:
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
stderr
出力をそのファイルにリダイレクトしますこれにより、stdout
を監視する(およびstdin
を提供する)1つのコンソールウィンドウと、stderr
を監視する別のコンソールウィンドウの望ましい効果が得られます。
tail
を模倣したものであれば何でも機能します。 PowerShellメソッドはWindowsでネイティブに機能しますが、少し遅い場合があります(つまり、ファイルへの書き込みと画面への表示の間に待ち時間が発生します)。他のtail
代替案については、 このStackOverflowの質問 を参照してください。
唯一の問題は、一時ファイルが非常に大きくなる可能性があることです。考えられる回避策は、ファイルにコンテンツがある場合にのみ印刷するループを実行し、直後にファイルをクリアすることですが、これにより競合状態が発生します。
これがまだ正しく答えられていないことに驚いています。実際、システムによって名前付きパイプに割り当てられた NCパス があり、ネットワーク内の任意のマシンからアクセス可能であり、通常のファイルのように使用できます。
program.exe >\\.\pipe\StdOutPipe 2>\\.\pipe\StdErrPipe
「StdOutPipe」および「StdErrPipe」という名前のパイプがこのマシンに存在すると想定すると、これはそれらに接続して書き込みを試みます。 pipe
の部分は、名前付きパイプが必要であることを指定するものです。
標準のシェル(CMD.EXE)では使用できません。プログラマにとっては かなり簡単 です。開始したプロセスの2つのパイプを取得するだけです。