2

I'm working on a generic/common PS script that I can use to execute other scripts remotely on multiple machines. Using psexec for this. I know there are other ways to do it but psexec seems to be the most reliable in my scenario.

Here is an excerpt of what I initially tried:

SWITCH ($ScriptExt) {
    '.bat' {$ShellCmd = 'CMD /C'}
    '.cmd' {$ShellCmd = 'CMD /C'}
    '.ps1' {$ShellCmd = 'powershell -ExecutionPolicy Unrestricted -File'}
    [...]
    }
}

Get-Content $PcList | ForEach-Object {

    & "$PSScriptRoot\..\psexec.exe" \\$_.$Domain -u $Domain\$AdminUser -p $AdminPassword -h -i $ShellCmd $ScriptPath $ScriptArgs  ## Does NOT work...

    [...]
}

This does not work: psexec errors out every time telling me it can't run the program on the remote PC even though the path it provides looks correct.

Also tried to add some quotes within the ForEach:

& "$PSScriptRoot\..\psexec.exe" "\\$_.$Domain -u $Domain\$AdminUser -p $AdminPassword -h -i $ShellCmd $ScriptPath $ScriptArgs" ## Does NOT work...

...and various other iterations to try to get this to work.

After doing more troubleshooting, I found that it was the $ShellCmd variable that was causing the issue. If I hard-code that portion in the ForEach, like so:

& "$PSScriptRoot\..\psexec.exe" \\$_.$Domain -u $Domain\$AdminUser -p $AdminPassword -h -i powershell -ExecutionPolicy Unrestricted -File $ScriptPath $ScriptArgs

...it works but it's a hack.

Anyone know what I might be doing wrong with syntax? Comparing my working and non-working examples, there is very little difference except I'm trying to use the $ShellCmd variable in one.

martopg
  • 21
  • 2

2 Answers2

1

I believe the issue could be you're violating quoting rules.

Try breaking apart your command and using splatting:

$shell = 'powershell', '-ExecutionPolicy', 'Unrestricted', '-File'

& "$PSScriptRoot\..\psexec.exe" ... @shell $scriptPath $scriptArgs

As a side-note, I strongly recommend using WinRM & PSRemoting over psexec.

Maximilian Burszley
  • 18,243
  • 4
  • 34
  • 63
1

To complement TheIncorrigible1's helpful answer:

Just like $ShellCmd must not be passed as a single string - because it'll be passed as a single argument - and must instead be passed as an array of arguments (strings), so must $ScriptArgs.
You don't show its value in the question, but I'm mentioning it just to be clear.

As an aside: You don't strictly need the splatting operator (@) when passing a variable containing an array as individual arguments to an external program, so a regular (array) variable reference with $ will do in this case.[1]


[1] @array vs. $array makes a difference only in one edge case: if one of the array elements contains --%, the stop-parsing symbol, only @array treats it as such (and therefore modifies how the remaining arguments are parsed); by contrast, $array treats it as a literal string.

mklement0
  • 382,024
  • 64
  • 607
  • 775