Assistance with Invoke-Command ScriptBlock error.

Hello All,
What I am trying to accomplish is for this script to take a list of remote servers and find the “Service Name” of a service, and then convert that into a PID that will be used later for process termination. This is only a snippet of a script that will take a list of servers, ask the user for the “Service Name” of a service and kill that task. For a single server, I have it working.
Here is the issue, the script below is as far as I gotten toward my goal with a list of servers. This particular version seems the best, but gives an error "Get-Process: Cannot find a process withthe name “whatever”. I have verified the process exists with the name provided. In fact, the process that I am testing with has the same name as the Service Name except the process has ‘exe’ appended. Didn’t matter however.
It appears that Invoke-Command has trouble with multiple commands in the ScriptBlock, but I don’t know another way to make this happen.
I am limited to PoSH 5.1 and Get-Process and Get-WMIObject can’t accept the $server variable in the -ComputerName parameter of Invoke-Command. They only work if thier -ComputerName parameter is used.
Any assistance would be appreciated.

$ServerList = 'server01','server02'
$SvcName = 'whatever'
 
  
$ted = ForEach ($Server in $ServerList){
    Invoke-Command -ScriptBlock {
          $ProcID = Invoke-Command -ScriptBlock {(Get-Process -ComputerName $server -name $SvcName).Id};
          $ProcObj = Invoke-command -ScriptBlock {Get-WmiObject Win32_Process -ComputerName $server  | ?{ $_.ProcessId -match $ProcID }}
        }
}

Variables defined outside of the Invoke-Command script block cannot be referenced inside the Invoke-Command script block. So in your case line 7, $SvcName does not exist ($null). To “fix” this you would need to preface $using: or pass the object in as an argument to a parameter. Either way I would change the approach. Based on what your requirements are per the post here’s what I would do:

$ServerList = 'server01','server02'

$ted = Invoke-Command -ComputerName $ServerList -ScriptBlock {
    $SvcName = 'whatever'
    $PID = Get-CimInstance -ClassName win32_service |
        Where-Object {$_.Name -eq $SvcName} |
            Select-Object -ExpandProperty ProcessID
    #Do whatever you want to the process here. Just reference $PID for the pid
    

} #invoke-command script block

Note the computername parameter of invoke-command will take an array so no need for the foreach loop. Any objects returned from the remote script block will be assigned to $ted with a new property of PSComputerName that will tell you which server it came from.

There are numerous issues. This is invoking a command locally, to invoke a command locally again to make a remote call from the local server to the remote server. WMI and Get-Process (which in the background is using WMI) can make RPC calls to the server with DCOM:

$ServerList = 'server01','server02'
$SvcName = 'whatever'
   
$ted = ForEach ($Server in $ServerList){
    $ProcID = (Get-Process -ComputerName $server -name $SvcName).Id
    $ProcObj = Get-WmiObject Win32_Process -ComputerName $server  | ?{ $_.ProcessId -match $ProcID }
}

If you want to use PS Remoting with WSMAN, then you can do it like this to execute the commands remotely on the server. To pass a local variable to the remote session, you need to use the ‘Using:’ keyword:

$ServerList = 'server01','server02'
$SvcName = 'whatever'
  
$ted = ForEach ($Server in $ServerList){
    Invoke-Command -ComputerName $server -ScriptBlock {
          $ProcID  = (Get-Process -name $using:SvcName).Id
          $ProcObj = Get-WmiObject Win32_Process  | ?{ $_.ProcessId -match $ProcID }
        }
}

Also, keep in mind that this is assuming there is 1 returned value. Using -match is a regex, a better comparison would be using -eq (equals) for a straight comparison.

Yea, I had a feeling that I was on a bad path with this one, but couldn’t sort out exactly what. Thank you for the guidance.