Skip to content

Commit

Permalink
Merge pull request #19 from sdondley/search-app-paths
Browse files Browse the repository at this point in the history
Search app paths
  • Loading branch information
azawawi committed Sep 15, 2022
2 parents 16790d3 + 1db23aa commit 7678660
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 13 deletions.
6 changes: 4 additions & 2 deletions META6.json
@@ -1,10 +1,12 @@
{
"name" : "File::Which",
"license" : "MIT",
"version" : "1.0.1",
"version" : "1.0.2",
"perl" : "6.c",
"description" : "Cross platform Perl 6 executable path finder (aka which on UNIX)",
"depends" : [],
"depends" : [
"Win32::Registry"
],
"test-depends" : [ "Test" ],
"provides" : {
"File::Which" : "lib/File/Which.pm6",
Expand Down
64 changes: 54 additions & 10 deletions lib/File/Which/Win32.pm6
Expand Up @@ -3,6 +3,7 @@ use v6;

unit class File::Which::Win32;

use Win32::Registry;
use NativeCall;

method which(Str $exec, Bool :$all = False) {
Expand Down Expand Up @@ -47,7 +48,7 @@ method which(Str $exec, Bool :$all = False) {

return @results.unique if $all && @results;
# Fallback to using win32 API to find executable location
return self.which-win32-api($exec);
return self.which-win32-api($exec, @PATHEXT) || Any;
}

#
Expand All @@ -61,7 +62,7 @@ sub AssocQueryStringA(uint32 $flags, uint32 $str, Str $assoc, uint32 $extra,

# This finds the executable path using the registry instead of the PATH
# environment variable
method which-win32-api(Str $exec) {
method which-win32-api(Str $exec, @paths) {
constant ASSOCF_OPEN_BYEXENAME = 0x2;
constant ASSOCSTR_EXECUTABLE = 0x2;
constant MAX_PATH = 260;
Expand All @@ -76,17 +77,60 @@ method which-win32-api(Str $exec) {
$exec, 0, $path, $size);

# Return nothing if it fails
return Any unless $hresult == S_OK;
if $hresult == S_OK {
# Compose path from CArray using the size DWORD (uint32)
# Ignore null marker from null-terminated string
my $exe-path = '';
for 0 .. $size[0] - 2 {
$exe-path ~= chr($path[$_]);
}

# Return the executable path string if found
return $exe-path if $exe-path;
}

# Compose path from CArray using the size DWORD (uint32)
# Ignore null marker from null-terminated string
my $exe-path = '';
for 0..$size[0] - 2 {
$exe-path ~= chr($path[$_]);
# search registry for apps
my $has-extension = @paths.first({ $exec.ends-with($_, :i)}).so;

my @keys-to-check;
@keys-to-check = $has-extension
?? $exec
!! @paths.map: { $exec ~ $_ } ;

my @hives-to-check = <local_machine current_user>;
my $key = 'SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths';
for @keys-to-check -> $k {
for @hives-to-check -> $h {
my $full-key = $h ~ "\\$key\\$k";
if key-exists($full-key) {
return get-path $full-key;
}
}
}
}

sub get-path(Str:D $key) {
my $k = open-key($key);

my int32 $b = 600;
my $value = CArray[uint16].new;
$value[$_] = 0 for ^$b;

my $blah = RegGetValueW($k, wstr(''), wstr(''), 0x0000ffff, 0,

This comment has been minimized.

Copy link
@ugexe

ugexe Sep 17, 2022

Contributor

$blah?

This comment has been minimized.

Copy link
@azawawi

azawawi Sep 18, 2022

Author Owner

Yeah this should be fixed once the PR is merged.

$value, $b);
my $name = '';
$value[$b] = 0;
if !$blah {
for ^$b {
last if !$value[$_].so;
$name ~= chr($value[$_]);
}
}
close-key $k;

# Return the executable path string
return $exe-path;
# Sometimes, the path is surrounded by quotes for some reason. Remove them.
$name.=trans( '"' => '');
return $name;
}

=begin pod
Expand Down
3 changes: 2 additions & 1 deletion t/02-win32.t
@@ -1,9 +1,10 @@
use v6;

use lib 'lib';

This comment has been minimized.

Copy link
@ugexe

ugexe Sep 17, 2022

Contributor

dont use lib 'lib' in tests

This comment has been minimized.

Copy link
@azawawi

azawawi Sep 18, 2022

Author Owner

Noted. I thought we used to need that. My Raku memory cache needs to be refreshed 👍

use Test;
use File::Which;

my @execs = ('calc', 'cmd', 'explorer', 'notepad');
my @execs = ('calc', 'cmd', 'explorer', 'notepad', 'wordpad');

plan @execs.elems * 2;

Expand Down

0 comments on commit 7678660

Please sign in to comment.