Windows コンソール:
- ツール A はバイナリ データをファイルに書き込むことができますが、stdout を使用するように指示するオプションはありません。
- ツール B は、stdin からバイナリ データを読み取り、その中の情報を処理できます。
中間ファイルを使用せずに、A からの出力を B にパイプするにはどうすればよいですか?
言い換えると、 の Windows 版とは何でしょうか/dev/stdout
?
答え1
Windows には /dev/stdout に類似するものがありますが、CON は次のとおりです。
Microsoft の継続的な「レガシー互換性」プログラムを考慮すると、まだ機能すると思います。
ああ…見つけた。 マイクロソフト サポート予約名のリストを示します。これらの名前をファイルに付けることはできません。また、入力または出力として使用する場合は特別な意味を持ちます。
CON を出力デバイスとして使用して、stdout に送信できる可能性があります。
リスト:
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
Windows には に直接相当するものはありません/dev/stdout
。
これは、C#プログラムを作成して、名前付きパイプは、プログラム A にファイル名として与えることができます。.NET v4 が必要です。
(C# は、コンパイラに .NET ランタイムが付属しているためです。最近では、.NET が搭載されていないコンピューターなどあるでしょうか?)
パイプサーバー.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);
}
}
}
コンパイル:
csc PipeServer.cs /r:System.Core.dll
csc
見つけることができる%SystemRoot%\Microsoft.NET\Framework64\<version>\csc.exe
たとえば、32 ビット Windows XP で .NET Client Profile v4.0.30319 を使用する場合:
"C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\csc.exe" PipeServer.cs /r:System.Core.dll
走る:
PipeServer foo in | programtwo
ウィンドウ 1 では、次のようになります。
programone \\.\pipe\foo
ウィンドウ2で。
答え3
に基づく重力の回答 複数のターミナル ウィンドウを使用せずにプロセスを直接開始できる拡張バージョンを作成しました。
一般的な使用法:
PipeServer [in|out] [process name] [argument 1] [argument 2] [...]
文字列「{pipe}」はリダイレクト パスに置き換えられます。
実際の例:
PipeServer.exe in "C:\Keil\UV4\Uv4.exe" -b "C:\Project\Project.uvproj" -j0 -o "{pipe}"
このコマンドラインを Eclipse などに直接挿入して、特定の外部ビルダーのビルド ログを StdOut にリダイレクトすることができます。
おそらくこれが最高でしょう...
class PipeServer
{
static
int
Main(string[] args)
{
if(args.Length < 2
||(System.String.Compare(args[0], "in") != 0
&& System.String.Compare(args[0], "out") != 0)) {
System.Console.WriteLine("Usage: PipeServer <in | out> <process> <args>");
return 1;
}
///////////////////////////////////
// // // Process arguments // // //
///////////////////////////////////
// Convert pipe direction
System.IO.Pipes.PipeDirection pipe_dir = 0;
if(System.String.Compare(args[0], "in") == 0) {
pipe_dir = System.IO.Pipes.PipeDirection.In;
}
if(System.String.Compare(args[0], "out") == 0) {
pipe_dir = System.IO.Pipes.PipeDirection.Out;
}
// Find process name to start
string proc_name = args[1];
// Build commandline argument string
string proc_args = "";
for(System.UInt16 i = 2; i < args.Length; i++) {
if(args[i].IndexOf(" ") > -1) {
proc_args += "\"" + args[i].Replace("\"", "\\\"") + "\" ";
} else {
proc_args += args[i] + " ";
}
}
// Create server
string pipe_name = "";
System.IO.Pipes.NamedPipeServerStream pipe_stream = null;
for(System.UInt16 i = 1; i < 65535; i++) {
// Generate new pipe name
pipe_name = "pipeserver_" + System.Convert.ToString(i);
try {
// Start server
pipe_stream = new System.IO.Pipes.NamedPipeServerStream(pipe_name, pipe_dir, 1);
break;
} catch(System.IO.IOException _) {
continue;
}
}
if(pipe_stream == null) {
System.Console.WriteLine("Could not create pipe");
return 1;
}
// Make sure the process knows about the pipe name
proc_args = proc_args.Replace("{pipe}", "\\\\.\\pipe\\" + pipe_name);
// Run process
System.Diagnostics.Process proc = new System.Diagnostics.Process();
proc.StartInfo.FileName = proc_name;
proc.StartInfo.Arguments = proc_args;
proc.Start();
// Connect pipes and wait until EOF
pipe_stream.WaitForConnection();
try {
if(pipe_dir == System.IO.Pipes.PipeDirection.In) {
pipe_stream.CopyTo(System.Console.OpenStandardOutput());
}
if(pipe_dir == System.IO.Pipes.PipeDirection.Out) {
System.Console.OpenStandardInput().CopyTo(pipe_stream);
}
} catch (System.IO.IOException e) {
System.Console.WriteLine("error: {0}", e.Message);
return 1;
}
// Wait for process termination
while(!proc.HasExited) {
proc.WaitForExit();
}
// Return correct exit code
return proc.ExitCode;
}
}