You wrote:
$var = '"C:\Program Files (x86)\Opera\Launcher.exe" /uninstall'
& $var
You've noticed that this doesn't work. That's because the argument to the &
operator is a string representing the command to execute (but not parameters). The correct way to write it would be:
$var = "C:\Program Files (x86)\Opera\Launcher.exe"
& $var /uninstall
If you want to read a command line string from the registry (or somewhere else) and execute it as-is, one way to avoid Invoke-Expression
or invoking cmd.exe
is to tokenize the string. Here's a function that does that:
function Split-String {
param(
[String] $inputString
)
[Regex]::Matches($inputString, '("[^"]+")|(\S+)') | ForEach-Object {
if ( $_.Groups[1].Success ) {
$_.Groups[1].Value
}
else {
$_.Groups[2].Value
}
}
}
The first element in the returned array is the executable's name, and the remaining elements (if any) are the executable's parameters. The quote marks around the array elements are preserved.
You could use the function to run an executable using the &
operator as follows:
$var = '"C:\Program Files (x86)\Opera\Launcher.exe" /uninstall'
$tokens = @(Split-String $var)
$command = $tokens[0] -replace '^"?([^"]+)"?$', '$1'
if ( $tokens.Count -eq 1 ) {
& $command
}
else {
& $command $tokens[1..$($tokens.Count - 1)]
}
The third line in the code removes leading and trailing "
characters from the command name.
If you want to run the executable asynchronously, you can use Start-Process
. Example:
$var = '"C:\Program Files (x86)\Opera\Launcher.exe" /uninstall'
$tokens = @(Split-String $var)
$startArgs = @{
"FilePath" = $tokens[0] -replace '^"?([^"]+)"?$', '$1'
}
if ( $tokens.Count -gt 1 ) {
$startArgs.ArgumentList = $tokens[1..($tokens.Count - 1)]
}
Start-Process @startArgs