GUI scripts

version 2.1

The standard perl.exe is a console based application, this is the right thing usually, but sometimes it might be tedious.

Imagine you have a Tk or Win32::GUI based script, you start it by a doubleclick on an icon and an ugly empty useless console appears and stays on screen until you close the script. Not a nice thing huh?

There are several solutions.

Hiding the console

You may hide the console as soon as the script starts.

use Win32::GUI; BEGIN {Win32::GUI::Hide(scalar(Win32::GUI::GetPerlWindow()))};

There are three problems with this solution.

The first is that the console flashes on screen when you start the program. Even if you use BEGIN{} to hide it as soon as possible.

Second, if you run such a script from a console, it will hide the console instead of detaching itself and leaving the console visible and ready to take other commands.

Now let's think about what to do when the script ends. If it keeps the console hidden and it was started by a doubleclick on an icon everything is cool, but if it was started from a command prompt, the prompt is still running, but it's invisible. This way, you'd run out of memory.

If you on the other hand show the console, it may flash on screen.

Solutions

For some time I advertised a way to prepare a perl.exe that doesn't create a console. This is no longer needed if you use ActivePerl. The distribution contains wperl.exe which is just that. If you compiled Perl yourself you may need to create such an executable yourself. It's easier than it may seem:

All you have to do is to copy your perl.exe to wperl.exe and run this :

c:\> EDITBIN.EXE /subsystem:windows wperl.exe

I'm using extension .gpl for the scripts that are to be run by wperl, but this is up to you.

Since the editbin.exe is part of Microsoft's development tools and AFAWK is not free, Jan wrote the following script that is able to do the same.

 Usage:
  exetype c:\perl\bin\guiperl.exe WINDOWS

I've tested this both under WinNT4.0 (sp4) and Win95sp1.

An updated version of the script is now installed with ActivePerl as c:\perl\bin\exetype.bat.

You may use it to ``de-consolize'' any EXEcutable of course ;-)

Script

This script was written by Jan Dubois <jand@ActiveState.com>. Thanks, Jan :-)

 ============================exetype.pl=============================
 #!perl
 use strict;
 unless (@ARGV == 2) {
     print "Usage: $0 exefile [CONSOLE|WINDOWS]\n";
     exit;
 }
 unless ($ARGV[1] =~ /^(console|windows)$/i) {
     print "Invalid subsystem $ARGV[1], please use CONSOLE or WINDOWS\n";
     exit;
 }
 my ($record,$magic,$offset,$size);
 open EXE, "+< $ARGV[0]" or die "Cannot open $ARGV[0]: $!";
 binmode EXE;
 read EXE, $record, 32*4;
 ($magic,$offset) = unpack "Sx58L", $record;
 die "Not an MSDOS executable file" unless $magic == 0x5a4d;
 seek EXE, $offset, 0;
 read EXE, $record, 24;
 ($magic,$size) = unpack "Lx16S", $record;
 die "PE header not found" unless $magic == 0x4550;
 die "Optional header not in NT32 format" unless $size == 224;
 seek EXE, $offset+24+68, 0;
 print EXE pack "S", uc($ARGV[1]) eq 'CONSOLE' ? 3 : 2;
 close EXE;

Automatic setup

I've written a script that creates the wperl.exe (if you do not have it already) and sets the file extension mapping for extensions you specify. You may find it at http://Jenda.Krynicky.cz/perl/makeGUIperl.pl.txt

You need Win32::Registry2 patch from my pages! http://Jenda.Krynicky.cz

Subprocesses

If your application doesn't have a console, your subprocesses should not have one either. It would look dirty if a console flicked on the screen every time you use system() or backticks. Since build 632 of ActivePerl you may use this

        BEGIN {
                Win32::SetChildShowWindow(0)
                        if defined &Win32::SetChildShowWindow
        };

to instruct Perl to hide the consoles of such processes.

Author

The text was written by Jan Krynicky <Jenda@Krynicky.cz> and is based on discussion on Perl-Win32-Users mailing list, the code is by Jan Dubois <jand@ActiveState.com>.