To offer a concise alternative, which also trims enclosing "
chars. from command lines with executables containing spaces and recognizes argument-less unquoted executable paths containing spaces without enclosing "..."
:
((Get-CimInstance win32_service).PathName -match '\.exe\b').ForEach({
if (Test-Path -LiteralPath $_) { # Check if the entire string is an unquoted executable path alone.
$_
} else {
$_ -replace '^(?:"(.+?)"|([^ ]+)).*', '$1$2'
}
})
The above uses:
member-access enumeration to get all .PathName
values simply by using property access at the collection level.
the regex-based -match
operator to limit the values to those containing the verbatim substring .exe
(regex metachar. .
must be escaped as \.
) at a word boundary (\b
).
the .ForEach()
array method, for faster processing (than with the ForEach-Object
cmdlet) of values already in memory.
- The
Test-Path
is used to check if the entire command line refers to a single executable, possibly with spaces in its path; if so, the entire string ($_
) is passed out.
- Otherwise, the command line is assumed to include arguments and/or an executable path enclosed in embedded
"..."
.
the regex-based -replace
operator with a regex that matches the entire input string and replaces it only with the substring of interest, the executable file path, via capture groups ((...)
).
- Note: The regex works whether or not the executable path ends in
.exe
, but given that the command line by definition does contain .exe
, simpler solutions are possible, as shown in Santiago's helpful answer and elkenyo's helpful answer, though the latter should be made more robust:
('"C:\Program Files\bar2.exe" -baz' -split '(?<=\.exe\b)')[0].Trim('"')
For an explanation of how the -replace
regex and substitution work, see this regex101.com snippet.
A simple demonstration:
$commandLines = 'c:\tools\foo1.exe',
'c:\tools\foo2.exe -bar',
'"C:\Program Files\bar1.exe"',
'"C:\Program Files\bar2.exe" -baz'
$commandLines -replace '^(?:"(.+?)"|([^ ]+)).*', '$1$2'
The above yields:
c:\tools\foo1.exe
c:\tools\foo2.exe
C:\Program Files\bar1.exe
C:\Program Files\bar2.exe