Windows 控制台:
- 工具 A 可以将二进制数据写入文件,但没有选项告诉它使用标准输出。
- 工具 B 可以从标准输入读取二进制数据并处理其中的信息。
如何在不使用中间文件的情况下通过 B 获得 A 的输出?
换句话说:Windows 的对应版本是什么/dev/stdout
?
答案1
Windows 确实有一个 /dev/stdout 的类似物,CON:
考虑到微软正在进行的“遗留兼容性”计划,我想它仍然有效。
啊。。找到了。 Microsoft 支持给出保留名称列表。您不能用这些名称命名文件,并且它们在用作输入或输出时具有特殊含义。
您也许能够使用 CON 作为输出设备发送到标准输出。
列表:
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?)
管道服务器
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
在窗口一中,并且:
programone \\.\pipe\foo
在第二个窗口。
答案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;
}
}