Reading from the Windows registry in Perl

I try to get the installation location of the program without checking a number of hard-coded paths, hoping to get them from the path stored in the Windows registry, but I get empty return values ​​or error messages when I try to read the required key values.

I read about Parsing windows registry using Perl , and I think I included all the answers in my script, but I always get an empty result when I try to read the registry value, even if you run from an elevated command prompt to make sure that the script has administrator rights.

At first I tried to use Win32 :: TieRegistry, and as mentioned, the return value is empty, so I tried just to bypass and use reg query , but this gives an error in that the key was not found. Running the same reg query command outside of Perl successfully reads the key. What am I doing wrong?


Update. The main reason (indicated in the pair's responses received) was trying to access the 64-bit registry representation from 32-bit Perl ; by default, any 32-bit Windows application is redirected to HKLM\Software\WOW6432Node when trying to access the HKLM\Software keys, so I need to find a way to avoid this, since my interesting key does not exist in this place.


Perl script:

 #!/usr/bin/perl -w use strict; use Data::Dumper; use Win32::TieRegistry (Delimiter => '/'); my $mykey = $Registry->{'HKEY_LOCAL_MACHINE/Software/ikv++ technologies ag/medini unite (x64)'}; my $mykeyval = $mykey->{'/Path'}; print " value=$mykeyval\n"; print Dumper $mykey; my $sysCmd =`reg query "HKLM\\Software\\ikv++ technologies ag\\medini unite (x64)" /v Path`; print " sysCmd=$sysCmd\n"; 

Output:

 C:\Users\username\AppData\Local\Temp>perl test_reg_read.pl Use of uninitialized value in concatenation (.) or string at test_reg_read.pl line 9. value= $VAR1 = {}; ERROR: The system was unable to find the specified registry key or value. sysCmd= 

reg query command outside Perl:

 C:\Users\username\AppData\Local\Temp>reg query "HKLM\Software\ikv++ technologies ag\medini unite (x64)" /v Path HKEY_LOCAL_MACHINE\Software\ikv++ technologies ag\medini unite (x64) Path REG_SZ C:\Program Files\ikv++ technologies ag\mediniUnite 

Note that all this is done from an elevated command prompt; as soon as he works there, I was going to experiment with necessity.

+2
windows perl registry
source share
2 answers

As mentioned in Srgrn's answer, the problem is that my Perl is 32-bit, running on a 64-bit system. Windows automatically redirects 32-bit processes to the Wow6432Node node registry when accessing HKLM\Software , unless specifically instructed to use 64-bit or 32-bit registry views with the access mode flag .

I could specify access with the old Win32API :: Registry , but instead I decided to specify access mode with the TieRegistry object's Functions :

 #!/usr/bin/perl -w use strict; use Win32::TieRegistry (Delimiter => '/'); print "explicitly access 64-bit location:\n"; my $mykey = new Win32::TieRegistry 'HKEY_LOCAL_MACHINE/Software/ikv++ technologies ag/medini unite (x64)', { Access=>Win32::TieRegistry::KEY_READ()|0x0100, Delimiter=>'/' }; my $mykeyval = $mykey->GetValue('Path'); print " value=$mykeyval\n"; print " Values are: "; print join(', ', $mykey->ValueNames); print "\n"; print "explicitly access 32-bit location:\n"; $mykey = new Win32::TieRegistry 'HKEY_LOCAL_MACHINE/Software/ikv++ technologies ag/medini unite', { Access=>Win32::TieRegistry::KEY_READ()|0x0200, Delimiter=>'/' }; $mykeyval = $mykey->GetValue('Path'); print " value=$mykeyval\n"; print " Values are: "; print join(', ', $mykey->ValueNames); print "\n"; 

This gives the expected results for both 32-bit and 64-bit keys, and should also work the same in both 32-bit and 64-bit Perl (theoretically, one way or another).

Note. I needed to specify the full namespace for the KEY_READ () function in my version of Perl to prevent compilation errors, and I'm not sure if there are named values ​​for the constants 0x0100 and 0x0200, so this may be coarser than necessary for some systems but it seems to work great for me!


Note. It also allows you to read the correct key version with the same name in either the 32-bit or 64-bit version , so this answer is duplicated.

+2
source share

you use 64-bit OS and 32-bit pearls, which means that when you start from perl, you actually get the values ​​in the WOW6432Node, and not behind the keys you want

you need to use 64 bit perl.

for example from my own car

 Ξ» c:\Strawberry\perl\bin\perl my $sysCmd = `reg query "HKLM\\SOFTWARE\\VMware, Inc.\\VMware Drivers" /v vmci.status`; print $sysCmd; ^D ERROR: The system was unable to find the specified registry key or value. Ξ» c:\Strawberry\perl\bin\perl my $sysCmd = `reg query "HKLM\\SOFTWARE\\VMware, Inc.\\VMware USB" /v InstallPath`; print $sysCmd; ^D HKEY_LOCAL_MACHINE\SOFTWARE\VMware, Inc.\VMware USB InstallPath REG_SZ C:\Program Files (x86)\Common Files\VMware\USB\ 

where "HKEY_LOCAL_MACHINE \ SOFTWARE \ VMware, Inc. \ VMware USB" is located in WOW6432Node, but there are no drivers.

this affects both the command executed with perl and the module.

[Edit for completeness] apperantly there is a way to get 64-bit keys from 32-bit perl, as shown at the bottom of the discussion at http://www.perlmonks.org/?node_id=1007098

+2
source share

All Articles