1

I am trying to install Win32::TieRegistry for use in a perl program that I will run in WSL (under emacs). Details about the perl program I am writing at the end. I see that the above module should let me query the Windows Registry from perl.

I get the following error when in cpan I do:

cpan[16]> install Win32API::Registry

Running install for module 'Win32API::Registry'
  CHORNY/Win32API-Registry-0.33.tar.gz
  Has already been unwrapped into directory /home/cfclark/.cpan/build/Win32API-Registry-0.33-0
  CHORNY/Win32API-Registry-0.33.tar.gz
  '/usr/bin/perl Makefile.pl INSTALLDIR$=site' returned status 65280, not re-running

cpan[17]> install Win32::TieRegistry

Running install module 'Win32::TieRegistry'
  CHORNY/Win32-TieRegistry-0.30.tar.gz
  Has already been unwrapped into directory /home/cfclark/.cpan/build/Win32-TieRegistry-0.30-1
  CHORNY/Win32-TieRegistry-0.30.tar.gz
  Has already been prepared
  CHORNY/Win32-TieRegistry-0.30.tar.gz
  Has already been made
Running make test for CHORNY/Win32-TieRegistry-0.30.tar.gz
PERL_DL_NONLAZY=1 "/usr/bin/perl" "-MExUtils::Command::MM" "-MTest::Harness" "-e" "undef *Test::Harness::Switches; test_harness(0, 'blib/lib', 'blib/arch')" t/*.t
t/01_compile.t .. skipped: Not testing on non-Windows
t/02_main.t .... Can't locate Win32API/Registry.pm in @INC (you may need to install the Win32API::Registry module) (@INC contains: /home/cfclark/.cpan/build/Win32-TieRegistry-0.30-1/blib/lib  /home/cfclark/.cpan/build/Win32-TieRegistry-0.30-1/blib/arch  /home/cfclark/.cpan/build/YAML-1.30-1/blib/arch <and a bunch more directories but not ones for Win32-TieRegistry-0.30-0>
BEGIN failed--compilation aborted at t/02/main.t line 17.
t/02_main.t .... Dubious, test returned 2 (wstat 513, 0x200)
No subtests run

My goal is to convert a Windows .cmd file which gets some data out of the Windows registry (using reg query) into a perl program I can run under (emacs under) WSL. I initially tried converting the .cmd script to BASH, but I needed some regex operations on the registry output that were easier to do in Perl. I also tried system('reg.exe', 'query' .....) but that seems to never return to the emacs shell, i.e. the perl program just hangs after that system command.

In any case, the issue seems to be that installing Win32API::Registry failed and it refuses to re-install it. Thus, the relevant directory was never added to the @INC search path. However, I don't know how to tell cpan to fix that issue.

intel_chris
  • 708
  • 1
  • 6
  • 17

2 Answers2

4

Those are modules which make Windows system calls. You can't install them in Linux. Linux doesn't even have a concept of registry.

You'll have to do what you want from the Windows machine whose registry you want to change (e.g. using Strawberry Perl) instead of from a Linux machine.

It is possible to remotely edit a registry. I don't know what requirements are needed. (For example, do you need a certain version of Windows on the client? Do both machines need to be connected to the same domain?) And I don't know what tools are available for doing that from Linux, if any. This is not a route I recommend.

ikegami
  • 367,544
  • 15
  • 269
  • 518
  • I don't have a linux machine at the moment. My linux machines are 6 hours away. I have a windows laptop with WSL installed. I can call reg.exe from bash (in WSL) and get the information I want, but that's adding another layer, I guess I could pipe that output to perl, you can pipe windows commands to unix command in WSL, but then that would be a separate perl process. Ugg. I'll play some more. – intel_chris Apr 04 '23 at 15:57
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/252972/discussion-between-intel-chris-and-ikegami). – intel_chris Apr 04 '23 at 16:46
  • 1
    Re "*I don't have a linux machine at the moment.*", You said you were using WSL. WSL is a component of Windows which allows one to run virtual *Linux machines*. The test output corroborates this. WSL isn't a port of GNU utils; it's a VM running the Linux OS. My answer stands. You can't make Windows API calls when using Linux. – ikegami Apr 04 '23 at 17:45
0

Not being able to use the Windows API in Linux for the reasons pointed out by @ikegami, I have a rough work-around that lets my Perl script running in WSL read the registry values of interest from the Windows machine it is running on. It is not pretty, but it works.

First, the Perl code:

use feature 'signatures';
sub GetRegistryValue($registry, $query_suffix, $value) {
  my $results = qx( "pathtobashscript/regquery ${registry}, ${query_suffix}, ${value}" );
  # check $? here for errors, code omitted, but the script returns 0 on found
  return $results;
}

Now, the bash script 'regquery' (the hard part):

#!/bin/bash
set -e
set -o pipefail
trap 'exit 1' 1 2 3 13 15
reg.exe query "$1\\$2" /v "$3" |& cat
trap 1 2 3 13 15
exit 0

Usage example in perl:

my $reg_value = GetRegistryValue('HKLM', 
    "\"SOFTWARE\\\\Microsoft\\\\VisualStudio\\\\SxS\\\\VS7\"", '"14.0"');

I might have been able to avoid some of the backslash hell in the 2nd argument, but this came from tweaking it until I found enough to get through, Perl, Bash, and possibly Windows requirements.

Some of the key issues, without the cat command in the bash script, WSL doesn't always return cleanly to the Perl caller (nor to Emacs shell buffers). However, due to that pipe, you need the code that traps pipe failures and returns an exit status if the reg.exe command fails. Otherwise, the pipe to the cat command hides that status.

Note, reg.exe seems to be always in my path, but you might need to use a specific Windows path if it isn't on yours. There is an example of that somewhere here on StackOverflow, but that wasn't my issue.

Note, the StackOverflow code I cribbed the trap command from (How do you catch error codes in a shell pipe?) lists 0 in the list of signals to trap, but because of the pipe, that creates a sub-shell and you get that signal and the script returns an error code of 256 to Perl, removing 0 from the list avoids that problem.

The results have text I still need to filter, which is why I am using Perl in the first place, but I now have the values that I used to depend upon nested .cmd files to get.

If anyone, knows how to do this all in Perl (running in Emacs running in WSL, not on Windows), so that I can avoid the bash script, I would be interested in seeing how it works. (I need to be able to run Emacs within WSL as that's the environment I work in.)

intel_chris
  • 708
  • 1
  • 6
  • 17