在 Perl 中从 Windows 注册表中读取 [英] Reading from Windows registry in Perl

查看:174
本文介绍了在 Perl 中从 Windows 注册表中读取的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm trying to get the installation location of a program without checking a series of hard-coded paths, hoping to get it 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.

我已经阅读了 使用 Perl 解析 Windows 注册表,并且我想我已经将所有答案都包含在我的脚本,但是当我尝试读取注册表值时总是得到空结果,即使从提升的命令提示符运行以确保脚本具有管理员权限.

I've read about Parsing windows registry using Perl, and I think I've incorporated all of the answers in my script, but I always get an empty result when I try reading a registry value, even when running from an elevated command-prompt to make sure the script has admin rights.

我第一次尝试使用 Win32::TieRegistry,并且如前所述返回的值为空,所以我尝试只使用 reg 查询,但这给出了一个关于密钥不存在的错误成立.在 Perl 之外运行相同的 reg query 命令成功读取密钥.我做错了什么?

I first tried using Win32::TieRegistry, and as mentioned the returned value is empty, so then I tried just shelling out and using reg query, but that gives an error about the key not being found. Running the same reg query command outside of Perl successfully reads the key. What am I doing wrong?

更新:根本原因(在我收到的几个答案中指出)试图从 32 位 Perl 访问 64 位注册表视图;默认情况下,Windows 中的任何 32 位应用程序在尝试访问 HKLM\Software 键时都被重定向到 HKLM\Software\WOW6432Node,所以我需要找到一种方法来避免因为我感兴趣的密钥在那个位置不存在.

Update: The root cause (pointed out in the couple answers I received) was trying to access a 64-bit registry view from a 32-bit Perl; by default, any 32-bit application in Windows is redirected to HKLM\Software\WOW6432Node when trying to access HKLM\Software keys, so I needed to find a way to avoid that since my key of interest does not exist in that location.

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 命令:

Manual reg query command outside of 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, all this is running from an elevated command prompt for now; once it works there I was going to experiment with whether it is necessary.

推荐答案

正如 Srgrn 的回答中提到的,问题源于我的 Perl 是 32 位的,在 64 位系统上运行.Windows 会在访问 HKLM\Software 时自动将 32 位进程重定向到 Wow6432Node 注册表节点,除非特别告知 使用带有访问模式标志的 64 位或 32 位注册表视图.

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

我可以使用旧的 Win32API::Registry 指定访问权限,但我选择了使用 TieRegistry 的对象函数指定访问模式:

I could specify access with the old Win32API::Registry, but instead I chose to specify the access mode with 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 中应该以相同的方式工作(理论上无论如何).

This gives results as expected for both the 32-bit and 64-bit keys, and additionally should work the same way in both 32-bit and 64-bit Perl (in theory anyway).

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

Note: I needed to specify the full namespace for the KEY_READ() function in my version of Perl to prevent compile errors, and I'm not certain whether there are named values for the 0x0100 and 0x0200 constants, so this may be rougher than needed on some systems, but it seems to work great for me!

注意:这还允许您读取 32 位和64 位,所以这个答案在那里重复.

Note: this also allows you to read the right version of a key with the same name in either 32-bit and 64-bit, so this answer is duplicated there.

这篇关于在 Perl 中从 Windows 注册表中读取的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆