You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PowerShell:IIS证书到期检测脚本替换Foreach-Object为传统foreach异常求助

问题:传统foreach循环替代Foreach-Object后无法正确输出证书到期剩余天数

需求为编写脚本获取IIS服务器上已安装证书的到期剩余天数,使用Foreach-Object的原脚本可正常输出结果,但改用传统foreach循环后,脚本返回证书的Thumbprint和Subject信息,无法得到正确的到期天数。

原脚本(可正常运行)

$CertAll=Get-ChildItem -Path Cert:\LocalMachine\My
$CertInUse=Get-Childitem -Path IIS:\SslBindings
$CertSame=Compare-Object -ReferenceObject $CertAll -DifferenceObject $CertInUse -Property ThumbPrint -IncludeEqual -ExcludeDifferent
$CertSame | foreach{Get-Childitem –path Cert:\LocalMachine\My\$($_.thumbprint)} | Select-Object @{n=’ExpireInDays’;e={($_.notafter – (Get-Date)).Days}}

原脚本输出

ExpireInDays
------------
         311
          74

修改后的脚本(输出异常)

$CertAll=Get-ChildItem -Path Cert:\LocalMachine\My
$CertInUse=Get-Childitem -Path IIS:\SslBindings
$CertSame=Compare-Object -ReferenceObject $CertAll -DifferenceObject $CertInUse -Property ThumbPrint -IncludeEqual -ExcludeDifferent

Foreach ($element in (Get-Childitem –path Cert:\LocalMachine\My\$($CertSame.thumbprint))) {

    Select-Object @{n=’ExpireInDays’;e={($CertSame.notafter – (Get-Date)).Days}}
    #command to send value

}

修改后脚本输出

Thumbprint                                Subject                                                                                                                              
----------                                -------                                                                                                                              
91365BBBE0104494AA9C1C7413595B8B7395F05A  CN=*.zetes.be                                                                                                                            
98F20A03831CAE8895E8F39E369A07CAAC161C88  CN=*.zetes.com   

错误原因分析

  1. 路径拼接逻辑错误:$CertSame是Compare-Object返回的集合,直接取$CertSame.thumbprint会得到一个数组,尽管Get-ChildItem能处理数组路径,但后续循环未正确绑定单个证书对象。
  2. Select-Object的对象引用错误:循环内的Select-Object未针对当前循环的$element处理,反而引用整个$CertSame集合,且未将$element传入管道,导致Select-Object默认输出Get-ChildItem返回的证书对象的默认属性(Thumbprint和Subject)。

修正后的脚本

写法一:直接构造自定义对象

$CertAll=Get-ChildItem -Path Cert:\LocalMachine\My
$CertInUse=Get-Childitem -Path IIS:\SslBindings
$CertSame=Compare-Object -ReferenceObject $CertAll -DifferenceObject $CertInUse -Property ThumbPrint -IncludeEqual -ExcludeDifferent

foreach ($item in $CertSame) {
    # 根据Thumbprint获取单个证书对象
    $targetCert = Get-ChildItem -Path "Cert:\LocalMachine\My\$($item.thumbprint)"
    # 构造自定义输出对象
    [PSCustomObject]@{
        ExpireInDays = ($targetCert.NotAfter - (Get-Date)).Days
    }
    # 在这里添加发送值的逻辑,比如:
    # Send-Notification -Days $($_.ExpireInDays)
}

写法二:沿用管道传递对象

$CertAll=Get-ChildItem -Path Cert:\LocalMachine\My
$CertInUse=Get-Childitem -Path IIS:\SslBindings
$CertSame=Compare-Object -ReferenceObject $CertAll -DifferenceObject $CertInUse -Property ThumbPrint -IncludeEqual -ExcludeDifferent

foreach ($item in $CertSame) {
    # 获取证书对象后通过管道传给Select-Object
    Get-ChildItem -Path "Cert:\LocalMachine\My\$($item.thumbprint)" | 
        Select-Object @{n='ExpireInDays';e={($_.NotAfter - (Get-Date)).Days}}
}

修正点说明

  • 遍历$CertSame集合中的单个条目,确保每次处理单个证书的Thumbprint
  • 针对每个获取到的证书对象($targetCert或管道中的$_)计算到期天数,避免引用整个集合
  • 明确构造输出对象或通过管道传递对象,确保Select-Object处理目标证书属性

内容的提问来源于stack exchange,提问作者Alexis ExSL

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 05:40:37