简体   繁体   中英

Powershell problem with service status searching

Hi guys its maybe a easy question for you but im newbie from powershell so can you pls help me?

In school I got an assignment where I needed to make a menu, a script that could search from service to status, and a script that could search from status to service, and it looks like this:

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

i really dont understand where my problem is. It dosn't work: It doesn't do anything and then just ends the script If i debug, i only see it will skip this, even they are a lot of true value in $statusbank :

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

Try using this instead:

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

To complement Santiago Squarzon's helpful answer with an optimization :

# 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

Casting the user input (which is always a string ) to type [System.ServiceProcess.ServiceControllerStatus] (the type of the .Status property of the objects returned by Get-Service ) is used to ensure that a valid service-status identifier was entered.


As for what you tried :

Leaving the inefficiency of calling Get-Service twice aside, your primary problem was the use of the .Contains() .NET array method (implemented via the IList interface ):

  • .Contains() performs no on-demand type conversions, so looking for a string ( $sstatuss ) in your array of [System.ServiceProcess.ServiceControllerStatus] values ( $statusbank ) never succeeds.

  • By contrast, PowerShell's -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 .

To illustrate the difference:

# 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]

In a nutshell: -contains is in effect using the -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 for more information about -contains and -in .

Pitfall: Due to having the same name, there's potential for confusion with the .Contains() string method , which functions differently, however: it performs literal substring matching, and there is no direct operator equivalent in PowerShell for that - see this answer .

Also:

  • Format-* cmdlets output objects whose sole purpose is to provide formatting instructions to PowerShell's output-formatting system - see this answer . In short: only ever use Format-* cmdlets to format data for display , never for subsequent programmatic processing .

  • 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 ; eg, $value instead of Write-Host $value (or use Write-Output $value , though that is rarely needed); see this answer

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM