如何使32位Perl读取64位Windowsregistry?

我有一个32位的Perl安装程序。 使用这个我需要能够安装和卸载32位和64位应用程序。

安装32位和64位是好的。 卸载32位也是好的。

但是,卸载64位应用程序时遇到问题。

应用程序只知道应用程序的名称,如控制面板中的“添加删除程序”所示。 例如,它可以是Winzip的显示名称“Winzip 14.0”。

我使用以下方法进行卸载:我遍历到HKLM/Software/Microsoft/Windows/CurrentVersion/Uninstall并parsing当前存在的密钥,以查看Winzip是否匹配。 如果是的话,我从那里得到卸载string。

  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
并没有在那里find安装。

那么如何让在32位进程中运行的Perl代码读取64位configuration单元中的registry值呢? 我知道使用KEY_WOW64_64KEY参数的RegOpenKey() API。 但由于它是一个Windows API,我不知道这是否会有所帮助。 即使如此,还有其他的select吗?

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

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

 $WINDIR/system32/reg.exe 

这是操作系统附带的reg.exe的默认位置。

 $WINDIR/sysnative/reg.exe 

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

正如你在你的问题中注意到的,可以用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常量是否有命名值,所以这可能是漂亮。 但它的作品!


(从我的解决方案适应我的问题,关于不能够读取注册表 ,询问之前,我知道我的问题是有关的64位与32位)。