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

PowerShell服务监控脚本执行正常但邮件无内容问题求助

问题修复:PowerShell邮件内容为空的解决方法

核心问题分析

  1. 参数类型不匹配:New-Email的EmailBody参数定义为PSCustomObject[],但传入的是纯字符串数组($results是存储字符串的ArrayList),ConvertTo-Html处理纯字符串数组时无法生成有效HTML片段,导致邮件内容为空。
  2. HTML构造逻辑错误:你将邮件说明消息放到了ConvertTo-Html的-Head参数中,而-Head仅用于定义HTML头部(如样式),消息内容应该放在HTML主体的前置位置。
  3. 作用域潜在隐患:全局变量$results在函数中修改时,若未明确作用域可能导致值未正确传递(虽你提到CheckServices运行正常,此为优化项)。

具体修复代码

1. 调整CheckServices函数,优化结果存储

将结果存储为自定义对象(方便生成结构化表格),并明确作用域:

Function CheckServices {
    # 初始化结果集合,存储为自定义对象
    $script:results = [System.Collections.ArrayList]@()

    foreach ($server in $computers) {
        foreach ($service in $checklist) {
            try {
                $state = (Invoke-Command -ComputerName $server -ScriptBlock {
                    param ($service)
                    Get-Service -Name $service
                } -ArgumentList $service -Credential $cred -ErrorAction Stop).Status

                switch ($state) {
                    'Running' {
                        $null = $script:results.Add([PSCustomObject]@{
                            服务器 = $server
                            服务名称 = $service
                            状态 = "运行正常"
                            操作 = "无"
                        })
                    }
                    'Stopped' {
                        $null = $script:results.Add([PSCustomObject]@{
                            服务器 = $server
                            服务名称 = $service
                            状态 = "已停止"
                            操作 = "已重启服务"
                        })
                        # 执行服务重启
                        Invoke-Command -ComputerName $server -ScriptBlock {
                            param ($service)
                            Restart-Service -Name $service -ErrorAction Stop
                        } -ArgumentList $service -Credential $cred
                    }
                    $null {
                        $null = $script:results.Add([PSCustomObject]@{
                            服务器 = $server
                            服务名称 = $service
                            状态 = "未找到服务"
                            操作 = "无"
                        })
                    }
                }
            }
            catch {
                $null = $script:results.Add([PSCustomObject]@{
                    服务器 = $server
                    服务名称 = $service
                    状态 = "检查失败"
                    操作 = $_.Exception.Message
                })
                Write-Logfile -ActionType ERROR -Message "检查服务器$server的服务$service失败:$($_.Exception.Message)"
            }
        } 
    }   

    # 调用邮件函数传递结果
    New-Email -EmailBody $script:results -Subject "服务状态报告" -Message "请查看以下服务状态报告。若邮件无结果表格,则夜间无服务异常情况。"
}

2. 修改New-Email函数,修复HTML生成逻辑

调整参数适配、修正HTML构造方式,确保内容正常显示:

Function New-Email {
    Param(
        [Parameter(Mandatory=$false)]
        [string]$Attachment,
        [Parameter(Mandatory=$false)]
        [PSCustomObject[]]$EmailBody,
        [Parameter(Mandatory=$true)]
        [string]$Message,
        [Parameter(Mandatory=$true)]
        [string]$Subject
    )
    try {
        Write-Logfile -ActionType INFO -Message "函数New-Email:尝试发送状态邮件..." 
        $style = @"
<style>
BODY{font-family: Arial; font-size: 10pt;}
TABLE{border: 1px solid black; border-collapse: collapse; margin-top:10px;}
TH{border: 1px solid black; background: #dddddd; padding: 5px;text-align: center;}
TD{border: 1px solid black; padding: 5px;text-align: left;}
</style>
"@

        # 生成结果HTML片段,无结果时显示提示文本
        $BodyResults = if ($EmailBody) {
            $EmailBody | ConvertTo-Html -Fragment | Out-String
        } else {
            "<p>无服务状态异常或检查记录</p>"
        }

        # 构造完整HTML,将消息作为前置内容,样式放入头部
        $Body = ConvertTo-Html -Head $style -PreContent "<p>$Message</p>" -PostContent $BodyResults | Out-String

        # 发送邮件
        $mailParams = @{
            BodyAsHtml = $true
            From = $EmailFrom
            To = $EmailTo
            Subject = $Subject
            Body = $Body
            SmtpServer = $PSEmailServer
        }
        if ($Attachment) {
            $mailParams['Attachments'] = $Attachment
            Send-MailMessage @mailParams
            Write-Logfile -ActionType SUCCESS -Message "函数New-Email:已发送带附件[$Attachment]的状态邮件!"
        } else {
            Send-MailMessage @mailParams
            Write-Logfile -ActionType SUCCESS -Message "函数New-Email:已发送无附件的状态邮件!"
        }
    }
    catch {
        Write-Logfile -ActionType ERROR -Message "函数New-Email:无法发送状态邮件!" 
        Write-Logfile -ActionType ERROR -Message $_.Exception.Message
    }
}

3. 补充全局配置变量

脚本开头需定义以下变量,否则邮件和日志功能会报错:

# 全局配置
$EmailFrom = "你的发件邮箱@域名.com"
$EmailTo = "收件邮箱@域名.com"
$PSEmailServer = "smtp.你的域名.com"
$currentloc = $PSScriptRoot # 日志文件存储路径,也可手动指定如"C:\Logs"
$cred = Get-Credential # 或提前定义远程服务器访问凭据

# 服务器列表
$computers = @(
    "Server01",
    "Server02"
)

# 待检查服务列表
$checklist = @(
    "WinRM",
    "Spooler"
)

额外优化建议

  • 为Invoke-Command添加-ErrorAction Stop,确保捕获远程执行的错误。
  • 可在CheckServices末尾将$results写入日志文件,方便离线排查。

内容的提问来源于stack exchange,提问作者Eddie Bailey

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 15:47:27