Home > OS >  Problem Executing NirSoft SearchMyFiles.exe from Powershell
Problem Executing NirSoft SearchMyFiles.exe from Powershell

Time:04-06

I know this is a problem in how I'm passing the arguments but I can't figure it out as it looks like I've successfully escaped the characters that might cause a problem.

PS> $ExecutionPath = "G:\BEKDocs\NonInstPrograms\NirSoftx64"
$PgmName       = "Searchmyfiles.exe"
$RunCmd        = Join-Path -Path "$ExecutionPath" -ChildPath "$PgmName"
$MyArgs        = " `/config `"G:\BEKDocs\TestSMF.cfg`" `/StartSearch `/ExplorerCopy `/stext `"G:\BEKDocs\TestSMF.txt`""
$runcmd         = $MyArgs
& $Runcmd

---Results: No file Created no Error messages displayed---

--- Show the Created Command ---

PS> $RunCmd
G:\BEKDocs\NonInstPrograms\NirSoftx64\Searchmyfiles.exe /config "G:\BEKDocs\TestSMF.cfg" /StartSearch /ExplorerCopy /stex
t "G:\BEKDocs\TestSMF.txt"

--- Try to Execute the command from History ---

PS> G:\BEKDocs\NonInstPrograms\NirSoftx64\Searchmyfiles.exe /config "G:\BEKDocs\TestSMF.cfg" /StartSearch /ExplorerCopy /stex
t "G:\BEKDocs\TestSMF.txt"

--- Result: No file created no Error messages displayed. ---

--- Type the command by hand ---

PS> G:\BEKDocs\NonInstPrograms\NirSoftx64\searchmyfiles.exe /config "G:\BEKDocs\TestSMF.cfg" /StartSearch /ExplorerCopy /stext "G:\BEKDocs\TestSMF.txt"

--- Result: File CREATED as expected ---
PS> 

I'm at a loss!

CodePudding user response:

In testing it appears that it is treating $Runcmd — both executable path and parameters — as one complete executable path to execute. I believe this is explained by the following section of about_Operators...

The call operator does not parse strings. This means that you cannot use command parameters within a string when you use the call operator.

PS> $c = "Get-Service -Name Spooler"
PS> $c
Get-Service -Name Spooler
PS> & $c
& : The term 'Get-Service -Name Spooler' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.

Instead, pass the executable path and parameters to the call operator separately...

$ExecutionPath = "G:\BEKDocs\NonInstPrograms\NirSoftx64"
$PgmName       = "Searchmyfiles.exe"
$RunPath       = Join-Path -Path "$ExecutionPath" -ChildPath "$PgmName"
$MyArgs        = @(
    '/config',       '"G:\BEKDocs\TestSMF.cfg"',
    '/StartSearch',
    '/ExplorerCopy',
    '/stext',        '"G:\BEKDocs\TestSMF.txt"'
)

& $RunPath $MyArgs

You'll notice that $MyArgs is now an array and not a [String]. It seems that if $MyArgs is a [String] or a single-element array it gets passed to the executable as one parameter surrounded by double quotes. Stored as above each array element gets passed as a parameter with no additional quoting. If you still want to define $MyArgs using one line of text you could do so like this...

$MyArgsText    = '/config "G:\BEKDocs\TestSMF.cfg" /StartSearch /ExplorerCopy /stext "G:\BEKDocs\TestSMF.txt"'
# NOTE: This only works because the path parameters contain no spaces
$MyArgs        = $MyArgsText -split ' '

All of the above is why, for anything but ad hoc commands, I would prefer the self-documenting, obvious-as-to-which-string-is-treated-as-which nature of a Start-Process call with explicitly-named parameters over the call operator. Given...

$ExecutionPath = "G:\BEKDocs\NonInstPrograms\NirSoftx64"
$PgmName       = "Searchmyfiles.exe"
$RunPath       = Join-Path -Path "$ExecutionPath" -ChildPath "$PgmName"
$MyArgsText    = '/config "G:\BEKDocs\TestSMF.cfg" /StartSearch /ExplorerCopy /stext "G:\BEKDocs\TestSMF.txt"'

...then both this...

Start-Process -FilePath $RunPath -ArgumentList $MyArgsText

...and this...

# NOTE: This only works because the path parameters contain no spaces
$MyArgs        = $MyArgsText -split ' '

Start-Process -FilePath $RunPath -ArgumentList $MyArgs

...execute $RunPath with the same parameters.

CodePudding user response:

I think every time I tried to include both the EXE name and the parameters in the same string, The call operator (&) fails. With that in mind, try something where $Runcmd is pointing only to the EXE and nothing else. This also makes testing easy by temporarily placing the path to EchoArgs in $Runcmd to view the actual parameters the EXE will be receiving.

This code example uses the Stop-parsing token (--%) and environmental variables to build the parameters passed to the EXE in $Runcmd.

$ExecutionPath = "G:\BEKDocs\NonInstPrograms\NirSoftx64"
$PgmName       = "Searchmyfiles.exe"
$RunCmd        = Join-Path -Path "$ExecutionPath" -ChildPath "$PgmName"
$Env:Config = '"G:\BEKDocs\TestSMF.cfg"'
$Env:SText = '"G:\BEKDocs\TestSMF.txt"'
& $Runcmd --% /config %Config% /StartSearch /ExplorerCopy /stext %SText%
  • Related