package Tk::Wizard::Installer::Win32; =head1 NAME Tk::Wizard::Installer::Win32 - Win32-specific routines for Tk::Wizard::Installer =cut use strict; use warnings; use lib "../../../"; # dev use Carp; use Cwd; use Data::Dumper; # for debugging only use File::Path; use Exporter; use Tk::Wizard ':use' => 'FileSystem'; use base 'Tk::Wizard::Installer'; use vars '@EXPORT'; @EXPORT = ("MainLoop"); our $VERSION = do { my @r = ( q$Revision: 2.18 $ =~ /\d+/g ); sprintf "%d." . "%03d" x $#r, @r }; use constant DEBUG_FRAME => 0; # use Log4perl if we have it, otherwise stub: # See Log::Log4perl::FAQ BEGIN { eval { require Log::Log4perl; }; if($@) { no strict qw"refs"; *{__PACKAGE__."::$_"} = sub { } for qw(TRACE DEBUG INFO WARN ERROR FATAL); } else { no warnings; no strict qw"refs"; require Log::Log4perl::Level; Log::Log4perl::Level->import(__PACKAGE__); Log::Log4perl->import(":easy"); # It took four CPAN uploads and tests to workout why # one user was getting syntax errors for TRACE: must # be the Mithrasmas spirit (hic): if ($Log::Log4perl::VERSION < 1.11){ *{__PACKAGE__."::TRACE"} = *DEBUG; } } use Win32::Shortcut; require Win32; if ( $Win32::VERSION lt 0.2 ) { eval 'use Win32::OLE'; # autouse is still not very good? die "Could not load Win32::OLE: $@" if $@; } eval { use Win32; use Win32::TieRegistry( Delimiter => "/", ArrayValues => 0 ); }; die $@ if $@; } =head1 DESCRIPTION As a sub-class of L and L, this module offers all of those methods and means, plus the below, which are thought to be specific to the Microsoft Windows platform. If you are looking for a freeware software installer that is not dependant upon Perl, try Inno Setup - C. It's so good, even Microsoft have been caught using it. If you are looking for a means to update the Windows C variable, have a look for I, a tiny Windows 32-bit executable by Luke Bailey (C). This tool can also be used to add new, persistant environment variables to the system. =head1 METHODS =head2 register_with_windows Registers an application with Windows so that it can be "uninstalled" using the I's I dialogue. An entry is created in the Windows' registry pointing to the uninstall script path. See C, below. Returns C on failure, C<1> on success. Does nothing on non-MSWin32 platforms Aguments are: =over 4 =item uninstall_key_name The name of the registery sub-key to be used. This is transparent to the end-user, but should be unique for all applications. =item UninstallString The command-line to execute to uninstall the script. According to Microsoft at L: "You must supply complete names for both the DisplayName and UninstallString values for your uninstall program to appear in the Add/Remove Programs utility. The path you supply to Uninstall-String must be the complete command line used to carry out your uninstall program. The command line you supply should carry out the uninstall program directly rather than from a batch file or subprocess." The default value is: perl -e '$args->{app_path} -u' This default assumes you have set the argument C, and that it checks and reacts to the the command line switch C<-u>: package MyInstaller; use strict; use Tk::Wizard; if ($ARGV[0] =~ /^-*u$/i){ # ... Have been passed the uninstall switch: uninstall myself now ... } Or something like that. =item QuietUninstallString As C above, but for ... quiet uninstalls. =item app_path Please see the entry for C, above. =item DisplayName =item DisplayVersion =item Size The strings displayed in the Control Panel's Add/Remove Programs list. =item ModifyPath =item NoRepair NoModify NoRemove =item EstimatedSize InstallSorce InstallDate InstallLocation =item AthorizedCDFPrefix Language ProductID Unknown =item Comments =item RegOwner =item RegCompnay =item Contact =item HelpTelephone =item Publisher =item URLUpdateInfo =item URLInfoAbout =item HelpLink These are all displayed when the Support Information link is clicked in the Add/Remove Programs dialogue. The last should be full URIs. =back The routine will also try to add any other parameters to the registry tree in the current location: YMMV. =cut sub register_with_windows { my ( $self, $args ) = ( shift, {@_} ); return 1 if $^O !~ /mswin32/i; unless ($args->{DisplayName} and $args->{UninstallString} and ( $args->{uninstall_key_name} or $args->{app_path} ) ) { die __PACKAGE__ . "::register_with_windows requires an argument of name/value pairs which must include the keys 'UninstallString', 'uninstall_key_name' and 'DisplayName'"; } if ( not $args->{UninstallString} and not $args->{app_path} ) { die __PACKAGE__ . "::register_with_windows requires either argument 'app_path' or 'UninstallString' be set."; } if ( $args->{app_path} ) { $args->{app_path} = "perl -e '$args->{app_path} -u'"; } my $uninst_key_ref = $Registry->{'LMachine/SOFTWARE/Microsoft/Windows/CurrentVersion/Uninstall/'} ->CreateKey( $args->{uninstall_key_name} ); die "Perl Win32::TieRegistry error" if !$uninst_key_ref; foreach ( keys %$args ) { next if $_ =~ /^(app_path|uninstall_key_name)$/g; $uninst_key_ref->{"/$_"} = $args->{$_}; } return 1; } =head2 addStartMenuPage Adds a page that allows users to select a location on the Windows "Start Menu", perhaps to add a shortcut there. This routine does not currently create the directory in the I, nor does it place a link there - see L for that. Rather, the caller supplies a C<-variable> parameter that is a reference to a scalar which, once the page is 'run', will contain either the path to the user's chosen directory, or C if the option to not select was chosen. In addition, when the page is 'run', it places the path to the current user's I directory into the object field C, and the path to the common I in the object field C. The physical creation of the shortcut is left as an exercise to the reader. Have a look at the C<$mkdir> C