2015-05-15 97 views
2

我试图在没有检查一系列硬编码路径的情况下获取程序的安装位置,希望从存储在Windows注册表中的路径中获取它,但是我得到空的返回值或者当我尝试读取所需的键值时出现错误消息。从Perl注册表中读取Perl

我已阅读Parsing windows registry using Perl,我想我已经将所有答案都包含在脚本中,但是当我尝试读取注册表值时,即使从提升的命令提示符运行时,我也会得到空的结果以确保脚本具有管理权限。

我第一次尝试使用Win32 :: TieRegistry,并提到返回的值是空的,所以然后我试图只是脱壳并使用reg query,但这给出了一个关于找不到密钥的错误。在Perl外部运行相同的reg query命令可成功读取密钥。我究竟做错了什么?


更新:的根本原因(在我收到的夫妇的答案指出)试图access a 64-bit registry view from a 32-bit Perl;默认情况下,Windows中的任何32位应用程序在尝试访问HKLM\Software密钥时都被重定向到HKLM\Software\WOW6432Node,所以我需要找到一种方法来避免这种情况,因为我的感兴趣的密钥在该位置不存在。


Perl脚本:

#!/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"; 

输出:

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= 

的Perl以外手册reg query命令:

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 

请注意,所有这些都是从提升的命令提示符开始运行;一旦它在那里工作,我将试验是否有必要。

+0

应该是'LMachine',而不是'HKEY_LOCAL_MACHINE'。 – ikegami

+0

获取子键(与值相对)时应该有一个尾随的'/' – ikegami

+1

失败的注册表提取后'$^E'中的错误消息。 – ikegami

回答

2

如Srgrn的回答提到一种方式来获得从32位的Perl 64位密钥,则问题源于我的Perl是32位的,运行在64位系统上。除非明确告知use 64-bit or 32-bit registry views with an access mode flag,否则Windows在访问HKLM\Software时会自动将32位进程重定向到Wow6432Node注册表节点。

我可以specify access with the old Win32API::Registry,而是我选择了指定与TieRegistry's object 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"; 

此给出的结果如预期的在32位和64位密钥,另外还应该工作一样方式在32位和64位Perl(理论上无论如何)。

注:我需要在我的Perl版本中为KEY_READ()函数指定完整的命名空间以防止编译错误,并且我不确定0x0100和0x0200常量是否有命名值,所以这可能会在某些系统上比需要更粗糙,但它似乎对我很好!


注:这也可以让你read the right version of a key with the same name in either 32-bit and 64-bit,所以这个答案是重复出现。

2

您使用的是64位操作系统和32位的Perl 这意味着从perl的运行时,你实际上在WOW6432Node和值不是你想要

你需要使用一个64位的Perl的关键。

例如,从我自己的机器

λ 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\ 

其中 “HKEY_LOCAL_MACHINE \ SOFTWARE \ VMware公司\ VMware的USB” 是WOW6432Node和司机都没有。

这会影响从perl和模块运行的命令。

[编辑为完整起见] apperantly有如图所示在讨论的底部在http://www.perlmonks.org/?node_id=1007098

+0

呃,不是这个问题了。我敢打赌,这是我的问题。有没有办法从Perl访问64位视图,或者我应该使用外部'reg query'命令和'/ reg:64'开关? – Ben

+0

我其实不知道该模块足以说明,我敢肯定这是一种方式 – Srgrn

+0

我发现以下内容:http://www.perlmonks.org/?node_id=1007098 – Srgrn