Replace psexec with native powershell commands

Brass Contributor

Hello,

 

we have a remotely located ($remoteserver1) script that we want to run on the said remote computer ($remoteserver1) from a "controler" server (via a scheduled task).

 

As of today in a CMD file (located in our controler server) we have something like this :

%dir_command%\psexec.exe "\\servername" -accepteula powershell "C:\_Scripts\Pools_Scripts\myscript.ps1" "param1" "param2" "param3" "param4" 

 

For the moment I want to replace this cmd by a ps script as a first step.

 

I have tried to use the call operator &, invoke-expression, invoke-command etc but nothing works.

 

What would be the correct method for executing a remote script on a remote computer (knowing that the script is local to the remote server) ?

 

As a secondary step I will probable try to run a "locally" (centralized smb share) stored script to the remote computer. But I can't go straight to this step. However if you already have recommandations for doing this I would be interested.

 

thank you for your help.

 

 

 

10 Replies
I think I found the solution myself. I simply had to replace the " " by { } in the $command var.
Though I still have an issue of the nested variables not beeing interpreted.

$command = {C:\_Scripts\Pools_Scripts\myscript.ps1" "param1" "$param2" "param3" "param4" }
Invoke-Command -ComputerName $remoteserver1 -ScriptBlock $command

For my test I wrote $param2 value and it's working. If I leave $param2 in $command it is not interpreted.
So apparently I must use $using:param2

$command = {C:\_Scripts\Pools_Scripts\myscript.ps1" "param1" "$using:param2" "param3" "param4" }
Invoke-Command -ComputerName $remoteserver1 -ScriptBlock $command

It seemd to work now.

If anyone can validate this :)

thank you

@John_Dodo 

 

It's odd that using the $Using scope modifier is the resolution, however, without the full scripts (from the host doing the remoting as well as the script being run on the remote host) it's too hard to say why that's needed - other than it speaks to the likelihood of a variable with the same name existing in a higher-priority scope.

 

Setting that aside, you'd normally go about this using -ArgumentList in the Invoke-Command and then using param() definitions within the script block to name those parameters.

 

Here's a basic example.

 

$Param1 = "Foo";
$Param2 = "Chew";
$Param3 = "Bless";
$Param4 = "You";

Invoke-Command -ComputerName "someRemoteComputer.yourdomain.com" -ArgumentList $Param1, $Param2, $Param3, $Param4 -ScriptBlock {
    param($LocalParam1);
    param($LocalParam2);
    param($LocalParam3);
    param($LocalParam4);
    
    .\MyScript.ps1 $LocalParam1 $LocalParam2 $LocalParam3 $LocalParam4;
}

 

Still, so long as what you've got is working, the example above is nothing more than general information on passing parameters with Invoke-Command.

 

Cheers,

Lain

Hi Lain,

thank you for your help on this. Both method seem to be working as for executing a remote code and using the value of a local variable as a parameter. So that's good.
Still, I decided to use your code because I trust more your knowledge than mine !! :D

Now I have an odd issue.
On my remote code I basically run a vmware action (VM shutdown etc). Let's call it vmware.ps1

If I run vmware.ps1 script directly on the remote server => it works
If I make a call to the same script from a command (cmd.exe) window from the controler server => it works.
Now when using the controler script using the invoke-command from the controler server => the code is stuck when running the remote vmware command.

Controler' script :

 

 

 

...somecode....
$vm = myvm
Invoke-Command -ComputerName remoteserver -ArgumentList $vm -ScriptBlock {
param($LocalParam1);
C:\_Scripts\Pools_Scripts\vmware.ps1 "$LocalParam1" "shutdown";
}
...somecode...

 

 

 



vmware.ps1 script located on remoteserver

 

 

 

...somecode....
switch ($vmaction)
{
"shutdown" {
write-host "1"
if ($vmstate.State -eq "Running") {
write-host "2a"
Shutdown-VMGuest -VM $vmname -Confirm:$false #-InformationAction Ignore -ErrorAction Ignore
write-host "2b"
}
write-host "3"
}

...somecode...

 

 

 



When running the controler script my last screen return is "2a". Then nothing happens... while when run it locally or with my former cmd call with psexec, it's all fine.

Any idea? I tried to add a -informationaction and -erroraction to ignore but still the same. As an additionnal information, the command shutdown-vmguest normally returns some information :
PowerState : PoweredOff
Version : v13
HardwareVersion : vmx-13
Notes : blabla
Guest : vmname
NumCpu : 2
CoresPerSocket : 1
MemoryMB : 8192
.... etc

Any idea why this behavior would happen? it looks like it's waiting for a confirmation or something...

@John_Dodo 

 

Out of curiosity, in line 2 from the controller's script, you assign a value to a variable named $var, but on line 3, you use a variable named $vm in the -Argumentlist.

 

Maybe this is valid (since we can't see all the code - which is fine), but if it's a mistake, then maybe that explains the pausing after 2a is written. That said, I'm really guessing here since I don't know how Shutdown-VMGuest behaves if you pass a bad value (including $null) for the -VM parameter since I don't use VMware (I'm a Hyper-V guy.)

 

Cheers,

Lain

Oh I'm so sorry, it's an error when I wrote it. I fixed $var to $vm
It's not the exact code only the important part of it. So the value passed is right and I can actually see it in the first informational outputs just before this vmware command is ran.

I don't think it's specificaly related to beeing from vmware. I think it's more because this command does something particular. I don't know exactly how "far" I can go when using invoke-command, is there any limitations ?

Again, when I call the exact same script using psexec + parameters instead of invoke-command + parameters, both calls work but the second one get's stuck while the first one ends properly.

PS : Maybe I should say that the command returns this when running locally, it's normally not blocking as I don't use these parameters : 

"WARNING: GuestId property is deprecated. Please use ConfiguredGuestId and RuntimeGuestId properties"
instead.

@John_Dodo 

 

I can't see anything wrong when looking at it from a PowerShell perspective.

 

If you comment out the call to Shutdown-VMGuest from your vmware.ps1 script and run it again, do you then see the 2b and 3 output?

 

As an aside, you should really have a "break;" statement after the Write-Host "3" in between the current lines 11 and 12, or else you'll possibly fall through that case block and into the next one (if there is one, that is.)

 

   write-host "3";
   break;
}

 

This isn't going to help with your current issue, just figured I'd flag it to avoid future potential issues.

 

Cheers,

Lain

If I comment the line with the call to shutdown-vmguest it works all fine until the end of the script.

@John_Dodo 

 

Do you get anything printed out if you insert the following line before the actual Shutdown-VMGuest command in vmware.ps1?

 

Write-Host "Shutdown-VMGuest -VM $vmname -Confirm:`$false";

 

So, it'd look like this:

 

write-host "2a";
Write-Host "Shutdown-VMGuest -VM $vmname -Confirm:`$false";
Shutdown-VMGuest -VM $vmname -Confirm:$false;

 

Cheers,

Lain

Hi Lain,

 

I would get the expected output form the write-host yes. Not sure what you try to demonstrate though. :)