How to get paths for apps showing in "App Paths" folder in Windows Registry using windows API?

Viewed 95

I'm trying to update the Raku code in this file which tries to find the path to commands/apps on a Windows machine.

I have a Windows 11 machine running inside VirtualBox. wordpad.exe cannot be run from the command line because it is not in the $PATH, and so the code will also fail to detect wordpad.exe in the path. As a fallback, the Raku code attempts to find the executable in the registry using the Windows API via the NativeCall module. However, this is also failing to find the wordpad.exe command.

Looking at the registry, there is a WORDPAD.EXE entry in the registry at Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\WORDPAD.EXE. It shows a path of "%ProgramFiles%\Windows NT\Accessories\WORDPAD.EXE".

I did a little googling, and this is how paths to some executables are stored. However, I was not able to figure out how to use the Windows API to find and extract the path to the app. I'm also unclear as to why the current Raku code uses the AssocQueryStringA() function.

Some hints are dropped in this SO answer.

But, never having done Windows API programming, and only knowing basic C programming, I'm a little at a loss.

1 Answers

I was able to piece together a solution using most of this code which needed a few adjustments to get working properly. Here is the code that works:

use NativeCall;

constant BYTE    := uint8;
constant WCHAR   := uint16;   
constant DWORD   := int32;    
constant REGSAM  := int32;
constant WCHARS  := CArray[WCHAR];
constant BYTES   := CArray[BYTE];

constant HKEY_LOCAL_MACHINE = 0x80000002;
constant KEY_QUERY_VALUE   = 1;
constant ERROR_SUCCESS     = 0; # Yeah, I know. The Win-Api uses 0 for success and other values to i
+ndicate errors

sub RegOpenKeyExW( DWORD, WCHARS, DWORD, REGSAM, DWORD is rw) is native("Kernel32.dll") returns DWOR
+D { * };


sub RegQueryValueExW( DWORD, WCHARS, DWORD is rw, DWORD is rw, BYTE is rw, DWORD is rw) is native("K
+ernel32.dll") returns DWORD { * };


my $key = 'SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths';

my DWORD $hkey;
my $length = 1024;

sub wstr( Str $str ) returns WCHARS {
    my $return = CArray[WCHAR].new( $str.encode.list );
    $return[$return.elems] = 0;
    return $return;
}

my $h-key = RegOpenKeyExW(HKEY_LOCAL_MACHINE, wstr($key), 0, KEY_QUERY_VALUE, $hkey);
say $hkey;

The key to figuring this out was that the HKEY_LOCAL_MACHINE constant has a hex value of 0x80000002 which can be used to getting the hkey value for other keys.

With this stumbling block overcome, it should now be a simple matter to retrieve data about the subkeys which contain the paths to the application in the folder using other Windows API functions.

Related