0

I am trying to write a post installer for a Perl build on Windows. The Perl is self-compiled; no Strawberry, but I cribbed much of the code from update.pl.bat in the Strawberry 5.12 release. It uses Win32::TieRegistry to get the current Path value, add in the new directories and then write it back. My problem is that even though the registry is updated, subsequent processes don't see the update unless I reboot OR I go into Control Panel/System/Advanced System Settings/Environment Variables, select the Edit button on the PATH variable and then select OK all the way out (no actual edit required). Here is a small repro:

@rem = '--*-Perl-*--
@echo on
set d0=%0
echo %*
shift
echo %*
shift
echo %*
%cd%\bin\perl -x -S %d0% %*
goto endofperl
@rem ';
#!perl

## Taken from strawberry release 5.12
use 5.010;
use strict;
use warnings;
use Win32::TieRegistry qw(:KEY_);
use File::Basename;
my $directory = dirname($^X); ## on Windows, we can cheat - this is always full path.
$directory =~ s|\\bin\\per||;
## Make sure we're Windows-y
$directory =~ s{/}{\\}g;
# Get the appropriate environment entries.
my $env = Win32::TieRegistry->new(
                                  'HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Control/Session Manager/Environment',
                                  {
                                   Access => KEY_READ() | KEY_WRITE() | 256,
                                   Delimiter => '/',
                                  }
                                 ); # returns undef if SYSTEM ENV not writable
my $oldpath = $env->GetValue('Path');
my $new_path = "$directory;$oldpath";
$env->SetValue('Path', $new_path);

### UPDATE: This code was ADDED on 2013/12/29, after the question was marked as a dup
### and should be the solution to the issue, untested at this time:

#gonna send WM_SETTINGCHANGE broadcast - to avoid the need for logout/login
my $HWND_BROADCAST   = 0xFFFF;
my $WM_SETTINGCHANGE = 0x001A;
my $SMTO_ABORTIFHUNG = 0x0002;
my $null = pack('xxxxxxxx'); # 8 x zero byte

my $SendMessageTimeout = Win32::API->new("user32", "SendMessageTimeout", 'NNNPNNP', 'N') or die "Can't import SendMessageTimeout: $!\n";  
$SendMessageTimeout->Call($HWND_BROADCAST,$WM_SETTINGCHANGE,0,'Environment',$SMTO_ABORTIFHUNG,5000,$null);

### UPDATE: END
__END__
:endofperl

After this program runs, I start up a new command box. The added values do not appear in the path. If I open the Environment Variable dialog box and look at the path, the values are there. I hit ok on the dialog box without even editing anything and the next command window sees the values.

What is it that the environment dialog is doing that my Perl program is not?

mpersico
  • 766
  • 7
  • 19
  • See [this perl script](http://svn.ali.as/cpan/trunk/Perl-Dist-Strawberry/share/extra-files/update_env.pl.bat) - it implements exactly what you need – kmx Dec 13 '13 at 16:15
  • Registry access from your perl interpreter is probably being redirected to another location. There are two main reasons: 32-bit script interpreter on a 64-bit system, or insufficient permissions – Ben Voigt Dec 29 '13 at 01:45
  • Ah! Thank you @kmx. My script was a reduction of the Strawberry Perl script from version 5.12. It appears your example is the same script, but of a later vintage because it includes the BROADCAST code needed to avoid having to login/logout. For those keeping score at home, you're looking for the code [here](http://svn.ali.as/cpan/trunk/Perl-Dist-Strawberry/share/extra-files/update_env.pl.bat) – mpersico Dec 29 '13 at 01:52

0 Answers0