2013-02-12 3 views
2

I 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 콘솔에 대한 핸들을 얻으려면 어떻게해야합니까? 사용자가 어떤 방향 전환을 수행하든 문제가되지 않도록하려면 어떻게해야합니까?

내가 원하는 효과는 배시 내장형 time 명령과 비슷한 방식으로 리다이렉션과 관계없이 일반 프로그램 출력 바로 다음에 콘솔에 메시지를 쓸 수있게하려는 것입니다. 본질적으로 Unix에서 열기 및 쓰기와 비슷합니다. /dev/tty.

나는 $console->Display()에 이어 새로운 콘솔을 할당하기 위해 my $console = new Win32::Console()을 시도했지만 이것은 완전히 잘못된 것입니다.

+0

일반적으로 **는 ** 2> blubb라고 말하는 것은 좋은 이유입니다. 나는 그들이 침묵을 지키라고 말할 때 프로그램이주의를 요구할 때 그것을 싫어한다. – Ingo

+0

@Ingo : 공정한 내용이지만 필자가 직접 작성한 프로그램의 요구 사항을 수정하지는 않습니다. :-) –

+0

당신은 내 하루를 만들었습니다! 당신은 뜻밖의 실수로 2> NUL을 입력하면됩니다. – Ingo

답변

3

이 질문을 한 후, 나는 조금 더 깊이 탐구하고 더러운 해킹 사용하여 해결할 수 있었다 : 나는 Win32::Console 내부의 new() 기능에 대한 코드 바라 보았다

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'; 

을하고 그냥 만들어 보았다 콘솔에 대한 핸들을 포함하는 해시. 매개 변수가 stdin/stdout/stderr을 지정하면 관련 핸들을 검색하고 그렇지 않으면 새 콘솔 화면 버퍼를 만들고 그 핸들을 사용합니다.

그래서 나는 수동으로 CreateFile에 의해 반환 된 콘솔 핸들을 포함하는 Win32::Console 개체를 만들었습니다.

이제 perl myscript.pl > nul 2> nul < nul은 명령 줄 바로 아래의 화면에 blah blah이라고 작성합니다.

누군가가 생각 나면 더 나은 대답을 받아 들일 것입니다.

0

AllocConsole() 문서 (C++ 문서 있지만 개념은 동일하다)에 따르면

"A 프로세스는 하나의 콘솔과 연관되므로 발신 프로세스가 이미 콘솔을 가지면 AllocConsole 함수가 실패 할 수있다. 프로세스는 FreeConsole 함수를 사용하여 현재 콘솔에서 자신을 분리 한 다음 AllocConsole을 호출하여 새로운 콘솔을 만들거나 AttachConsole을 호출하여 다른 콘솔에 연결할 수 있습니다.

콘솔이 이미 리디렉션되었으므로 아무 것도 할 수없는 것처럼 보입니다. 콘솔을 분리하고 새 콘솔을 할당하더라도 새 콘솔은 재 지정을 상속합니다. C++에서 SetStdHandle() API를 사용하여 표준 핸들이 다른 파일이나 장치를 가리 키도록 강요하지만 그와 동등한 Perl은 찾을 수 없습니다.

+0

표준 핸들을 리디렉션해도 콘솔이 해제되지 않습니다. 'CreateFile ('conout $')'는 할당 된 콘솔에 대한 핸들을 가져 오지만 Perl의 Win32 :: Console 모듈에서 직접 사용하는 방법은 없습니다. –

+0

리다이렉트가 콘솔을 자유롭게 할 것이라고 말한 곳을 보지 못했습니다 ... 어떤 경우에도 그것을 바꿀 수있는 직접적인 방법이 없다는 것에 대한 여러분의 의견은 저의 요점이었습니다. 또한 Conout $에서 CreateFile을 사용하여 리디렉션 된 출력을 처리 할 수도 있습니다. – HerrJoebob