开发者

Perl's TieRegistry and Windows Server 2008 R2

We have a Perl program that ran well on all Windows platforms so far.

When we tried it on the newly released Windows Server 2008 R2, it stopped working. Investigation revealed that the problem is that calls to read registry values using TieRegistry开发者_如何学JAVA returned undefined values.

Is this a known problem? Did anyone run into a problem accessing the registry on Windows Server 2008 R2 using TieRegistry? I'm running the program as administrator, so I don't think it is permission problems. The program works great and read the registry correctly on Windows 7 and Vista.

A sample script I wrote to access the registry also fail:

use Win32::TieRegistry(Delimiter=>'\\');
my $reg = "HKEY_LOCAL_MACHINE\\SOFTWARE\\TEST\\Value1";
my $val = $Registry->{$reg};
print "val: ".$val."\n";

Any help would be appreciated.

Thanks, splintor


Since google likes to come up with this when people are looking for the solution I figured I'd drop a little note.

You do not have to modify TieRegistry.pm to get this to work. All you have to do is add the "Access" parameter to the call. here is an example:

my $rk = Win32::TieRegistry->new('LMachine\Software\Microsoft\Microsoft SQL Server\Instance Names\SQL', {Access=> 0x20019|0x0200});

There are two flags above ORd together:

0x20019  -- Read access to keys
0x0200   -- Access the 64 bit version of registry (ignored on 32 bit systems)

You can also use 0x0100 to access the 32 bit redirect version of the registry (also ignored on 32 bit systems)

This way you don't have to modify the library AND a single program can access BOTH versions of the registry.


I found the source of my problem.

In order to make TieRegistry work well on 64-bit Windows, and access the correct registry hive, we used the solution suggested by Tony B. Okusanya (also quoted here). However, this solution adds both KEY_WOW64_64KEY and KEY_WOW64_32KEY to the access parameter, which is not logical – either you want to access the 64-bit registry and use KEY_WOW64_64KEY or you want the 32-bit registry and use KEY_WOW64_32KEY. Using both doesn’t really make any sense.

Nevertheless, in previous versions of Windows, as well as Windows 7, it seems that when RegOpenKeyEx notices that the KEY_WOW64_64KEY flag is set in the access parameter, it uses the 64-bit registry, and ignores the KEY_WOW64_32KEY flag. Windows Server 2008 R2, on the other hand, doesn’t ignore the KEY_WOW64_32KEY flag, and if both flags are set, opening the registry key fail, and Win32API::Registry.regLastError returns the error The parameter is incorrect.

Removing |KEY_WOW64_32KEY from our changed TieRegistry.pm solved the problem and caused our application to work again.

Regards,

splintor


This my first time posting here. Here was the solution I came up with and an example of its use:

use Win32::TieRegistry( Delimiter=>"#", ArrayValues=>0 );
my $pound              = $Registry->Delimiter("/");
my $fileSep            = "\\"; 
my $path               = "";
my $PerlBin            = "";
my $PerlInstallDir     = "";
my $PerlInstallDrive   = "";
my $SybaseInstallDir   = "";
my $SybaseInstallDrive = "";


# Standard syntax for access to 32-bit registry
my $regKey = $Registry->{"HKEY_LOCAL_MACHINE/SOFTWARE/Perl"};   
print "\n\n\n" . "Accessing 32 bit registry for Perl Info:" ."\n\n\n";
foreach $key (keys %$regKey){
    print"$key: " . $regKey->{"$key"} . "\n";
}

$path = $regKey->{"/"};
$PerlInstallDir = Win32::GetShortPathName($path);
$path = $regKey->{"/BinDir"};
$PerlBin = Win32::GetShortPathName($path);
$PerlInstallDrive  = substr($PerlInstallDir, 0, 2) . $fileSep;

print "\n\n\n" . "Accessing 64 bit registry for Sybase Info:" ."\n\n\n";

 # This syntax passes the HEX flag to access the 64 bit registry
$regKey = $Registry->Open("HKEY_LOCAL_MACHINE/SOFTWARE/SYBASE/Setup", {Access=> 0x20019|0x0100});
foreach $key (keys %$regKey){
    print"$key: " . $regKey->{"$key"} . "\n";
}
$path = $regKey->{"/SYBASE"};
$SybaseInstallDir = Win32::GetShortPathName($path);
$SybaseInstallDrive = substr($SybaseInstallDir, 0, 2) . $fileSep;


print "\n\n\nFinished retrieving registry info:" . "\n";
print "Perl executable Location  == $PerlBin" . "\n";
print "Perl Install Drive        == $PerlInstallDrive" . "\n";
print "Perl Install Directory    == $PerlInstallDir" . "\n";
print "Sybase Install Drive      == $SybaseInstallDrive" . "\n";
print "Sybase Install Directory  == $SybaseInstallDir" . "\n";


This works for me

use Win32::TieRegistry (
ArrayValues => 0,
SplitMultis => 1, AllowLoad => 1,
 qw(:KEY_), Delimiter => '/', FixSzNulls => 1
);

use constant KEY_WOW => (uc($ENV{PROCESSOR_ARCHITECTURE}) eq "AMD64" || uc($ENV{PROCESSOR_ARCHITEW6432}) eq "AMD64") ? 0x100 : 0x200;

$Registry->Open('LMachine/Software/Microsoft/',{Access => KEY_READ | KEY_WOW});
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜