【问题标题】:It returns all services even though there is one in list即使列表中有一项,它也会返回所有服务
【发布时间】:2021-11-26 12:18:13
【问题描述】:

我希望我的脚本将服务器和服务作为 .txt 文件中的列表。之后,我希望我的脚本检查该服务是否存在于 txt 文件中的服务器上。

但是当我运行这个脚本时,它会返回服务器上存在的所有服务,而不是我在服务列表中指定的服务。即使服务不存在,它也不会掉线。

你能告诉我为什么它会返回所有的服务吗?

$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" 
}

【问题讨论】:

  • 问题是,$Service 在您的脚本块中是不可访问的。如果您将脚本块更改为Write-Host $Service,您将不会得到任何输出。这就是你获得所有服务的原因,因为Get-Service $Service 将变成Get-Service。您需要将参数作为 -ArgumentList 传递,如下所示:stackoverflow.com/questions/4225748/…
  • 您需要将服务作为参数传递,或者作为远程变量进行引用。您可以使用$using 变量:$using:service。 . .但是,Get-Service 接受远程计算机的 -ComputerName 参数,您可以切换它。
  • @AbrahamZinala 当我尝试它工作时,它显示服务名称不同。像 System.ServiceProcess.ServiceController
  • @M.G 这个话题对我来说似乎很高级。我总是在部分传递参数方面苦苦挣扎
  • @RedAndBlack 那是因为$List 包含一个ServiceController 对象。如果您只想打印名称,请执行Write-Host "$($List.Name) exists on $Server"

标签: powershell


【解决方案1】:

继续我的评论。 . .在脚本块中对远程计算机使用本地变量时,您必须将其作为参数传递,或者使用远程变量$using 引用它。

  • 这是由于远程计算机上正在运行一个新会话,但不知道该计算机上的 $service 是什么,因为它从未在该计算机上声明过。
  • 您可以使用-Arguments 参数传递它。创建一个 param 块以将其传递给或使用$using. 的远程变量

此外,您实际上不需要将命令调用到远程机器上,因为Get-Service 有一个用于远程机器的-ComputerName 参数:

$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 }
            }           
        }
    }

至于你尝试了什么:

$Result = Invoke-Command -ComputerName $Server -ScriptBlock {
                Get-Service -Name $Service
            }
  1. $service如上所述)为空,未在远程会话范围内定义。
  2. 当您将其切换到 $using:service 时,它可以工作,但是它返回了对象的 type 而不是名称本身,因为您返回的是整个对象而不是 name 属性。相反,只需引用循环中正在使用的当前$service 并声明它是否存在。

【讨论】:

  • 我试过这个,它奏效了。但由于某种原因,比如我有一个像 A B C 这样的列表,都在单独的行中。但是程序将列表作为'A B C'并返回false。程序运行良好。
  • 您能详细说明一下吗?不太清楚你的意思。因此,在您的列表中,您在同一行中有服务,例如:A B C? A、B 和 C 应该在哪里?
  • 就像我有一个 txt 文件,其中第一行是 A,第二行是 B,第三行是 C。当我运行它时,即使我通过 for 调用它,输出也像 A B C 一样的行循环
  • 你是用我的代码还是你自己的?
  • 我从我的程序中删除了服务列表。相反,我在程序中使用了数组。因为我会一直在寻找一些特定的服务。这很难,但解决了我的问题。感谢你的协助。它帮助很大
【解决方案2】:

脚本结构不正确,不需要我们调用命令,当你可以使用'get-service -computername'时,try,catch语句只会捕获最后一个错误而不是每个。

我更改了您的原始脚本以反映这一点,并移动了 try、catch 语句以捕获每个错误(如果服务不存在)。

$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"
        }       
    }
}

【讨论】:

  • 它成功了,谢谢。但如果我把它写在“”中,它会说 System.ServiceProcess.ServiceController。我需要删除“”,以便它给出名称。感谢您的帮助。
猜你喜欢
  • 2013-06-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-09-25
  • 2020-10-11
  • 1970-01-01
相关资源
最近更新 更多