我有以下代码要写入 Windows 命令控制台:
use Win32::Console;
my $console = new Win32::Console(Win32::Console::STD_ERROR_HANDLE());
my $defaultAttribute = $console->Attr();
my $defaultFG = ($defaultAttribute & 0x0F);
my $defaultBG = ($defaultAttribute & 0xF0);
$console->Attr($defaultBG | $Win32::Console::FG_LIGHTGREEN);
$console->Write("blah blah");
$console->Attr($defaultAttribute);
如果用户在调用我的脚本时重定向 STDERR,此代码将失败:
perl myscript.pl 2> foo
如何获取进程所附加的 Win32 控制台的句柄而不引用标准句柄之一,以便用户进行什么重定向都无关紧要?
我想要的效果是能够在正常程序输出之后立即在控制台上写入一条消息,而不管任何重定向如何,与 bash 内置 time
命令类似。本质上,类似于在 Unix 中打开并写入 /dev/tty
。
我尝试过 my $console = new Win32::Console()
分配一个新控制台,然后分配 $console->Display()
但这完全有效错误的事情。
最佳答案
问完这个问题后,我进行了更深入的研究,并通过使用令人讨厌的 hack 解决了它:
use Win32API::File qw(createFile);
use Win32::Console;
my $handle = createFile('CONOUT$', 'rwke') or die "conout\$: $^E\n";
# my $console = new Win32::Console($handle) or die "new console: $^E\n";
my $console = bless {handle => $handle}, 'Win32::Console';
我查看了 new()
的代码里面的功能Win32::Console
并看到它只是创建一个包含控制台句柄的哈希。如果参数指定 stdin/stdout/stderr,它只会检索关联的句柄,否则它会创建一个新的控制台屏幕缓冲区并使用该句柄。
所以我只是手动创建了 Win32::Console
包含 CreateFile 返回的控制台句柄的对象。
现在perl myscript.pl > nul 2> nul < nul
会写blah blah
在紧邻命令行下方的屏幕上。
如果有人提出更好的答案,我会接受。
关于perl - 当 stdin/stderr/stdout 在 Activestate Perl 中重定向时写入控制台,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14842131/