【问题标题】:Powershell problem with service status searching服务状态搜索的Powershell问题
【发布时间】:2021-09-24 09:50:46
【问题描述】:

大家好,这对你来说可能是一个简单的问题,但我是 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)) {

【问题讨论】:

  • 你有什么问题?
  • 是的,它不起作用
  • 是的,我们看不到您的屏幕,因此我们无法理解问题所在。
  • 是的,sry mb,现在我已经编辑了它
  • .Contains() 是用于测试字符串是否包含另一个子字符串的 string 方法。改用-containsoperator,它测试一个array是否包含某个子字符串。

标签: windows powershell service properties status


【解决方案1】:

优化补充Santiago Squarzon's helpful answer

# 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]Get-Service 返回的对象的.Status 属性的类型)用于确保输入了有效的服务状态标识符。


至于你尝试了什么

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

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

  • 相比之下,PowerShell 的 -contains operator 确实执行按需类型转换(正如 PowerShell 通常所做的那样),并且特别是不区分大小写 em>(通常是 PowerShell)。这同样适用于功能等效但操作数反转的-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,因此后者的自动类型转换和不区分大小写适用。有关-contains-in 的更多信息,请参阅this answer 的底部。

陷阱:由于名称相同,可能会与 .Contains() string method 混淆,但其功能不同:它执行 文字子字符串 匹配,并且没有 em> 在 PowerShell 中等效的直接运算符 - 请参阅 this answer

还有:

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

  • Write-Host is typically the wrong tool to use,除非意图是仅写入显示器,绕过成功输出流,并且能够将输出发送到其他命令,将其捕获到变量中或重定向它到一个文件。要输出一个值,请单独使用它;例如,$value 而不是 Write-Host $value(或使用 Write-Output $value,尽管这很少需要);见this answer

【讨论】:

  • 哇,太感谢了,教程真的很清晰有用
  • 很高兴听到这个消息,@kaiwenShao;我的荣幸。
【解决方案2】:

尝试改用这个:

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

【讨论】:

  • @kaiwenShao 是的,没问题 :) .Contains(...) 不能在服务的状态数组上工作,这就是我使用 -in 的原因。如果此答案对您有帮助,请考虑accepting it
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-10
相关资源
最近更新 更多