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.