I'm trying to return TRUE from searching Get-ComplianceSearch's output for 'Completed'. My code below is a simple wait loop. But I don't think I'm returning the value correctly because the loop never finishes. I'm fairly new to PowerShell. Please assist or direct.
I'm using Powershell Core 7.1. There are no errors but the Search-String condition never returns TRUE.
try {
$timer = [Diagnostics.Stopwatch]::StartNew()
while (($timer.Elapsed.TotalSeconds -lt $Timeout) -and (-not (Get-ComplianceSearch -
Identity $searchName | Select-String 'Completed' -SimpleMatch -Quiet))) {
Start-Sleep -Seconds $RetryInterval
$totalSecs = [math]::Round($timer.Elapsed.TotalSeconds, 0)
Write-Verbose -Message "Still waiting for action to complete after [$totalSecs]
seconds..."
}
$timer.Stop()
if ($timer.Elapsed.TotalSeconds -gt $Timeout) {
throw 'Action did not complete before timeout period.'
} else {
Write-Verbose -Message 'Action completed before timeout period.'
}
} catch {
Write-Error -Message $_.Exception.Message
}
(This is the expected output of the command Get-ComplianceSearch)
Okay, you don't want to use Select-String
here (although you can, see @mklement0's helpful answer, looking at object properties is usually preferred). That is returning an object and you want to check the Status
property for "Completed"
. Make the following change to the -not
subexpression:
(-not (Get-ComplianceSearch -Identity $searchName | Where-Object {
$_.Status -eq 'Completed'
}))
The above can be on one line but I broke it up for readability.
Basically, Select-String
looks for content in strings. If you are looking for a particular value of an object property however, you can use Where-Object
to test for a condition and return any objects matching that condition. In this case, we want to return any object that have a Status
of 'Completed'
, so we can negate that in the if
statement.
You (or others) might be wondering how this works since Where-Object
returns matching objects, but not booleans. The answer is "truthiness". PowerShell objects are "truthy", which means anything can be evaluated as a [bool]
.
The following values evaluate to $false
in most cases. I've included some gotchas to watch out for when relying on "truthy" values:
0
0
evaluates as $true
$true
$false
False
evaluates as $true
Most everything else will evaluate to $true
. This is also why comparison operators are syntactically optional when checking whether a variable is $null
or not. Although there are times when an explicit value check is a good idea as comparison operators compare the actual values instead of only whether the variable "is" or "isn't".
How does this apply to the expression above then? Simple. if
statements, always treat the condition expression as a [bool]
, no conversion required. In addition, logical operators and conditional operators also imply a boolean comparison. For example, $var = $obj
assigns $obj
to $var
, but$var = $obj -eq $obj2
or $var = $obj -and $obj2
will assign $true
or $false
.
So knowing the above, if Where-Object
returns nothing, it's $false
. If it returns a tangible object, it's $true
.