Как заставить 32-битный Perl читать 64-битный реестр Windows? - PullRequest
6 голосов
/ 21 января 2010

У меня есть 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
и он не находит там установку.

Итак, как мне заставить Perl-код, запущенный в 32-битном процессе, прочитать значение реестра, найденное в 64-битном кусте? Мне известно о RegOpenKey() API, который принимает параметр KEY_WOW64_64KEY. Но так как это Windows API, я не знаю, поможет ли это. Даже тогда, есть ли другая альтернатива?

Ответы [ 3 ]

2 голосов
/ 23 марта 2010

Вы также можете вызвать инструмент reg напрямую, вместо командного файла:

$WINDIR/system32/reg.exe

Это расположение по умолчанию для reg.exe при включении в операционную систему.

$WINDIR/sysnative/reg.exe

Это виртуальное расположение собственного 64-битного reg.exe при выполнении из 32-битного процесса.

2 голосов
/ 21 января 2010

Да, вы должны использовать KEY_WOW64_64KEY, другого обходного пути для 32-битного процесса не существует. Вызов API Win32 напрямую из Perl представляется возможным, судя по этой веб-странице .

1 голос
/ 20 мая 2015

Как вы заметили в своем вопросе, можно указать 64-битные или 32-битные представления реестра с флагом KEY_WOW64_64KEY .

Старый Win32API :: Registry может указывать 64-битный реестр с KEY_WOW64_64KEY , но в наши дни лучше использовать объектные функции 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 (теоретически, в любом случае).

Примечание: мне нужно было указать полное пространство имен для функции KEY_READ () в моей версии Perl, чтобы предотвратить ошибки компиляции, и я не уверен, есть ли именованные значения для констант 0x0100 и 0x0200, так что это возможно это может быть красивее. Но это работает!


(Адаптировано с мое решение моего вопроса о невозможности чтения реестра , заданное до того, как я узнал, что моя проблема связана с 64-разрядным или 32-разрядным).

...