Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

My Perl GUI app needs to open an url in default web browser.

Doing

system("start $url");
does this, but a console window flashes for a moment (it flashes only for "windows-type" apps - i.e. scripts executed with wperl.exe, not with perl.exe).

Is there any win32-specific code to do this? The builtin "start" command does it somehow - which registry keys it might be inspecting?

Thank you in advance for your answers!

Replies are listed 'Best First'.
Re: How to start default browser on Windows?
by jasonk (Parson) on Aug 11, 2005 at 13:59 UTC

    No registry hacking needed... From the output of 'start /?':

    B Start application without creating a new window.

    So all you have to do is pass system("start /b http:.....");


    We're not surrounded, we're in a target-rich environment!
      So all you have to do is pass system("start /b http:.....");
      If the perl process is not running in a console window, then this won't work. A console window will be opened to run the shell for system(). This is before the actual command is parsed.

      A perl process can be started without a console window (on MSWindows), by, for example, double-clicking a .WPL file.

Re: How to start default browser on Windows?
by Thelonius (Priest) on Aug 11, 2005 at 14:59 UTC
    #!perl -w use Win32 qw(SW_SHOWNORMAL); use Win32::API; use strict; my $shellexec = Win32::API->new('shell32', 'ShellExecute', 'NPPPPI', 'N') or die "cannot import ShellExecute: $!\n"; my $result = $shellexec->Call(0, "open", "http://perlmonks.org/", "", ".", SW_SHOWNORMAL); if ($result < 33) { print STDERR Win32::FormatMessage($result), "\n"; exit(1); }
Re: How to start default browser on Windows?
by bunnyman (Hermit) on Aug 11, 2005 at 14:52 UTC

    The right way to do it is to go through the Windows Shell. This will ensure you get the default browser without having to do any poking around in the registry.

    	use Win32::FileOp qw(ShellExecute);
    	ShellExecute('http://...');
    

    (Note: Untested. Win32::FileOp is on CPAN.)

      This works perfectly in ActiveState 5.8.7.
Re: How to start default browser on Windows?
by puploki (Hermit) on Aug 11, 2005 at 13:26 UTC
    I seem to remember windows' start command is a console app, so if you're running in a GUI it has to spawn a console to run start. start itself then spawns an external program and quits, hence the flash of a console window.

    If you can always be sure that the browser will be IE, then you can use:

    system( "iexplore.exe http://myurl.com" );

    Failing that, you should be able to lookup in the registry the default association of .html files. I think it's this:

    [HKEY_CLASSES_ROOT\htmlfile\shell\open\command]

    Otherwise, have a play with Regmon and see what keys are being queried when the default browser is started. You can then query the same keys in Perl and invoke that browser directly.

    Update: Ah, jasonk has a much more simpler solution. But it's much more fun to have an purely Perl approach ;)

Re: How to start default browser on Windows?
by salva (Canon) on Aug 11, 2005 at 14:05 UTC
    Which GUI framework are you using?, some of them provide a way to launch external programs. For instance, PerlTray provides an Execute sub that can be called as
    Execute 'http://foo.com/'; Execute 'mailto:me@foo.com'; ...
Re: How to start default browser on Windows?
by jch341277 (Sexton) on Aug 11, 2005 at 14:00 UTC

    you're almost there: system("start http://$url") should do it...

Re: How to start default browser on Windows?
by chester (Hermit) on Aug 11, 2005 at 13:14 UTC
    I've used Win32::Process with some fairly good results. It gives you a lot of control over spawning new processes.

    Update: Ah, default browser. This may not be too helpful, then.

Re: How to start default browser on Windows?
by Anonymous Monk on Aug 12, 2005 at 23:20 UTC
    Here's the code I'm using (from a Perl/Tk app); it seems to handle all of (Firefox, IE, Mozilla):
    sub open_browser {
    	my ($obj, $url) = @_;
    #
    # open the registry to find the path to the default browser
    #
    	my $cmdkey = $reg{ 'HKEY_CLASSES_ROOT/' . 
    		$reg{'HKEY_CLASSES_ROOT/.htm//'} . 
    			'/shell/open/command'};
    
    	my $sysstr = $cmdkey->{'/'};
    #
    # replace the argument PH with our URL
    #
    	$url=~tr/\\/\//;
    	$url = "file://C:$url"
    		unless ($url=~/^(http|file):\/\//);
    
    	$sysstr=~s/\-nohome//;
    	
    	if ($sysstr=~/%1/) {
    		$sysstr =~ s!%1!$url!;
    	}
    	else {
    		$sysstr .= " $url";
    	}
    	my $exe = $sysstr;
    #
    #	in case we get a fancy pathname, strip the
    #	quotes
    #
    	if ($sysstr=~/^"/) {
    		$exe=~s/^"(^"+)"\s+.+$/$1/;
    	}
    	else {
    		$exe=~s/^(\S+)\s+.+$/$1/;
    	}
    
    # start the browser...
    	my $browser;
    	Win32::Process::Create($browser,
           $exe,
           $sysstr,
           0,
           NORMAL_PRIORITY_CLASS,
           '.'
           ) or die Win32::FormatMessage(Win32::GetLastError());
    
    	return 1;
    }