I have asked a question similar to the one I'm about to post. I tried using the solution to create my own version but I've had no success. I have the below script that I have found on another website and it's perfect for what I'm looking for, but rather the output be sent in as the body of the email rather than output to a file. How would I go about doing it? Also if anyone has the patience to explain a little It would be greatly appreciated :).
$a = (netsh dhcp server 172.20.102.1 scope 172.20.104.0 show clients 1)
$lines = #()
foreach ($i in $a){
if ($i -match "\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}"){
If ($i -match "[0-9a-f]{2}[:-][0-9a-f]{2}[:-][0-9a-f]{2}[:-][0-9a-f]{2}[:-][0-9a-f]{2}[:-][0-9a-f]{2}"){
$lines += $i.Trim()
}
}
}
$csvfile = #()
foreach ($l in $lines){
$Row = "" | select Hostname,IP
$l = $l -replace '[0-9a-f]{2}[:-][0-9a-f]{2}[:-][0-9a-f]{2}[:-][0-9a-f]{2}[:-][0-9a-f]{2}[:-][0-9a-f]{2}', ''
$l = $l -replace ' - ',','
$l = $l -replace '\s{4,}',''
$l = $l -replace '--','-'
$l = $l -replace '-D-','-'
$l = $l -replace '[-]{1}\d{1,2}[/]\d{1,2}[/]\d{4}',''
$l = $l -replace '\d{1,2}[:]\d{2}[:]\d{2}',''
$l = $l -replace 'AM',''
$l = $l -replace 'PM',''
$l = $l -replace '\s{1}',''
$l = $l + "`n"
$l = $l -replace '[,][-]',','
$Row.IP = ($l.Split(","))[0]
#Subnet mask not used, but maybe later
#$Row.SubNetMask = ($l.Split(","))[1]
$Row.Hostname = ($l.Split(","))[2]
$csvfile += $Row
}
$csvfile | sort-object Hostname | Export-Csv "Out_List.csv"
$a = "<style>"
$a = $a + "body {margin: 10px; width: 600px; font-family:arial; font-size: 12px;}"
$a = $a + "TABLE{border-width: 1px;border-style: solid;border-color: black;border-collapse: collapse;}"
$a = $a + "TH{border-width: 1px;padding: 2px;border-style: solid;border-color: black;background-color: rgb(179,179,179);align='left';}"
$a = $a + "TD{border-width: 1px;padding: 2px;border-style: solid;border-color: black;background-color: white;}"
$a = $a + "</style>"
$html = $csvfile | sort-object Hostname | ConvertTo-HTML | out-string
Send-MailMessage -SmtpServer "exchange" -Body $html -BodyAsHtml -From "DHCP#.com.au" -To "#.com.au" -Subject "DHCP Report"
Thanks in advance,
Daniel
As an addition to #Tim's answer:
you can even add CSS to the converted html like this :
$style = #"
<style>
table {
width: 50%;
margin: auto;
border-collapse: collapse;
}
th, td {
text-align: left;
padding: 8px;
border-bottom: 1px solid #fff;
}
tr:nth-child(even){background-color: #f2f2f2}
th {
background-color: #4CAF50;
color: white;
}
</style>
"#
$html =import-Csv "Out_List.csv" |ConvertTo-Html -head $style |out-string
Could you try:
$html = $csvfile | sort-object Hostname | ConvertTo-HTML | out-string
Send-MailMessage -SmtpServer "mail server" -Body $html -BodyAsHtml -From "noreply#mailserver.com.au" -To "me#mailserver.com" -Subject "DHCP Report"
Thanks, Tim.
Related
I need to get the email alert with the event ID 4202, 4204, 4206, 4208, 4212 for the past 24 hrs, from multiple servers.
How can I get that using the Powershell like below which is working for a local computer only?
Script:
$HtmlHead = #"
<style>
body {
font-family: Arial;
}
table {
width: 100%;
border-collapse: collapse;
border: 1px solid;
}
th {
background-color: green;
border: 1px solid;
padding: 1px;
}
td {
border: 1px solid;
padding: 1px;
}
</style>
"#
$mailArgs = #{
SmtpServer = 'mail.domain.com'
From = 'SystemAdmin#domain.com'
To = 'Manager#domain.com'
Subject = '{0} DFS report'
Attachments = 'C:\Logs\DFS-Events_{0}.csv'
}
$EventIDs = 4202, 4204, 4206, 4208, 4212
Get-DfsrMember | Select-Object -ExpandProperty ComputerName -Unique | Sort-Object | ForEach-Object {
Write-Host "Processing $($_) ..."
Try
{
$splat = $mailArgs.psobject.Copy()
$splat['Attachments'] = $splat['Attachments'] -f $_
Get-WinEvent -FilterHashTable #{ LogName = 'System'; StartTime = (Get-Date).AddHours(-24); ID = $EventIDs } |
Select-Object -Property TimeCreated, Id, Message |
Sort-Object -Property TimeCreated |
Export-Csv -NoTypeInformation -UseCulture -Path $splat['Attachments']
$splat['Body'] = "$($_) DFS Replication Related Events | ForEach-Object { "$($upTime.$_) $_" })"
}
Catch
{
Write-Error -ErrorRecord $_
$splat['Body'] = "$($_) query failed:`r`n$($_.Exception.Message)"
$splat.Remove('Attachments')
}
# Send the result for each server as email
$splat['Subject'] = $splat['Subject'] -f $_
Send-MailMessage #splat
}
I think you'll just need a second loop to go through all computers.
Change
$ComputerName = Get-DfsrMember | ...
into
$computers = Get-DfsrMember | ...
and then wrap your ForEach ( $LogType in $Logs ) { ... } loop inside another loop like
foreach ( $computerName in $computers ) {
foreach ( $LogType in $Logs ) {
..
}
}
P.S. I like to write lowercase for foreach ($thingy in $collection) {} and use camel-case in $collection | ForEach-Object {} to help visualizing the difference between the two
As per your comment, the results should also be in a HTML table for email.
For that, add BodyAsHtml = $true in your $mailArgs hashtable and Capture the results from the Get-WinEvent call so you can export to CSV and afterwards convert to a nice HTML table.
Your code slighlty adjusted for this:
$HtmlHead = #"
<style>
body {
font-family: Arial;
}
table {
width: 100%;
border-collapse: collapse;
border: 1px solid;
}
th {
background-color: green;
border: 1px solid;
padding: 1px;
}
td {
border: 1px solid;
padding: 1px;
}
</style>
"#
$mailArgs = #{
SmtpServer = 'mail.domain.com'
From = 'SystemAdmin#domain.com'
To = 'Manager#domain.com'
Subject = '{0} DFS report'
Attachments = 'C:\Logs\DFS-Events_{0}.csv'
BodyAsHtml = $true
}
$EventIDs = 4202, 4204, 4206, 4208, 4212
Get-DfsrMember | Select-Object -ExpandProperty ComputerName -Unique | Sort-Object | ForEach-Object {
Write-Host "Processing $($_) ..."
Try
{
$splat = $mailArgs.psobject.Copy()
$splat['Attachments'] = $splat['Attachments'] -f $_
$result = Get-WinEvent -FilterHashTable #{ LogName = 'System'; StartTime = (Get-Date).AddHours(-24); ID = $EventIDs } -ErrorAction Stop |
Select-Object -Property TimeCreated, Id, Message |
Sort-Object -Property TimeCreated
# export to csv file
$result | Export-Csv -NoTypeInformation -UseCulture -Path $splat['Attachments']
# create the HTML body
$splat['Body'] = ($result | ConvertTo-Html -Head $HtmlHead -PreContent "<h3>$($_) DFS Replication Related Events</h3>")
}
Catch
{
Write-Error -ErrorRecord $_
# don't forget you're sending HTML, so use "<br />" instead of "`r`n"
$splat['Body'] = "$($_) query failed:<br />$($_.Exception.Message)"
$splat.Remove('Attachments')
}
# Send the result for each server as email
$splat['Subject'] = $splat['Subject'] -f $_
Send-MailMessage #splat
}
Write-Output $details gives the output as a table, I want that output in my email, but when I add it to body part it throws me an error:
Cannot validate argument on parameter 'Body'. The argument is null or empty. Provide an argument that is not null or empty, and then try the command again
$date = Get-Date -DisplayHint Date -UFormat "%d/%m/%Y"
$time = Get-Date -DisplayHint Time
$ThresholdFileCount = 1
$smtp = "address"
$to = "ok#mail.com"
$from = "abc#def.com"
$subject = "Number of files is above threshold - $date"
$style = "<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;}
</style>"
function filecount {
param ([string]$path)
$body += "<body style='font-family: Cambria; font-size: 16pt;'><b><u><a
name='Monitor'>Monitor</a></u></b></body><br>"
if (-not (Test-Path $path)) {Throw "Path: $path not found"}
$count = 0
$count = Get-ChildItem -Path $path | where {!$_.PSIsContainer} | Measure-
Object | select -ExpandProperty count
if ($count -gt $ThresholdFileCount) {
$details = Get-Item -Path $path| Select-Object PSDrive, #{N = "Parent"; E =
{($_.PSParentPath -split "FileSystem::")[1]}
}, Name, #{N = "FileCount"; E =
{$count}
}
$body += $details |ConvertTo-Html
Write-Output $details
}
}
Send-MailMessage -FROM $from -To $to -Subject $subject -Body $body BodyAsHtml -Priority High -SmtpServer $smtp
filecount "address"
So, here's my issue... I have the below PowerShell script that I want to use to do the following:
Pull Each Hyper-V cluster member (currently 29 x Server 2016 nodes)
Run a ForEach loop on each node to get all VMs that have Hyper-V replication enabled.
Combine all 29 outputs into a single .html file with table formatting.
Here is the code:
$Cluster = Get-ClusterNode -Cluster hv-cluster01.contoso.com
$a = "<style>"
$a = $a + "BODY{background-color:peachpuff;}"
$a = $a + "TABLE{border-width: 1px;border-style: solid;border-color: black;border-collapse: collapse;}"
$a = $a + "TH{column-width: 200px;border-width: 1px;padding: 8px;border-style: solid;border-color: black;background-color:thistle}"
$a = $a + "TD{column-width: 200px;border-width: 1px;padding: 3px;border-style: solid;border-color: black;background-color:PaleGoldenrod;text-align: center}"
$a = $a + "</style>"
ForEach ($Node in $Cluster)
{
Get-VMReplication -ComputerName $Node | Select-Object VMName, State, Health, PrimaryServer | ConvertTo-HTML -head $a -body "<H2>DR Replication Status</H2>" | Out-File C:\Scripts\Test.htm
}
My ultimate goal would be to put this into a scheduled task to run 2-3 times per day, and using Send-MailMessage, send the html content in the body of an eamil, to myself and others on my team.
I appreciate any help I can get.
In your code, you convert and output the object for each $Node in $Cluster. Instead you first have to populate your final object, which contains all information, and then convert and output these information.
You do so, by moving the convert and output part outside the loop. For example:
$Cluster = Get-ClusterNode -Cluster hv-cluster01.contoso.com
$a = "<style>"
$a = $a + "BODY{background-color:peachpuff;}"
$a = $a + "TABLE{border-width: 1px;border-style: solid;border-color: black;border-collapse: collapse;}"
$a = $a + "TH{column-width: 200px;border-width: 1px;padding: 8px;border-style: solid;border-color: black;background-color:thistle}"
$a = $a + "TD{column-width: 200px;border-width: 1px;padding: 3px;border-style: solid;border-color: black;background-color:PaleGoldenrod;text-align: center}"
$a = $a + "</style>"
$Report = ForEach ($Node in $Cluster) {
Get-VMReplication -ComputerName $Node | Select-Object VMName, State, Health, PrimaryServer
}
$Report | ConvertTo-HTML -head $a -body "<H2>DR Replication Status</H2>" | Out-File C:\Scripts\Test.htm
I've modified the script quite a bit more, to accommodate the rest of what I was trying to do...
I've managed to get the script to pull the content of the HTML file and place it into an email message. My problem is, some of the table style info isn't transferring to the email. Specifically, the column-width part. So all of the table entries are squished together. See below:
Remove-Item C:\Scripts\ReplicationHealth.htm
$Cluster = Get-ClusterNode -Cluster hv-cluster01.contoso.com
$a = "<style>"
$a = $a + "BODY{background-color:LightGrey;}"
$a = $a + "TABLE{border-width: 1px;border-style: solid;border-color: black;border-collapse: collapse;}"
$a = $a + "TH{column-width: 200px;border-width: 1px;padding: 8px;border-style: solid;border-color: black;background-color:DodgerBlue}"
$a = $a + "TD{column-width: 200px;border-width: 1px;padding: 3px;border-style: solid;border-color: black;background-color:PapayaWhip;text-align: center}"
$a = $a + "</style>"
$Report = ForEach ($Node in $Cluster) {
Get-VMReplication -ComputerName $Node | Select-Object VMName, State, Health, PrimaryServer
}
$time = Get-Date -Format G
$Report | ConvertTo-HTML -head $a -body "<H2>Hyper-V Replication Status</H2>", $time | Out-File C:\Scripts\ReplicationHealth.htm
$MailBody = Get-Content C:\Scripts\ReplicationHealth.htm -Raw
Send-MailMessage -SmtpServer "SERVERIP" -From "HyperV-Replication#contoso.com" -To "User#contoso.com" -Subject "Hyper-V Replication Status" -Body $MailBody -BodyAsHtml
A tiny bit more help would be awesome!
Thanks in advance!
Hello newish to PS and i am having an issue getting the Output data to output.
The HTM file is created but no data, what am I missing here, again im newish!
This is to check TSM backup report and to start service if down.
Here is the script
$serverlist = gc servers.txt
$SvcName = '*tsm*scheduler*'
$filepath = "C:\Scripts\"
$date = "{0:yyy_MM_dd-HH_mm}" -f (get-date)
$file = $filepath + "Results_" + $date + ".htm"
New-Item $filepath -type directory -force -Verbose
$Header = #"
<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;}
</style>
<title>
TSM Report
</title>
"#
ForEach ($server in $serverlist)
{
$Tsm = Get-Service -ComputerName $server| Where {$_.name -Like $SvcName}
If ($Tsm.StartType -ne 'Automatic')
{
Set-Service -InputObject $Tsm -StartupType Automatic
}
If ($Tsm.Status -ne 'Running')
{
$output = "Starting the service."
Start-Service -InputObject $Tsm
}
$Tsm2 = Get-Service -ComputerName $SysName | Where {$_.name -Like $SvcName}
}
$pre= "Here are the results for $date"
$Tsm2 | Select-Object DisplayName, Status, StartupType | ConvertTo-HTML -Head $Header -PreContent $pre | Out-File $file
Invoke-Item $file
I am trying to fetch the details of current connection for website hosted in IIS. I tried bit of coding and generated below snippet. With below code I am getting the data successfully but I want to see
server name ,
current connection and site name only in the HTML result. As of now what I am getting is below:-
\servername1\web service(sitename)\current connections : 59
\servername2\web service(sitename)\current connections : 81.
This is quite hard for other people to read out the report correctly. Can someone help me here to get the better HTML report consisting of sitename/servername/current connections/timestamp. Below is code snippet
$a = "<style>"
$a = $a + "BODY{background-color:peachpuff;}"
$a = $a + "TABLE{border-width: 1px;border-style: solid;border-color: black;border-collapse: collapse;}"
$a = $a + "TH{border-width: 1px;padding: 0px;border-style: solid;border-color: black;}"
$a = $a + "TD{border-width: 1px;padding: 0px;border-style: solid;border-color: black;}"
$a = $a + "</style>"
import-module webadministration
$sitename = dir IIS:\Sites | Select Name
function get-CurrentConnection($Site) {
Get-Counter "web service($Site)\current connections" -ComputerName (Get-Content C:\server1.txt)
}
$CurrentConnection = #()
foreach ($Site in $SiteName)
{
#Write-Host $Site
$CC = get-CurrentConnection -Site $Site.name |Select Readings,Timestamp
$CurrentConnection += $cc
}
$CurrentConnection | ConvertTo-Html -head $a |out-file C:\report.htm
Invoke-Expression "C:\report.htm"
I don't know what fields are in your object, but you should be able to adapt this to your code to get the desired output.
Create the [pscustomobject] inside your loop accordingly and add to your $CurrentConnection array.
$a = "<style>"
$a = $a + "BODY{background-color:peachpuff;}"
$a = $a + "TABLE{border-width: 1px;border-style: solid;border-color: black;border-collapse: collapse;}"
$a = $a + "TH{border-width: 1px;padding: 0px;border-style: solid;border-color: black;}"
$a = $a + "TD{border-width: 1px;padding: 0px;border-style: solid;border-color: black;}"
$a = $a + "</style>"
$CurrentConnection = #()
$data = [pscustomobject]#{
"site" = "sitename1"
"server" = "servername1"
"connections" = "123"
"date" = (Get-Date)
}
$CurrentConnection += $data
$data = [pscustomobject]#{
"site" = "sitename2"
"server" = "servername2"
"connections" = "456"
"date" = (Get-Date)
}
$CurrentConnection += $data
$CurrentConnection | ConvertTo-Html -Head $a | Out-File d:\test\foo.htm
Invoke-Item d:\test\foo.htm