服务状态搜索的 Powershell 问题

Powershell problem with service status searching

大家好,这对您来说可能是一个简单的问题,但我是 Powershell 的新手,所以您能帮帮我吗?

在学校我接到了一个作业,我需要制作一个菜单,一个可以从服务搜索到状态的脚本,以及一个可以从状态搜索到服务的脚本,它看起来像这样:

    elseif ($menu -eq "2") {
    $statusbank = (Get-Service).Status
    $sstatuss = Read-Host "Bitte geben Sie ein Status ein z.B Running/Stopped"

if ($statusbank.Contains([string]$sstatuss)) {
        $Information = (Get-Service | Where-Object {$_status -eq $sstatuss}).Name | format-list -property Name
        Write-Host  $Information
    }
}

我真的不明白我的问题出在哪里。 它不起作用:它什么都不做,然后就结束了脚本 如果我调试,我只看到它会跳过这个,即使它们在 $statusbank 中有很多真实价值:

if ($statusbank.Contains([string]$sstatuss)) {

试试改用这个:

elseif ($menu -eq "2")
{
    $statusbank = Get-Service
    $sstatuss = Read-Host "Bitte geben Sie ein Status ein z.B Running/Stopped"

    if($sstatuss -match '^(Running|Stopped)$' -and $sstatuss -in $statusbank.Status)
    {
        $statusbank | Where-Object Status -EQ $sstatuss |
        Format-Table -Property Name,Status
    }
}

通过优化补充

# Prompt until a valid service status identifier is entered.
do {
  try {
    [System.ServiceProcess.ServiceControllerStatus] $sStatus = 
      Read-Host "Please specify the desired service status (e.g., Running or Stopped)"
    break # A valid value was entered, exit the loop
  } catch { }
  Write-Warning "Unknown status; please specify one of: $([Enum]::GetNames([System.ServiceProcess.ServiceControllerStatus]))"
} while ($true)

# Now output the names of all services that are in the specified state, if any:
(Get-Service | Where-Object Status -eq $sStatus).Name

将用户输入(始终是 字符串)转换为类型 [System.ServiceProcess.ServiceControllerStatus] (the type of the .Status property of the objects returned by Get-Service)用于确保输入了有效的服务状态标识符。


至于你试过的

抛开两次调用 Get-Service 的低效率不谈,你的主要问题是使用 .Contains() .NET 数组 方法 (通过 IList interface 实现):

  • .Contains() 不执行按需类型转换,因此在 string ($sstatuss) 数组中查找 [System.ServiceProcess.ServiceControllerStatus] 值 ($statusbank) 永远不会成功。

  • 相比之下,PowerShell 的 -contains operator does perform on-demand type conversions (as PowerShell generally does) and is notably also case-insensitive (as PowerShell generally is). The same applies to functionally equivalent, but operands-reversed -in operator.

为了说明区别:

# Sample array with [System.ServiceProcess.ServiceControllerStatus] elements.
$array = [System.ServiceProcess.ServiceControllerStatus]::Running,
         [System.ServiceProcess.ServiceControllerStatus]::Stopped

# WRONG.
$array.Contains('running') # !! always $false with a [string] as input

# OK.
$array -contains 'running' # -> $true - on-demand type conversion
                           # from string to [System.ServiceProcess.ServiceControllerStatus]

简而言之:-contains 实际上是在使用 -eq operator against each element behind the scenes, so the latter's automatic type conversions and case-insensitivity apply. See the bottom section of this answer 以获取有关 -contains-in 的更多信息。

陷阱:由于名称相同,可能会与 .Contains() string method, which functions differently, however: it performs literal substring matching, and there is no direct operator equivalent in PowerShell for that - see .

混淆

还有:

  • Format-* cmdlet 输出对象,其唯一目的是向 PowerShell 的输出格式化系统提供 格式化指令 - 请参阅 this answer。简而言之:只使用 Format-* cmdlet 来格式化数据 以供显示 ,永远不要用于后续 程序化处理 .

  • Write-Host is typically the wrong tool to use, unless the intent is to write to the display only, bypassing the success output stream and with it the ability to send output to other commands, capture it in a variable, or redirect it to a file. To output a value, use it by itself; e.g., $value instead of Write-Host $value (or use Write-Output $value, though that is rarely needed); see