我该如何让32位Perl读取64位Windows注册表?

6
我有一个32位的Perl安装程序,需要使用它来安装和卸载32位和64位应用程序。
安装32位和64位应用程序都没有问题。卸载32位也没问题。
然而,在卸载64位应用程序时,我遇到了问题。
该应用程序只知道在控制面板中“添加删除程序”中看到的应用程序名称。例如,“Winzip 14.0”是Winzip的显示名称。
我使用以下方法进行卸载:遍历HKLM/Software/Microsoft/Windows/CurrentVersion/Uninstall,并解析那里存在的键,以查看是否匹配Winzip。如果匹配,则从那里获取卸载字符串。
    my $register = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall";
    $HKEY_LOCAL_MACHINE->Open($register,$hKey)|| die $!;
    #Then parse all the nodes and fetch the uninstall string

如果应用程序是64位安装,则卸载信息将驻留在HKLM/Software/Microsoft/Windows/CurrentVersion/Uninstall中。
然而,上述Perl安装程序代码试图从HKLM/Software/WOW6432Node/Microsoft/Windows/CurrentVersion/Uninstall读取,并且在那里找不到安装信息。
那么,我该如何让运行在32位进程中的Perl代码读取在64位hive中发现的注册表值?我知道RegOpenKey() API需要KEY_WOW64_64KEY参数,但由于它是Windows API,我不知道这是否有帮助。即使这样,还有其他替代方法吗?

3个回答

2

正如你在问题中提到的那样,可以使用KEY_WOW64_64KEY标志指定64位或32位注册表视图。

旧的Win32API :: Registry可以使用KEY_WOW64_64KEY指定64位注册表,但现在最好使用TieRegistry的对象函数,它包装了功能,使其更易于与注册表一起使用:

#!/usr/bin/perl -w
use strict;
use Win32::TieRegistry (Delimiter => '/');

print "registry 64-bit:\n";
my $mykey = new Win32::TieRegistry
  'HKEY_LOCAL_MACHINE/Software/Microsoft/Windows/CurrentVersion/Uninstall',
  { Access=>Win32::TieRegistry::KEY_READ()|0x0100, Delimiter=>'/' };

print "\tValues are:\n";
print join("\n\t\t", $mykey->ValueNames);
print "\n";

#Getting a specific value's value
#$mykeyval = $mykey->GetValue('Path');

print "\tFiltered subkeys are:\n\t\t";
print join("\n\t\t", grep(!/\{[-A-Fa-f0-9]+\}/, $mykey->SubKeyNames));
print "\n";

print "registry 32-bit explicit:\n";
$mykey = new Win32::TieRegistry
  'HKEY_LOCAL_MACHINE/Software/Microsoft/Windows/CurrentVersion/Uninstall',
  { Access=>Win32::TieRegistry::KEY_READ()|0x0200, Delimiter=>'/' };

print "\tValues are:\n\t\t";
print join("\n\t\t", $mykey->ValueNames);
print "\n";

#Getting a specific value's value
#$mykeyval = $mykey->GetValue('Path');

print "\tFiltered subkeys are:\n\t\t";
print join("\n\t\t", grep(!/\{[-A-Fa-f0-9]+\}/, $mykey->SubKeyNames));
print "\n";

这将为32位和64位密钥产生预期的结果,并且在32位和64位Perl中应该以相同的方式工作(理论上)。
注意:我需要在我的Perl版本中指定KEY_READ()函数的完整命名空间以防止编译错误,并且我不确定是否有0x0100和0x0200常量的命名值,因此可能会更美观。但它有效!
< p > (改编自我的问题解决方案:无法读取注册表, 在我意识到我的问题与64位和32位有关之前提出的)。


2

您也可以直接调用reg工具,而不是批处理文件:

$WINDIR/system32/reg.exe

这是操作系统默认包含的reg.exe文件的位置。
$WINDIR/sysnative/reg.exe

当从32位进程执行时,这是本机64位reg.exe的虚拟位置。


您可以通过传递/reg:64/reg:32开关到reg.exe,避免明确指定32位或64位reg.exe的路径:https://support.microsoft.com/en-us/kb/948698。然后,您只需要关心键的类型(您可能应该知道),而不是还要关注安装的Perl的类型(您可能不需要关心)。 - Ben

2

是的,您必须使用KEY_WOW64_64KEY,对于32位进程没有其他解决方法。从Perl直接调用Win32 API似乎是可能的,根据这个网页


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接