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.