Last active
July 4, 2018 00:18
-
-
Save theagreeablecow/3682550 to your computer and use it in GitHub Desktop.
SysAdmin Modular Reporting (SAMReports)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
############################################################################################################ | |
# Global Variables # | |
#------------------------ | |
# Email Variables | |
$SmtpServer = "exchange.mydomain.com.au" | |
$EmailFrom = "[email protected]" | |
$EmailTo = "[email protected]" | |
$EmailSubject = "SysAdmin Modular Report for $module $($Date)" | |
# Report HTML Formatting | |
$DefaultBannerColour = "848284" | |
$BannerTxtColour = "FFFFFF" | |
$BannerTxtSize = "18pt" | |
$DefaultTitleColour = "D4DBDC" | |
$GoodTitleColour = "4EA846" | |
$WarningTitleColour = "FFB901" | |
$AlertTitleColour = "BD1917" | |
$TitleTxtColour = "FFFFFF" | |
$DefaultCommentColour = "F3F4F4" | |
$TableTxtColour = "000000" | |
$TableTxtSize = "10pt" | |
# Report Variables | |
$ReportTitle = $EmailSubject | |
$ReportSubTitle = "Created by <a href='sip:[email protected]' target='_blank'>The Agreeable Cow</a>, generated on $($ENV:Computername)." | |
#Environment Variables | |
$ScriptComputer = ($ENV:Computername) | |
$ScriptUser = ($ENV:Username) | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
############################################################################################################ | |
# HTML Styles # | |
#------------------------ | |
$DspHeader0 = " | |
BORDER-RIGHT: #bbbbbb 1px solid; | |
PADDING-RIGHT: 0px; | |
BORDER-TOP: #bbbbbb 1px solid; | |
DISPLAY: block; | |
PADDING-LEFT: 0px; | |
FONT-WEIGHT: bold; | |
FONT-SIZE: $($TableTxtSize); | |
MARGIN-BOTTOM: -1px; | |
MARGIN-LEFT: 0px; | |
BORDER-LEFT: #bbbbbb 1px solid; | |
COLOR: #$($BannerTxtColour); | |
MARGIN-RIGHT: 0px; | |
PADDING-TOP: 4px; | |
BORDER-BOTTOM: #bbbbbb 1px solid; | |
FONT-FAMILY: Tahoma; | |
POSITION: relative; | |
HEIGHT: 2.25em; | |
WIDTH: 95%; | |
TEXT-INDENT: 10px; | |
BACKGROUND-COLOR: #$($ReportBannerColour); | |
" | |
$DspHeader1 = " | |
BORDER-RIGHT: #bbbbbb 1px solid; | |
PADDING-RIGHT: 0px; | |
BORDER-TOP: #bbbbbb 1px solid; | |
DISPLAY: block; | |
PADDING-LEFT: 0px; | |
FONT-WEIGHT: bold; | |
FONT-SIZE: $($TableTxtSize); | |
MARGIN-BOTTOM: -1px; | |
MARGIN-LEFT: 0px; | |
BORDER-LEFT: #bbbbbb 1px solid; | |
COLOR: #$($TitleTxtColour); | |
MARGIN-RIGHT: 0px; | |
PADDING-TOP: 4px; | |
BORDER-BOTTOM: #bbbbbb 1px solid; | |
FONT-FAMILY: Tahoma; | |
POSITION: relative; | |
HEIGHT: 2.25em; | |
WIDTH: 95%; | |
TEXT-INDENT: 10px; | |
BACKGROUND-COLOR: #$($DefaultTitleColour); | |
" | |
$DspHeaderGood = " | |
BORDER-RIGHT: #bbbbbb 1px solid; | |
PADDING-RIGHT: 0px; | |
BORDER-TOP: #bbbbbb 1px solid; | |
DISPLAY: block; | |
PADDING-LEFT: 0px; | |
FONT-WEIGHT: bold; | |
FONT-SIZE: $($TableTxtSize); | |
MARGIN-BOTTOM: -1px; | |
MARGIN-LEFT: 0px; | |
BORDER-LEFT: #bbbbbb 1px solid; | |
COLOR: #$($TitleTxtColour); | |
MARGIN-RIGHT: 0px; | |
PADDING-TOP: 4px; | |
BORDER-BOTTOM: #bbbbbb 1px solid; | |
FONT-FAMILY: Tahoma; | |
POSITION: relative; | |
HEIGHT: 2.25em; | |
WIDTH: 95%; | |
TEXT-INDENT: 10px; | |
BACKGROUND-COLOR: #$($GoodTitleColour); | |
" | |
$DspHeaderWarning = " | |
BORDER-RIGHT: #bbbbbb 1px solid; | |
PADDING-RIGHT: 0px; | |
BORDER-TOP: #bbbbbb 1px solid; | |
DISPLAY: block; | |
PADDING-LEFT: 0px; | |
FONT-WEIGHT: bold; | |
FONT-SIZE: $($TableTxtSize); | |
MARGIN-BOTTOM: -1px; | |
MARGIN-LEFT: 0px; | |
BORDER-LEFT: #bbbbbb 1px solid; | |
COLOR: #$($TitleTxtColour); | |
MARGIN-RIGHT: 0px; | |
PADDING-TOP: 4px; | |
BORDER-BOTTOM: #bbbbbb 1px solid; | |
FONT-FAMILY: Tahoma; | |
POSITION: relative; | |
HEIGHT: 2.25em; | |
WIDTH: 95%; | |
TEXT-INDENT: 10px; | |
BACKGROUND-COLOR: #$($WarningTitleColour); | |
" | |
$DspHeaderAlert = " | |
BORDER-RIGHT: #bbbbbb 1px solid; | |
PADDING-RIGHT: 0px; | |
BORDER-TOP: #bbbbbb 1px solid; | |
DISPLAY: block; | |
PADDING-LEFT: 0px; | |
FONT-WEIGHT: bold; | |
FONT-SIZE: $($TableTxtSize); | |
MARGIN-BOTTOM: -1px; | |
MARGIN-LEFT: 0px; | |
BORDER-LEFT: #bbbbbb 1px solid; | |
COLOR: #$($TitleTxtColour); | |
MARGIN-RIGHT: 0px; | |
PADDING-TOP: 4px; | |
BORDER-BOTTOM: #bbbbbb 1px solid; | |
FONT-FAMILY: Tahoma; | |
POSITION: relative; | |
HEIGHT: 2.25em; | |
WIDTH: 95%; | |
TEXT-INDENT: 10px; | |
BACKGROUND-COLOR: #$($AlertTitleColour); | |
" | |
$dspcomments = " | |
BORDER-RIGHT: #bbbbbb 1px solid; | |
PADDING-RIGHT: 0px; | |
BORDER-TOP: #bbbbbb 1px solid; | |
DISPLAY: block; | |
PADDING-LEFT: 0px; | |
FONT-WEIGHT: bold; | |
FONT-SIZE: $($TableTxtSize); | |
MARGIN-BOTTOM: -1px; | |
MARGIN-LEFT: 0px; | |
BORDER-LEFT: #bbbbbb 1px solid; | |
COLOR: #$($TitleTxtColour); | |
MARGIN-RIGHT: 0px; | |
PADDING-TOP: 4px; | |
BORDER-BOTTOM: #bbbbbb 1px solid; | |
FONT-FAMILY: Tahoma; | |
POSITION: relative; | |
HEIGHT: 2.25em; | |
WIDTH: 95%; | |
TEXT-INDENT: 10px; | |
COLOR: #000000; | |
FONT-STYLE: ITALIC; | |
FONT-WEIGHT: normal; | |
FONT-SIZE: $($TableTxtSize); | |
BACKGROUND-COLOR: #$($DefaultCommentColour) | |
" | |
$filler = " | |
BORDER-RIGHT: medium none; | |
BORDER-TOP: medium none; | |
DISPLAY: block; | |
BACKGROUND: none transparent scroll repeat 0% 0%; | |
MARGIN-BOTTOM: -1px; | |
FONT: 100%/8px Tahoma; | |
MARGIN-LEFT: 43px; | |
BORDER-LEFT: medium none; | |
COLOR: #ffffff; | |
MARGIN-RIGHT: 0px; | |
PADDING-TOP: 4px; | |
BORDER-BOTTOM: medium none; | |
POSITION: relative | |
" | |
$dspcont =" | |
BORDER-RIGHT: #bbbbbb 1px solid; | |
BORDER-TOP: #bbbbbb 1px solid; | |
PADDING-LEFT: 0px; | |
FONT-SIZE: $($TableTxtSize); | |
MARGIN-BOTTOM: -1px; | |
PADDING-BOTTOM: 5px; | |
MARGIN-LEFT: 0px; | |
BORDER-LEFT: #bbbbbb 1px solid; | |
WIDTH: 95%; | |
COLOR: #000000; | |
MARGIN-RIGHT: 0px; | |
PADDING-TOP: 4px; | |
BORDER-BOTTOM: #bbbbbb 1px solid; | |
FONT-FAMILY: Tahoma; | |
POSITION: relative; | |
BACKGROUND-COLOR: #f9f9f9 | |
" | |
############################################################################################################ | |
# Style Sheet Functions # | |
#------------------------ | |
# Functions Credit to Alan Renouf http://virtu-al.net vCheck | |
Function Get-CustomHeader0 ($Title){ | |
$Report = @" | |
<div style="margin: 0px auto;"> | |
<h1 style="$($DspHeader0)">$($Title)</h1> | |
<div style="$($filler)"></div> | |
"@ | |
Return $Report | |
} | |
Function Get-CustomHeader ($Title, $Cmnt, $Alert){ | |
if ($Alert -eq "Good") { | |
$Report = @" | |
<h2 style="$($DspHeaderGood)">$($Title)</h2> | |
"@ | |
} | |
elseif ($Alert -eq "Warning") { | |
$Report = @" | |
<h2 style="$($DspHeaderWarning)">$($Title)</h2> | |
"@ | |
} | |
elseif ($Alert -eq "Alert") { | |
$Report = @" | |
<h2 style="$($DspHeaderAlert)">$($Title)</h2> | |
"@ | |
} | |
else { | |
$Report = @" | |
<h2 style="$($dspheader1)">$($Title)</h2> | |
"@ | |
} | |
If ($Cmnt) { | |
$Report += @" | |
<div style="$($dspcomments)">$($Cmnt)</div> | |
"@ | |
} | |
$Report += @" | |
<div style="$($dspcont)"> | |
"@ | |
Return $Report | |
} | |
Function Get-CustomHeaderClose ($Footer){ | |
$Report = @" | |
</DIV> | |
<div style="$($filler)">$($Footer)</div> | |
"@ | |
Return $Report | |
} | |
Function Get-CustomHeader0Close{ | |
$Report = @" | |
</DIV> | |
"@ | |
Return $Report | |
} | |
Function Get-CustomHTMLClose{ | |
$Report = @" | |
</div> | |
</body> | |
</html> | |
"@ | |
Return $Report | |
} | |
Function Get-ReportHeaderHTML ($Header){ | |
$Report = @" | |
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd"> | |
<html><head><title>$($Header)</title> | |
<META http-equiv=Content-Type content='text/html; charset=windows-1252'> | |
<style type="text/css"> | |
TABLE { | |
TABLE-LAYOUT: fixed; | |
font-family: Tahoma; | |
font-size:$($TableTxtSize); | |
WIDTH: 100% | |
} | |
* | |
{ | |
margin:0 | |
} | |
.pageholder { | |
margin: 0px auto; | |
} | |
td { | |
VERTICAL-ALIGN: TOP; | |
FONT-FAMILY: Tahoma | |
} | |
th { | |
VERTICAL-ALIGN: TOP; | |
COLOR: #$($TableTxtColour); | |
TEXT-ALIGN: left | |
} | |
</style> | |
</head> | |
<body margin-left: 4pt; margin-right: 4pt; margin-top: 6pt;> | |
<div style="font-family:Arial, Helvetica, sans-serif; font-size:$($BannerTxtSize); font-weight:bolder; background-color: ##BANNER_MARKER#;"><center> | |
<p class="accent"> | |
<H1><FONT COLOR= $($BannerTxtColour)>$($ReportTitle)</Font></H1> | |
</p> | |
</center></div> | |
<div style="font-family:Arial, Helvetica, sans-serif; font-size:14px; font-weight:bold;"><center>$($ReportSubTitle) | |
</center></div> | |
"@ | |
Return $Report | |
} | |
Function Get-HTMLTable { | |
param([array]$Data) | |
$HTMLTable = $Data | ConvertTo-Html -Fragment | |
$HTMLTable = $HTMLTable -Replace '<TABLE>', '<TABLE><style>tr:nth-child(even) { background-color: #e5e5e5; TABLE-LAYOUT: Fixed; FONT-SIZE: 100%; WIDTH: 100%}</style>' | |
$HTMLTable = $HTMLTable -Replace '<td>', '<td style= "FONT-FAMILY: Tahoma; FONT-SIZE: $($TableTxtSize);">' | |
$HTMLTable = $HTMLTable -Replace '<th>', '<th style= "COLOR: #$($DefaultBannerColour); FONT-FAMILY: Tahoma; FONT-SIZE: $($TableTxtSize);">' | |
$HTMLTable = $HTMLTable -replace '<', "<" | |
$HTMLTable = $HTMLTable -replace '>', ">" | |
Return $HTMLTable | |
} | |
Function Get-HTMLText ($OutText){ | |
$Report = @" | |
<TABLE> | |
<tr> | |
$OutText | |
</tr> | |
</TABLE> | |
"@ | |
Return $Report | |
} | |
Function Get-HTMLTable { | |
param([array]$OutData) | |
$HTMLTable = $OutData | ConvertTo-Html -Fragment | |
$HTMLTable = $HTMLTable -Replace '<TABLE>', '<TABLE><style>tr:nth-child(even) { background-color: #e5e5e5; TABLE-LAYOUT: Fixed; FONT-SIZE: 100%; WIDTH: 100%}</style>' | |
$HTMLTable = $HTMLTable -Replace '<td>', '<td style= "FONT-FAMILY: Tahoma; FONT-SIZE: $($TableTxtSize);">' | |
$HTMLTable = $HTMLTable -Replace '<th>', '<th style= "COLOR: #$($ReportBannerColour); FONT-FAMILY: Tahoma; FONT-SIZE: $($TableTxtSize);">' | |
$HTMLTable = $HTMLTable -replace '<', "<" | |
$HTMLTable = $HTMLTable -replace '>', ">" | |
Return $HTMLTable | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
############################################################################################################ | |
# Manage Credentials # | |
#------------------------ | |
function Get-MyCredential | |
{ | |
param( | |
$CredPath, | |
[switch]$Help | |
) | |
$HelpText = @" | |
Get-MyCredential | |
Usage: | |
Get-MyCredential -CredPath <[CredPath]> | |
eg $Credentials = Get-MyCredential (join-path ($ScriptPath) Syncred.xml) | |
If a credential is stored in $CredPath, it will be used. | |
If no credential is found, Export-Credential will start and offer to | |
Store a credential at the location specified. | |
"@ | |
if($Help -or (!($CredPath))){write-host $Helptext; Break} | |
if (!(Test-Path -Path $CredPath -PathType Leaf)) { | |
Export-Credential (Get-Credential) $CredPath | |
} | |
$cred = Import-Clixml $CredPath | |
$cred.Password = $cred.Password | ConvertTo-SecureString | |
$Credential = New-Object System.Management.Automation.PsCredential($cred.UserName, $cred.Password) | |
Return $Credential | |
} | |
function Export-Credential($cred, $path) { | |
$cred = $cred | Select-Object * | |
$cred.password = $cred.Password | ConvertFrom-SecureString | |
$cred | Export-Clixml $path | |
} | |
############################################################################################################ | |
# Veeam Functions # | |
#------------------------ | |
# Functin credit to ThomasMc http://vpowercli.wordpress.com/2012/01/23/vpowercli-v6-army-report/ | |
function Get-vPCRepoInfo { | |
[CmdletBinding()] | |
param ( | |
[Parameter(Position=0, ValueFromPipeline=$true)] | |
[PSObject[]]$Repository | |
) | |
Begin { | |
$outputAry = @() | |
[Reflection.Assembly]::LoadFile("C:\Program Files\Veeam\Backup and Replication\Veeam.Backup.Common.dll") | Out-Null | |
function Build-Object {param($name, $path, $free, $total) | |
$repoObj = New-Object -TypeName PSObject -Property @{ | |
Target = $name | |
Storepath = $path | |
StorageFree = [Math]::Round([Decimal]$free/1GB,2) | |
StorageTotal = [Math]::Round([Decimal]$total/1GB,2) | |
FreePercentage = [Math]::Round(($free/$total)*100) | |
} | |
return $repoObj | Select Target, Storepath, StorageFree, StorageTotal, FreePercentage | |
} | |
} | |
Process { | |
foreach ($r in $Repository) { | |
if ($r.GetType().Name -eq [String]) { | |
$r = Get-VBRBackupRepository -Name $r | |
} | |
if ($r.Type -eq "WinLocal") { | |
$Server = $r.GetHost() | |
$FileCommander = [Veeam.Backup.Core.CRemoteWinFileCommander]::Create($Server.Info) | |
$storage = $FileCommander.GetDrives([ref]$null) | ?{$_.Name -eq $r.Path.Substring(0,3)} | |
$outputObj = Build-Object $r.Name $r.Path $storage.FreeSpace $storage.TotalSpace | |
} | |
elseif ($r.Type -eq "LinuxLocal") { | |
$Server = $r.GetHost() | |
$FileCommander = new-object Veeam.Backup.Core.CSshFileCommander $server.info | |
$storage = $FileCommander.FindDirInfo($r.Path) | |
$outputObj = Build-Object $r.Name $r.Path $storage.FreeSpace $storage.TotalSize | |
} | |
elseif ($r.Type -eq "CifsShare") { | |
$fso = New-Object -Com Scripting.FileSystemObject | |
$storage = $fso.GetDrive($r.Path) | |
$outputObj = Build-Object $r.Name $r.Path $storage.AvailableSpace $storage.TotalSize | |
} | |
$outputAry = $outputAry + $outputObj | |
} | |
} | |
End { | |
$outputAry | |
} | |
} | |
# Functin credit to ThomasMc http://vpowercli.wordpress.com/2012/01/23/vpowercli-v6-army-report/ | |
function Get-vPCReplicaTarget { | |
[CmdletBinding()] | |
param( | |
[Parameter(Position=0)] | |
[String]$Name, | |
[Parameter(Position=1, ValueFromPipeline=$true)] | |
[PSObject[]]$InputObj | |
) | |
BEGIN { | |
$outputAry = @() | |
$dsAry = @() | |
if (($Name -ne $null) -and ($InputObj -eq $null)) { | |
$InputObj = Get-VBRJob -Name $Name | |
} | |
} | |
PROCESS { | |
foreach ($obj in $InputObj) { | |
if (($dsAry -contains $obj.ViReplicaTargetOptions.DatastoreName) -eq $false) { | |
$esxi = $obj.GetTargetHost() | |
$dtstr = $esxi | Find-VBRDatastore -Name $obj.ViReplicaTargetOptions.DatastoreName | |
$objoutput = New-Object -TypeName PSObject -Property @{ | |
Target = $esxi.Name | |
Datastore = $obj.ViReplicaTargetOptions.DatastoreName | |
StorageFree = [Math]::Round([Decimal]$dtstr.FreeSpace/1GB,2) | |
StorageTotal = [Math]::Round([Decimal]$dtstr.Capacity/1GB,2) | |
FreePercentage = [Math]::Round(($dtstr.FreeSpace/$dtstr.Capacity)*100) | |
} | |
$dsAry = $dsAry + $obj.ViReplicaTargetOptions.DatastoreName | |
$outputAry = $outputAry + $objoutput | |
} | |
else { | |
return | |
} | |
} | |
} | |
END { | |
$outputAry | Select Target, Datastore, StorageFree, StorageTotal, FreePercentage | |
} | |
} | |
# Get the current product version of Veeam | |
function Get-VeeamVersion { | |
$veeamExe = Get-Item 'C:\Program Files\Veeam\Backup and Replication\Veeam.Backup.Manager.exe' | |
$VeeamVersion = $veeamExe.VersionInfo.ProductVersion | |
Return $VeeamVersion | |
} | |
############################################################################################################ | |
# Visuals # | |
#------------------------ | |
Function Get-Base64Image ($Path) { | |
$pic = Get-Content $Path -Encoding Byte | |
[Convert]::ToBase64String($pic) | |
} | |
# Function credit to Sean Duffy http://www.simple-talk.com/sysadmin/powershell/building-a-daily-systems-report-email-with-powershell/ | |
# NB Required MS Chart Controls for .NET 3.5 installed (http://www.microsoft.com/en-us/download/details.aspx?id=14422) | |
Function Create-PieChart() { | |
param([string]$FileName) | |
[void][Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") | |
[void][Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms.DataVisualization") | |
#Create chart object | |
$Chart = New-object System.Windows.Forms.DataVisualization.Charting.Chart | |
$Chart.Width = 150 | |
$Chart.Height = 150 | |
$Chart.Left = 1 | |
$Chart.Top = 1 | |
#Create a chartarea to draw on and add this to the chart | |
$ChartArea = New-Object System.Windows.Forms.DataVisualization.Charting.ChartArea | |
$Chart.ChartAreas.Add($ChartArea) | |
[void]$Chart.Series.Add("Data") | |
#Add a datapoint for each value specified in the arguments (args) | |
foreach ($value in $args[0]) { | |
$datapoint = new-object System.Windows.Forms.DataVisualization.Charting.DataPoint(0, $value) | |
$datapoint.AxisLabel = $value | |
$Chart.Series["Data"].Points.Add($datapoint) | |
} | |
# Manually Select Colours | |
#$Colour1 = "#" + $GoodTitleColour | |
#$Colour2 = "#" + $WarningTitleColour | |
#$Colour3 = "#" + $AlertTitleColour | |
#if ($args[0]){ | |
# $datapoint.Color = $Colour1 | |
#} | |
#if ($args[1]){ | |
# $datapoint.Color = $Colour2 | |
#} | |
#if ($args[2]){ | |
# $datapoint.Color = $Colour3 | |
#} | |
$Chart.Series["Data"].ChartType = [System.Windows.Forms.DataVisualization.Charting.SeriesChartType]::Pie | |
$Chart.Series["Data"]["PieLabelStyle"] = "Outside" | |
$Chart.Series["Data"]["PieLineColor"] = "Black" | |
$Chart.Series["Data"]["PieDrawingStyle"] = "Concave" | |
#($Chart.Series["Data"].Points.FindMaxByValue())["Exploded"] = $true | |
#Set the title of the Chart to the current date and time | |
$Title = new-object System.Windows.Forms.DataVisualization.Charting.Title | |
$Chart.Titles.Add($Title) | |
$Chart.Titles[0].Text = "My Pie Chart" | |
#Save the chart to a file | |
$Chart.SaveImage($FileName,"png") | |
} | |
############################################################################################################ | |
# Misc # | |
#--------------------- | |
function Get-DirectoryStats() { | |
param ([string]$root = $(resolve-path .)) | |
Get-ChildItem $root -recurse -force | where { -not $_.PSIsContainer } | measure-object -sum -property Length | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
############################################################################################################ | |
# Info # | |
#------------------------ | |
$Title = "Example Script" | |
$Comment = "This example script shows the top 10 process (by Working set Memory)" | |
$Author = "John Example" | |
$PluginDate = "1/1/2013" | |
$Version = "v1.0" | |
# 1.0 01/01/2013 John Example Original Build | |
############################################################################################################ | |
# Main Script # | |
#------------------------ | |
#Create an Array and run query | |
$ResultsData = @() | |
$Processes = get-process | sort-object ws -descending | select -first 10 | select-object id,Name,ws | |
# Add results into the array | |
foreach ($Process in $Processes){ | |
$obj = New-Object PSobject | |
$Memory = ($Process.WS/1mb) | |
$obj | Add-Member -MemberType NoteProperty -name "Server" -value $($ENV:Computername) | |
$obj | Add-Member -MemberType NoteProperty -name "Process ID" -value $Process.ID | |
$obj | Add-Member -MemberType NoteProperty -name "Process Name" -value $Process.Name | |
$obj | Add-Member -MemberType NoteProperty -name "Memory (WS)" -value $Memory | |
$ResultsData += $obj | |
# Update Text and Alert count based on your criteria | |
if ($Memory -gt 300){ | |
$AlertText += "Alert: High memory usage for " + $Process.name + " </br>" | |
$AlertCount += $AlertCount.count + 1 | |
} | |
elseif ($Memory -gt 150){ | |
$WarningText += "Warning: Moderate memory usage for " + $Process.name + " </br>" | |
$WarningCount += $WarningCount.count + 1 | |
} | |
} | |
# Results Text | |
if ($AlertText -ne $null -or $WarningText -ne $null){ | |
$ResultsText = $AlertText + $WarningText | |
} | |
else{ | |
$ResultsText = "Memory usage normal" | |
} | |
# Results Data | |
$ResultsData = $ResultsData | sort -Property "Name" | |
# Results Alert | |
if ($AlertCount -ge 1){ | |
$ResultsAlert = "Alert" | |
} | |
elseif ($WarningCount -ge 1){ | |
$ResultsAlert = "Warning" | |
} | |
else{ | |
$ResultsAlert = "Good" | |
} | |
############################################################################################################ | |
# Output # | |
#------------------------ | |
$OutText = $ResultsText # $OutText MUST be either $ResultsText or "" Valid $ResultsText is any text string | |
$OutData = $ResultsData # $OutData MUST be either $ResultsData or "" Valid $ResultsData is any data array | |
$OutAlert = $ResultsAlert # $OutAlert MUST be either $ResultsAlert or "" Valid $ResultsAlert are 'Good', 'Warning' or 'Alert' | |
$Attachment = "" # $Attachment MUST be either UNC path or "" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<# | |
.SYNOPSIS | |
The SysAdmin Modular Reporting framework provides flexible data collection and 'traffic light' style alerts for your environment | |
.DESCRIPTION | |
Using a modular plugin system, this report collates information from a series of sub-scripts, specific to the module chosen | |
Get-SAMReport.ps1 This script, used to call all other scripts and join report together | |
\_Assets | |
00_Global_Variables.ps1 Top level variables, applicable for all module sets <- Update this script accordingly | |
01_Global_StyleSheet.ps1 Top level HTML stylesheet, applicable for all module sets | |
02_Global_Functions.ps1 Top level functions, applicable for all module sets | |
Scheduled Task Example.xml Example task that can be imported into Task Scheduler | |
\<module name> | |
00 Module Variables.ps1 Module specific plugins, variables and overrides <- Update this script accordingly | |
01 Example Template.ps1 Get-Process demonstration showing example modular script format | |
\Output All generated output files for this module are saved here | |
\zzz_Ignore Items in here will not be processed or run | |
.USAGE | |
1. Modify the scripts in the Assets folder according to your environment | |
2. This script is currently designed to be run from a server with the relevant module's management tools and powershell plugins installed locally | |
Syntax | |
Get-SAMReport [[-module] <string>] [[-output] <Email/OnScreen>] | |
Example | |
Get-SAMReport Veeam Email | |
Scheduled Task Action settings | |
Start a program: C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe | |
Arguments: -NonInteractive c:\Scripts\SAMReports\Get-SAMReport.ps1 Exchange | |
Start in: c:\Scripts\SAMReports\ | |
3. Ensure script is run manually at least once for each module. You will be prompted for your "Run As" credentials for that module | |
- These will be saved for future (scheduled) use in a hashed xml file. | |
4. Any script in the appropriate format in the module's subfolder will be included in the report | |
- Scripts can be renumbered to define order. Rename the extension or simply move it to the zzz_ignore folder to exclude from report | |
.NOTES | |
Script Name: Get-SAMReport.ps1 | |
Created By: The Agreeable Cow | |
Contact: [email protected] | |
Date: August 2012 | |
.VERSION HISTORY | |
1.0 Aug 2012 The Agreeable Cow Original Build | |
2.0 Jul 2014 The Agreeable Cow Module expansions, customisation features and minor updates | |
.CREDIT | |
Report Stylesheet Alan Renouf http://virtu-al.net (vCheck) | |
Storage Functions ThomasMc http://vpowercli.wordpress.com/2012/01/23/vpowercli-v6-army-report/ | |
License Check Arne Fokkema http://xtravirt.com/powershell-veeam-br-%E2%80%93-get-total-days-before-license%C2%A0expires | |
Charting Sean Duffy http://www.simple-talk.com/sysadmin/powershell/building-a-daily-systems-report-email-with-powershell/ | |
#> | |
#---------------------------------------------------------------------------------------------------------------- | |
# Variables | |
$ScriptPath = (Split-Path ((Get-Variable MyInvocation).Value).MyCommand.Path) + "\" | |
$ModuleArray = @(Get-ChildItem -exclude "_*" | where { $_.PSIsContainer} | ForEach-Object { $_.Name }) | |
$OutputArray=@("OnScreen","Email") | |
$TranscriptLog = $True | |
$Date = get-date -f yyyy-MM-dd | |
#---------------------------------------------------------------------------------------------------------------- | |
# Run SAM Report | |
Function get-SAMReport{ | |
[CmdletBinding()] | |
Param( | |
[Parameter(Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName = $true,Position=0)] | |
[String] $Module="", | |
[Parameter(Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName = $true,Position=1)] | |
[String] $Output="email" | |
) | |
Begin{ | |
#Logging | |
if ($TranscriptLog -eq $True){ | |
$Logfile = $ScriptPath + "SAMReport.log" | |
Start-Transcript -path $Logfile -append | |
} | |
# Assets Folder | |
$AssetsFolder = $ScriptPath + "_Assets\" | |
$Assets = Get-ChildItem -Path $AssetsFolder -filter "*.ps1" | Sort Name | |
Foreach ($Asset in $Assets) { | |
. $Asset.Fullname | |
} | |
# Module Folder | |
$ModulesFolder = $ScriptPath + $module + "\" | |
$Modules = Get-ChildItem -Path $ModulesFolder -filter "*.ps1" | Sort Name | |
# Output Folder | |
$OutputFolder = $ModulesFolder + "Output\" | |
IF (!(TEST-PATH $OutputFolder)) {NEW-ITEM $OutputFolder -type Directory} | |
# Ignore Folder | |
$IgnoreFolder = $ModulesFolder + "zzz_Ignore\" | |
IF (!(TEST-PATH $IgnoreFolder)) {NEW-ITEM $IgnoreFolder -type Directory} | |
# Credentials | |
$Credentials = Get-MyCredential (join-path ($ModulesFolder) ModuleCredentials.xml) | |
} | |
Process{ | |
$OutReport = Get-ReportHeaderHTML "$Module Modular Report" | |
$AllAttachments = @() | |
# Call each plugin | |
Foreach ($script in $Modules) { | |
. $script.Fullname | |
# Footer | |
$OutFooter = "<div style='font-family:Arial, Helvetica, sans-serif; font-size:9px; color:#bbbbbb'>" + $script.name + " " + $Author + " " + $PluginDate + " (" + $Version + ")</br></br>" | |
# Text and Data | |
if ($OutText -AND $OutData) { | |
$OutReport += Get-CustomHeader $Title $Comment $OutAlert | |
$OutReport += Get-HTMLText $OutText | |
$OutReport += "</br>" | |
$OutReport += Get-HTMLTable $OutData | |
$OutReport += Get-CustomHeaderClose $OutFooter | |
} | |
elseif ($OutText) { | |
$OutReport += Get-CustomHeader $Title $Comment $OutAlert | |
$OutReport += Get-HTMLText $OutText | |
$OutReport += Get-CustomHeaderClose $OutFooter | |
} | |
elseif ($OutData) { | |
$OutReport += Get-CustomHeader $Title $Comment $OutAlert | |
$OutReport += Get-HTMLTable $OutData | |
$OutReport += Get-CustomHeaderClose $OutFooter | |
} | |
$OutReport += Get-CustomHeader0Close | |
$OutReport += Get-CustomHTMLClose | |
# Attachments | |
if (!$attachment -eq ""){ | |
$AllAttachments += $Attachment | |
} | |
# Count OutAlerts | |
if ($OutAlert -eq "Good"){ | |
$GoodStatus += $GoodStatus.count + 1 | |
} | |
elseif ($OutAlert -eq "Warning"){ | |
$WarningStatus += $WarningStatus.count + 1 | |
} | |
elseif ($OutAlert -eq "Alert"){ | |
$AlertStatus += $AlertStatus.count + 1 | |
} | |
# Reset Fields | |
$ResultsText = "" | |
$ResultsData = "" | |
$ResultsAlert = "" | |
$OutText = "" | |
$OutData = "" | |
$OutAlert = "" | |
} | |
} | |
End{ | |
# Apply Global Banner Status Colours | |
if ($AlertStatus -ge 1){ | |
$OutReport = $OutReport -replace ("#BANNER_MARKER#",$AlertTitleColour) | |
} | |
elseif ($WarningStatus -ge 1){ | |
$OutReport = $OutReport -replace ("#BANNER_MARKER#",$WarningTitleColour) | |
} | |
else{ | |
$OutReport = $OutReport -replace ("#BANNER_MARKER#",$GoodTitleColour) | |
} | |
# Update Colour Formatting for Text | |
$OutReport = $OutReport -replace ("!GREEN!","<span style='color:green'>") | |
$OutReport = $OutReport -replace ("!ORANGE!","<span style='color:orange'>") | |
$OutReport = $OutReport -replace ("!RED!","<span style='color:red'>") | |
if ($module -eq "Veeam") { | |
$OutReport = $OutReport -replace ("01/01/1900 00:00:00","") | |
$OutReport = $OutReport -replace ("Success:","<span style='color:green'>Success") | |
$OutReport = $OutReport -replace ("InProgress:","<span style='color:orange'>InProgress") | |
$OutReport = $OutReport -replace ("Pending:","<span style='color:orange'>Pending") | |
$OutReport = $OutReport -replace ("Warning:","<span style='color:orange'>Warning") | |
$OutReport = $OutReport -replace ("Error:","<span style='color:red'>Error:") | |
$OutReport = $OutReport -replace ("Unknown:","<span style='color:red'>Unknown:") | |
$OutReport = $OutReport -replace ("Failed","<span style='color:red'>Failed") | |
$OutReport = $OutReport -replace ("Stopped","<span style='color:red'>Stopped") | |
} | |
# Output Report | |
if ($output -eq "OnScreen"){ | |
$Filename = $Env:TEMP + "\" + $Module + "_" + $Date + ".htm" | |
$OutReport | out-file -encoding ASCII -filepath $Filename | |
Invoke-Item $Filename | |
} | |
elseif ($output -eq "Email"){ | |
if ($AllAttachments) { | |
Send-MailMessage -To $EmailTo -From $EmailFrom -Subject $EmailSubject -SmtpServer $SmtpServer -body $OutReport -BodyAsHtml -attachment $AllAttachments | |
} | |
else { | |
Send-MailMessage -To $EmailTo -From $EmailFrom -Subject $EmailSubject -SmtpServer $SmtpServer -body $OutReport -BodyAsHtml | |
} | |
} | |
# Close Log | |
if ($TranscriptLog -eq $True){ | |
Stop-Transcript | |
$Format = Get-Content $Logfile | |
$Format > $Logfile | |
} | |
} | |
} | |
# Module Validation | |
$HelpText = @" | |
Missing or invalid arguments. Correct syntax is Get-SAMReport.ps1 <module> <output> | |
Valid modules are: $ModuleArray | |
Valid outputs are: $OutputArray | |
For example Get-SAMReport.ps1 Exchange OnScreen | |
"@ | |
if ($args[0] -ne $NULL){ | |
$ModuleCheck = $ModuleArray -contains $args[0] | |
if ($ModuleCheck -eq $false){ | |
write-host $HelpText | |
exit | |
} | |
else{ | |
$Module = $args[0] | |
} | |
} | |
else{ | |
write-host $HelpText | |
exit | |
} | |
# Output Validation | |
if ($args[1] -ne $NULL){ | |
$OutputCheck = $OutputArray -contains $args[1] | |
if ($OutputCheck -eq $false){ | |
write-host $HelpText | |
exit | |
} | |
else{ | |
$Output = $args[1] | |
} | |
} | |
else{ | |
$Output = "Email" | |
} | |
get-SAMReport $Module $Output |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="UTF-16"?> | |
<Task version="1.2" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task"> | |
<RegistrationInfo> | |
<Date>2012-11-22T09:58:09.334214</Date> | |
<Author>mydomain\administrator</Author> | |
</RegistrationInfo> | |
<Triggers> | |
<CalendarTrigger> | |
<StartBoundary>2014-08-01T06:00:00</StartBoundary> | |
<Enabled>true</Enabled> | |
<ScheduleByMonth> | |
<DaysOfMonth> | |
<Day>1</Day> | |
</DaysOfMonth> | |
<Months> | |
<January /> | |
<February /> | |
<March /> | |
<April /> | |
<May /> | |
<June /> | |
<July /> | |
<August /> | |
<September /> | |
<October /> | |
<November /> | |
<December /> | |
</Months> | |
</ScheduleByMonth> | |
</CalendarTrigger> | |
</Triggers> | |
<Principals> | |
<Principal id="Author"> | |
<UserId>mydomain\Administrator</UserId> | |
<LogonType>Password</LogonType> | |
<RunLevel>LeastPrivilege</RunLevel> | |
</Principal> | |
</Principals> | |
<Settings> | |
<MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy> | |
<DisallowStartIfOnBatteries>true</DisallowStartIfOnBatteries> | |
<StopIfGoingOnBatteries>true</StopIfGoingOnBatteries> | |
<AllowHardTerminate>true</AllowHardTerminate> | |
<StartWhenAvailable>false</StartWhenAvailable> | |
<RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable> | |
<IdleSettings> | |
<StopOnIdleEnd>true</StopOnIdleEnd> | |
<RestartOnIdle>false</RestartOnIdle> | |
</IdleSettings> | |
<AllowStartOnDemand>true</AllowStartOnDemand> | |
<Enabled>true</Enabled> | |
<Hidden>false</Hidden> | |
<RunOnlyIfIdle>false</RunOnlyIfIdle> | |
<WakeToRun>false</WakeToRun> | |
<ExecutionTimeLimit>PT2H</ExecutionTimeLimit> | |
<Priority>7</Priority> | |
</Settings> | |
<Actions Context="Author"> | |
<Exec> | |
<Command>C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe</Command> | |
<Arguments>C:\Scripts\SAMReports\Get-SAMReport.ps1 MODULE_NAME</Arguments> | |
<WorkingDirectory>C:\Scripts\SAMReports\</WorkingDirectory> | |
</Exec> | |
</Actions> | |
</Task> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment