我有来自多个 SQL Server 的多个数据库。
我正在尝试使用这些数据库/SQL Server 中的 Powershell 将 SQL 数据输出到 HTML 表,然后发送邮件。我制作的脚本有效,但它会为 html 报告中的每个结果输出多个表格。我想要的是将数据附加到同一个表(只有一个包含所有数据的表)。在如何将数据连接到只有一个表上有点挣扎。
#Set flag to 0 for email notification (if any) $alert= 0 $List = Get-Content -Path "C:\Users\testadmin\Documents\Log\serverlist.txt" Foreach($Server in $ServerList){ $SQL = ($Server -split '=')[0] $ = ($Server -split '=')[1] $Query = "select host, Service, Status from Table with(nolock)" $Value = Invoke-Sqlcmd -ServerInstance $SQL -Database $DB -Query $Query foreach($mylocal in $Value ){ $hostname = $mylocal.host $Service= $mylocal.Service $Status = $mylocal.Status if($Status -ne 'Running'){ $alert= 1 $Body += "<head> <meta http-equiv='Content-Type' content='text/html; charset=iso-8859-1'> <style> TABLE {border-width: 1px; border-style: solid; border-color: black; border-collapse: collapse;} TH {border-width: 1px; padding: 3px; border-style: solid; border-color: black; background-color: #6495ED;} TD {border-width: 1px; padding: 3px; border-style: solid; border-color: black;} table.center { margin-left: auto; margin-right: auto; } </style> <title>Warning</title> </head> <body> <h3>Apps are Stopped !</h3> <h4>Timestamp: $(Get-Date)</h4> <table> <tr> <th>SQL</th> <th>DB</th> <th>Service Status</th> </tr> <tr> <td>$SQL</td> <td>$DB</td> <td>$Status</td> </tr> </table> </body> " } else{ Write-Host ("no alert") } } } if($alert-eq '1'){ $Mail = @{ From = 'testadmin@local.com' To = 'localadmin@local.com' Subject = 'Warning!!' smtpserver = 'myrelay.test.com' Body = $Body BodyAsHtml = $true } Send-MailMessage @Mail }
您需要在循环之外创建基本 html(包含标题/正文/表格标题/表格标题的内容)。在循环中,您只创建表格单元格。
从那里,您构建完整的 HTML。
例子
# Just some data... I used calculated field to have the same field name as you. $Value = Get-Service | Select @{'Name' = 'host' ; 'Expression' = { "localhost" } }, @{'Name' = 'Service' ; 'Expression' = { $_.ServiceName } }, Status $HtmlTemplate = @{ Base_Date_TableLoop = @' <head> <meta http-equiv='Content-Type' content='text/html; charset=iso-8859-1'> <style> TABLE {border-width: 1px; border-style: solid; border-color: black; border-collapse: collapse;} TH {border-width: 1px; padding: 3px; border-style: solid; border-color: black; background-color: #6495ED;} TD {border-width: 1px; padding: 3px; border-style: solid; border-color: black;} table.center { margin-left: auto; margin-right: auto; } </style> <title>Warning</title> </head> <body> <h3>Apps are Stopped !</h3> <h4>Timestamp: {0:Date}</h4> <table> <tr> <th>SQL</th> <th>DB</th> <th>Service Status</th> </tr> {0:TableLoop} </table> </body> '@ TableLoop_SQL_DB_Status = @' <tr> <td>{0}</td> <td>{1}</td> <td>{2}</td> </tr> '@ } $Date = Get-Date $Table = [System.Text.StringBuilder]::new() foreach ($mylocal in $Value ) { $hostname = $mylocal.host $Service = $mylocal.Service $Status = $mylocal.Status $Table.AppendLine(($HtmlTemplate.TableLoop_SQL_DB_Status -f $hostname,$Service,$Status)) | Out-Null } $HtmlBody = $HtmlTemplate.Base_Date_TableLoop.Replace('{0:Date}',$Date).Replace('{0:TableLoop}',$Table.ToString()) $HtmlBody | Out-File 'SomeReport.html'
设计选择
我喜欢将我所有的 html 元素放在一个变量中。在前面的示例中,我曾经$HtmlTemplate存储所有片段。这些作品不打算直接编辑,而是作为我的构建块。
$HtmlTemplate
对于元素本身,我个人喜欢Base_Date_TableLoop在每个下划线划分我需要替换的内容的位置上设置一些东西,这样以后更容易进行替换,而不必考虑去哪里。
Base_Date_TableLoop
补充说明
我将“{0}”与for-f循环片段和基本 html 片段混合使用。这是因为基本 html 包含用于格式运算符的括号,需要将其加倍以使运算符忽略它们。由于我不想随意修改html,所以我使用.Net方法,它可以让我替换我需要的东西,而不必完全修改html。此外,在这里使用,而不是因为后者是正则表达式运算符,我不希望那样。{0:TableLoop}``.replace``{}``-f``.replace``.Replace``-Replace
-f
{0:TableLoop}``.replace``{}``-f``.replace``.Replace``-Replace