PowerShell中相同数值逻辑比较返回不同结果的问题排查
问题分析与解决方案:Select-Object自定义属性内比较始终返回False
问题根源
你遇到的问题核心在于:Select-Object中定义的多个自定义属性是并行独立执行的,无法引用同一操作内其他自定义属性。
当你在ToRestart的脚本块中写[int]$_.UptimeHours -gt 24时,$_.UptimeHours并不是你刚定义的那个UptimeHours属性——所有自定义属性的脚本块都是基于原始输入对象(Get-BrokerDesktop返回的对象)执行的,此时UptimeHours还未被添加到对象中,所以$_.UptimeHours会返回$null。将$null转为int得到0,0 -gt 24自然返回False。
而你在Select-Object之后执行[int]$var.UptimeHours -gt 24时,$var已经包含了生成好的UptimeHours属性,所以能得到正确结果。
解决方案
有三种常用的修复方式,按需选择:
1. 分两步执行Select-Object
先生成包含UptimeHours的中间对象,再基于该对象添加ToRestart属性:
$var = Get-BrokerDesktop -Filter {HostedMachineName -eq $machineName} | Select-Object -Property MachineName, @{L="UptimeHours";E={(New-TimeSpan $_.LastHostingUpdateTime (Get-Date)).TotalHours}}, @{L='UptimeFormatted';E={'{0:%d} Days & {0:%h\:mm\:ss}' -f (New-TimeSpan $_.LastHostingUpdateTime (Get-Date))}}, RegistrationState | Select-Object -Property *, @{L="ToRestart";E={[int]$_.UptimeHours -gt 24}}
2. 复用计算结果,避免重复计算
在单个处理步骤中先计算时间跨度,再同时生成多个属性,减少重复调用New-TimeSpan:
$var = Get-BrokerDesktop -Filter {HostedMachineName -eq $machineName} | ForEach-Object { $timeSpan = New-TimeSpan $_.LastHostingUpdateTime (Get-Date) [PSCustomObject]@{ MachineName = $_.MachineName UptimeHours = $timeSpan.TotalHours UptimeFormatted = '{0:%d} Days & {0:%h\:mm\:ss}' -f $timeSpan ToRestart = [int]$timeSpan.TotalHours -gt 24 RegistrationState = $_.RegistrationState } }
3. 在自定义属性中通过Add-Member传递计算结果
利用Add-Member的-PassThru参数,在生成UptimeHours的同时附加其他属性:
$var = Get-BrokerDesktop -Filter {HostedMachineName -eq $machineName} | Select-Object -Property MachineName, @{ L="UptimeHours"; E={ $ts = New-TimeSpan $_.LastHostingUpdateTime (Get-Date) $_ | Add-Member -NotePropertyName 'UptimeFormatted' -NotePropertyValue ('{0:%d} Days & {0:%h\:mm\:ss}' -f $ts) -PassThru | Add-Member -NotePropertyName 'ToRestart' -NotePropertyValue ([int]$ts.TotalHours -gt 24) -PassThru $ts.TotalHours } }, RegistrationState
验证
采用上述任意一种方式后,$var.ToRestart都会正确返回True(当UptimeHours为87时),和后续单独执行的比较结果一致。
内容的提问来源于stack exchange,提问作者Arcturus
相关产品推荐
相关产品推荐

