Monday, August 22, 2011

On Guilty Perl/Win32 Pleasures

I've been messing with PerlApp-packaged gui Perl apps for a while and I was annoyed that stderr output (useful when debugging) was not available when having the exe type set to Win32.

I have just remembered about an obscure W*ndows feature: debug messages (a lame-arse feature cloning syslogd(8) and only available in a debugger). So I set myself to use this having fond a debug message viewer

The question was how to log to stderr when running as a console app (under perl.exe) and to the debug message subsystem if running as a non-console app (unde wperl.exe)?

I found no direct answer but kernel32!GetConsoleTitle can be used in an indirect way to answer this question:
#!perl -w
use strict;
use Win32::API;
use File::Basename qw(basename);
my $myself = basename($0);
Win32::API->Import("kernel32", 'OutputDebugStringA', 'P', 'V');
Win32::API->Import("kernel32", 'GetConsoleTitle', 'PN', 'I');
sub DbgPrint
OutputDebugStringA("$myself\[$$\]: ".join('' => @_)."\r\n");
sub isConsole()
my $title = 'x' x 128;
my $r = GetConsoleTitle($title, 128);
return if $r == 0;
return if $title =~ /^x+x$/;
return 1;
sub Log
not @_ and return;
return print(STDERR @_, "\n") if isConsole();
return DbgPrint(@_);
main::Log "Testing";
I must say that Dave Roth's book Win32 Perl Scripting: The Administrator's Handbook was an eye opener to all sorts of deliciously perverse Perl/Win32 programming tidbits.


P.S. Why not use the Event Log subsystem? Because is sucks even more than the debug messages subsystem! and because I like obscure features and because the debug messages are not on-disk persistent.