I want my script to take the server and service as a list from a .txt file. After that I want my script to check that if this service exists on the servers on the txt file.
But when I run this script, it returns all of the services as it exists on the server and not the ones I specified in service list. Also it doesn't drop to catch even tho the service doesn't exist.
Can you tell me why it returns all of the services?
$ErrorActionPreference='stop'
$ServerList = Get-Content 'C:\Users\username\Desktop\service test\servers.txt'
$ServiceList = Get-Content 'C:\Users\username\Desktop\service test\services.txt'
try{
foreach($Server in $ServerList){
foreach($Service in $ServiceList){
$Result = Invoke-Command -ComputerName $Server -ScriptBlock {
Get-Service -Name $Service
}
foreach($List in $Result){
Write-Host "$List exists on $Server"
}
}
}
}
catch [System.Management.Automation.ActionPreferenceStopException]
{
Write-Host "Error"
}
CodePudding user response:
Continuing from my comment. . . when using a local variable against a remote computer in a scriptblock, you have to pass it as an argument, or have it referenced using the remote variable of $using
.
- This is due to a new session being ran on the remote machine with no clue what
$service
is on that machine as it's never been declared on that side. - You can pass it using the
-Arguments
, parameter. Creating a param block to pass it onto or, using the remote variable of$using
.
Also, there's really no need for you to invoke the command over to the remote machine as Get-Service
has a -ComputerName
parameter for remote machines:
$ServerList = Get-Content 'C:\Users\username\Desktop\service test\servers.txt'
$ServiceList = Get-Content 'C:\Users\username\Desktop\service test\services.txt'
foreach ($Server in $ServerList)
{
foreach ($Service in $ServiceList.trim())
{
[PSCustomObject]@{
ComputerName = $Server
Service = $Service
Exists = if (Get-Service -Name $service -ComputerName $Server -ErrorAction SilentlyContinue) { $true } else { $false }
}
}
}
as for what you tried:
$Result = Invoke-Command -ComputerName $Server -ScriptBlock {
Get-Service -Name $Service
}
$service
(as mentioned above), is empty and not defined on the remote sessions scope.- When you switched it to
$using:service
it worked but, it returned the type of object and not the name itself, because you're returning the entirety of an object and not the name property. Instead, just reference the current$service
that is being used in the loop and declare if it's there, or not.
CodePudding user response:
the script is not structured correctly, an no need to us the invoke command, when you can use 'get-service -computername' Also the try, catch statement would only catch the last error not each.
I changed your original script to reflect this and moved the try, catch statement to catch each error (if the service does not exist).
$ErrorActionPreference='stop'
$ServerList = Get-Content 'C:\temp\servicetest\servers.txt'
$ServiceList = Get-Content 'C:\temp\servicetest\services.txt'
ForEach($Server in $ServerList){
#Get-Service -ComputerName $Server -Name 'XblAuthManager'
ForEach($Service in $ServiceList){
try {
$a = Get-Service -ComputerName $Server -Name $Service
IF ($a) {
Write-Host "Service - $Service exists on Server - $Server"
}
} catch {
Write-Host "Service - $Service does not exist on Server - $Server"
}
}
}