Output foreach loop to html - powershell

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!

Related

How to concatenate a value to Select-Object's output

I have a script which finds snapshots that are older than 3 days and below are my code and output. However I want to add a new column for each VM displaying the actual age of that snapshots, say for example 5 days or 4 days. I have tried getting age by subtracting created date from today's date. But I am not sure how to add it as a column to my output.
I used this to calculate age:
$StartDate = Get-Date
$created = Get-VM |
Get-Snapshot |
Where {$_.Created -lt (Get-Date).AddDays(-1)} |
Select-Object Created
$age = New-Timespan -Start $StartDate -End $created
Full code:
Add-PSSnapin VMware.VimAutomation.Core
# HTML formatting
$a = "<style>"
$a = $a + "BODY{background-color:white;}"
$a = $a + "TABLE{border-width: 1px;border-style: solid;border-color: black;border-collapse: collapse;}"
$a = $a + "TH{border-width: 1px;padding: 5px;border-style: solid;border-color: black;foreground-color: black;background-color: LightBlue}"
$a = $a + "TD{border-width: 1px;padding: 5px;border-style: solid;border-color: black;foreground-color: black;background-color: white}"
$a = $a + "</style>"
Connect-VIServer -Server ***** -User ****** -Password ******
# Main section of check
Write-Host "Checking VMs for for snapshots"
$date = Get-Date
$datefile = Get-Date -UFormat '%m-%d-%Y-%H%M%S'
$filename = "C:\Temp\snaps_older_than_3\" + $datefile + ".htm"
$created = Get-VM |
Get-Snapshot |
Where {$_.Created -lt (Get-Date).AddDays(-1)} |
Select-Object Created
$age = New-Timespan -Start $StartDate -End $created
$ss = Get-VM |
Get-Snapshot |
Where {$_.Created -lt (Get-Date).AddDays(-1)} |
Select-Object vm, name, SizeGB, SizeMB, Created, powerstate + $age |
ConvertTo-HTML -Head $a -Body "<H2>VM Snapshot Report </H2>"|
Out-File $filename
Write-Host " Complete " -ForegroundColor Green
Write-Host "Your snapshot report has been saved to:" $filename
$SMTPServer = "*******"
$SMTPPort = 25
$username = "vcenter#mmmm.com"
#Define the receiver of the report
$to = "mmmmm#hcl.com"
$subject = "VM Snapshot Report"
$body = "VM Snapshot Report"
$attachment = New-Object Net.Mail.Attachment($filename)
$message = New-Object System.Net.Mail.MailMessage
$message.Subject = $subject
$message.Body = $body
$message.To.Add($to)
$message.From = $username
$message.Attachments.Add($attachment)
$smtp = New-Object System.Net.Mail.SmtpClient($SMTPServer, $SMTPPort);
$smtp.EnableSSL = $false
$smtp.Send($message)
Write-Host "Mail Sent"
Output:
I want to add a new column named "age".
Use a calculated property:
Get-VM |Select-Object VM,Name,SizeGB,SizeMB,Created,PowerState,#{Name='Age';Expression={New-TimeSpan -Start $StartDate -End $_.Created}}
From the help text for Select-Object:
-Property
Specifies the properties to select. Wildcards are permitted.
The value of the Property parameter can be a new calculated property.
To create a calculated property, use a hash table. Valid keys are:
Name (or Label) <string>
Expression <string> or <script block>

Output to HTML issue

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

Outputting DHCP script into body of email

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.

Powershell Script to fetch Websites current connections Hosted in IIS

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

PowerShell outtput to HTML

Using the following and would like to know how to output the results to HTML file
$Start = (Get-Date).AddMinutes(-5)
$Computername = gc C:\Temp\List.txt
$Events = gc C:\Temp\ErrorCodes.txt
Get-EventLog -AsString -ComputerName $Computername |
ForEach-Object {
# write status info
Write-Progress -Activity "Checking Eventlogs on \\$ComputerName" -Status $_
# get event entries and add the name of the log this came from
Get-EventLog -LogName $_ -EntryType Error, Warning -After $Start -ComputerName $ComputerName -ErrorAction SilentlyContinue |
Add-Member NoteProperty EventLog $_ -PassThru | Where-Object {$Events -contains $_.eventid}
} |
# select the properties for the report
Select-Object EventLog, EventID, TimeGenerated, EntryType, Source, Message
This will get it to print with pretty colors. You can tinker around with it and change whatever you want.
$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;background-color:thistle}"
$a = $a + "TD{border-width: 1px;padding: 0px;border-style: solid;border-color: black;background-color:palegoldenrod}"
$a = $a + "</style>"
$Variable = get-what_I_want
$Variable2 = get-what_I_want
$VariableHTML = $Variable | ConvertTo-HTML -head $a -body "<H2>Title I want</H2>"
$Variable2HTML = $Variable2 | ConvertTo-HTML -head $a -body "<H1>Header One</H1> <H2>Header Two</H2> <H3>Header Three</H3> <p>Paragraph<p/>"
$VariableHTML > C:\PoSH\My_Exported_HTML.html
I added a second variable. As you can see, you can add different levels of headers and a Paragraph. I found this helpful for single line items or if you want a better description.
If I would say: ConvertTo-Html is what you need, than probably that would be enough to add a comment.
Instead I will say: before asking questions outside PowerShell, ask them inside PowerShell first.
Get-Help *html*