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
错误原因分析
- 路径拼接逻辑错误:
$CertSame是Compare-Object返回的集合,直接取$CertSame.thumbprint会得到一个数组,尽管Get-ChildItem能处理数组路径,但后续循环未正确绑定单个证书对象。 - 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
相关产品推荐
相关产品推荐

