This Script generates a dynamic PC Environment Report. The report can include various information from Configuration Manager and Active Directory depending on your needs. There is an option to send this report as a mail to the specified recipient(s).
The information that can be collected from Configuration Manager is:
- Patch Compliance overview showing a given past number of Software Update Groups (default 3 Groups)
- Application categorization showing the number of applications that are either superseeded, without deployment or expired
- Devices categorization showing the number of devices that are active, inactive, obsolete and without a configuration manager client
- Computer reboot overview showing how many computers that have not been rebooted within a given time period (default 5 days)
The information that can be collected from Active Directory:
- Computer password information – how many computers that have and have not changed their computer password within a given time period (default 90 days)
- Operating system Overview – showing how many different Operating System versions that are present in the domain and how many there are of each
<#
.SYNOPSIS
Returns a environment status report within the areas that have been selected as parameters running the report
.DESCRIPTION
Queries the ConfigMgr to get information about applications, devices and software updates. Runs a query towards AD to find information about last computer password change.
These information can be included or excluded using the parameters. All the information gathered from SCCM and AD will then ultamately be sent to the recipients specified in the mail section.
.PARAMETER runAppScan
Scan SCCM for applications to find both used an unused applications
.PARAMETER runClientScan
Scan SCCM Computer Clients to find out how many inactive clients there are
.PARAMETER runPatchCompScan
SCCM 3 Month Patch Compliance
.PARAMETER runRebootCount
Find computers that have not rebooted within the last X days
.PARAMETER runOSCount
AD Count number of unique Operating Systems in OU specified in $ADSearchBase and Count number of computers within different Operating Systems
.PARAMETER runComputerPasswordCount
#Find info about when computers last changed Computer password
.PARAMETER runComputerPasswordCount
#Create the report with everything included
.EXAMPLE
PCManagementReport -runAppScan $true -runPatchCompScan $true
Creates a report including SCCM Application Scan and Path Compliance Graph
.EXAMPLE
PCManagementReport -runEverything $true
Creates a report including everything
.NOTES
Cmdlet name: PCManagementReport
Author: Mikael Blomqvist
DateCreated: 2017-04-19
#>
[CmdletBinding(SupportsShouldProcess = $True)]
param
(
[Parameter(Mandatory = $False, HelpMessage = "Scan ConfigMgr Applications (True/False)")]
[boolean]$runAppScan = $false,
[Parameter(Mandatory = $False, HelpMessage = "Scan ConfigMgr Devices (True/False)")]
[boolean]$runClientScan = $false,
[Parameter(Mandatory = $False, HelpMessage = "Create Path Compliance Scan (True/False)")]
[boolean]$runPatchCompScan = $true,
[Parameter(Mandatory = $False, HelpMessage = "Calculate Computer Reboot numbers (True/False)")]
[boolean]$runRebootCount = $false,
[Parameter(Mandatory = $False, HelpMessage = "Count number of unique Operating Systems and the number of Computers within each Operation Systems (True/False)")]
[boolean]$runOSCount = $false,
[Parameter(Mandatory = $False, HelpMessage = "Calculate Computer password change numbers (True/False)")]
[boolean]$runComputerPasswordCount = $false,
[Parameter(Mandatory = $False, HelpMessage = "Run everything (True/False)")]
[boolean]$runEverything = $false
)
#Load the ActiveDirectory Module
$m = Get-Module -List ActiveDirectory
if (!$m) {
Write-Host "AD Powershell Module is not installed can not continue."
Exit
}
else {
Import-Module ActiveDirectory
}
$CMSiteServerFQDN = 'siteserver.domain.com' #Configuration Manager Site Server FQDN
$CMSiteServer = $CMSiteServerFQDN.ToString().split(".") | Select -First 1
#Load Configuration Manager PowerShell Module
try {
Import-Module "\\$CMSiteServer\d$\Program Files\Microsoft Configuration Manager\AdminConsole\bin\ConfigurationManager.psd1" -ErrorAction Stop
}
catch {
$_.Exception.Message
$_.Exception.ItemName
Write-Host "Cannot load the Configuration Manager PowerShell Module from the specified location"
break #Terminate if the module cannot be loaded
}
###############################################################################
#
#Edit these to the customer specific values and $CMSiteServer above
#
###############################################################################
#Mail
$smtpServer = "smtprelay.domain.com"
$mailinfo_to = "recipient1@domain.com", "recipient2@domain.com"
$mailinfo_cc = ""
$mailinfo_from = "$env:computername@domain.com"
$logo = "logo.gif"
$Customername = "My Company"
$sendMail = $true
#Active Directory
[string]$ADSearchBase = "OU=ComputersWin10,DC=domain,DC=com" #Win10
[int]$ComputerPasswordAgeDays = 90
[int]$RebootTresholdDays = 5
#SCCM
$Collection = "All Windows 10" #Collection in SCCM which should be used as basis for the device count
$patchNumberOfMonth = 3 #Number of month contained in the patch compliance overview
#Graphic
$CorporateColor = "#780000"
$BackGroundColor = "#505A55"
#Misc
$ReportTitle = "System Report"
$printToConsole = $true #Write Output to console
##############################################################################
#
#Variables which should not be edited
#
##############################################################################
$File_ExpSuperseededApps = "$PSScriptRoot\ExpiredSuperseededApps.csv"
$File_CompNotBooted = "$PSScriptRoot\NotRebootedComputers.csv"
[string]$Attachments = "$OutFile"
#Mail
$OutFile = "$PSScriptRoot\StatusReport.html"
$subject = "$Customername : Status Report"
#AD
$OUName = (Get-ADOrganizationalUnit -Filter * -Properties CanonicalName -SearchBase $ADSearchBase -SearchScope Base).Name
#SCCM
$SiteCode = Get-PSDrive -PSProvider CMSITE #Configuration Manager Site Code
$SCCMNameSpace = "root\sms\site_$SiteCode"
$head = @"
<style>
H1{color: #000000}
H2{color: #FFFFFF}
H3{color: #000000}
p{color: $CorporateColor; font-size:70%}
TABLE {margin-left:50px;background-color: #FFFFFF;}
TR {padding: 0px}
TH {padding: 5px;background-color: $CorporateColor}
TD {padding: 15px;text-align: Center}
BODY {font-family: verdana;background-color: $BackGroundColor}
</style>
<Title>$ReportTitle</Title>
"@
#Build ADSummary table
$tbl_ADSummary = New-Object System.Data.DataTable ADSummary
$col_ADHeading = New-Object System.Data.DataColumn ADHeading, ([string])
$col_ADData = New-Object System.Data.DataColumn ADData, ([string])
$tbl_ADSummary.columns.Add($col_ADHeading)
$tbl_ADSummary.columns.Add($col_ADData)
#Build AppsSummary table
$tbl_AppsSummary = New-Object System.Data.DataTable AppsSummary
$col_AppsHeading = New-Object System.Data.DataColumn AppsHeading, ([string])
$col_AppsData = New-Object System.Data.DataColumn AppsData, ([string])
$tbl_AppsSummary.columns.Add($col_AppsHeading)
$tbl_AppsSummary.columns.Add($col_AppsData)
#Build DeviceSummary table
$tbl_DeviceSummary = New-Object System.Data.DataTable DeviceSummary
$col_DeviceHeading = New-Object System.Data.DataColumn DeviceHeading, ([string])
$col_DeviceData = New-Object System.Data.DataColumn DeviceData, ([string])
$tbl_DeviceSummary.columns.Add($col_DeviceHeading)
$tbl_DeviceSummary.columns.Add($col_DeviceData)
#Build OS Table
$tbl_ostable = New-Object System.Data.DataTable OS
$Col_OSName = New-Object System.Data.DataColumn OSName, ([string])
$Col_OSCount = New-Object System.Data.DataColumn OSCount, ([string])
$tbl_ostable.Columns.Add($Col_OSName)
$tbl_ostable.Columns.Add($Col_OSCount)
#create patch table and columns
$tbl_Compliance = New-Object System.Data.DataTable Patches
$Col_month = New-Object System.Data.DataColumn Month, ([string])
$Col_compliant = New-Object System.Data.DataColumn Compliant, ([decimal])
$Col_noncompliant = New-Object System.Data.DataColumn NonCompliant, ([decimal])
$Col_unknown = New-Object System.Data.DataColumn Unknown, ([decimal])
$tbl_Compliance.columns.Add($Col_month)
$tbl_Compliance.columns.Add($Col_compliant)
$tbl_Compliance.columns.Add($Col_noncompliant)
$tbl_Compliance.columns.Add($Col_unknown)
#Build PieChart for Last Computer PW Change
$tbl_piechart = New-Object System.Data.DataTable PWChange
$Col_category = New-Object System.Data.DataColumn Category, ([string])
$Col_amount = New-Object System.Data.DataColumn Amount, ([string])
$tbl_piechart.columns.Add($Col_category)
$tbl_piechart.columns.Add($Col_amount)
#Function to add rows to table
Function AddTo-Table {
$tableName = $args[0]
$tableHeading = $args[1]
$tableHeadingValue = $args[2]
$tableData = $args[3]
$tableDataValue = $args[4]
$row = $tableName.NewRow(); $row.$tableHeading = $tableHeadingValue; $row.$tableData = $tableDataValue
$tableName.Rows.Add($row)
If ($printToConsole) { Write-Host $tableHeadingValue ": " $tableDataValue }
}
#Function to add attachments to Sting that can be added to the mail
Function Add-Attachment {
[string]$file = $args[0]
$Attachments = $Attachments + ',' + $file
return $Attachments
}
#Create a Pie Chart with the supplied information
Function CreateChart {
$datasource = $args[0]
$title = $args[1]
$ChartType = $args[2]
$xValue = $args[3]
$yValue = $args[4]
$imagePath = $args[5]
$imagewidth = $args[6]
$imageheight = $args[7]
$displayedinLegend = $args[8]
[void][Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms.DataVisualization")
$scriptpath = $PSScriptRoot
# chart object
$chart1 = New-object System.Windows.Forms.DataVisualization.Charting.Chart
$chart1.Width = $imagewidth
$chart1.Height = $imageheight
$chart1.BackColor = [System.Drawing.Color]::White
# title
[void]$chart1.Titles.Add("$title")
$chart1.Titles[0].Font = "Verdana,14pt"
$chart1.Titles[0].Alignment = "topCenter"
$chart1.Titles[0].ForeColor = $CorporateColor
# chart area
$chartarea = New-Object System.Windows.Forms.DataVisualization.Charting.ChartArea
$chartarea.Name = "ChartArea1"
$chartarea.AxisY.MajorGrid.Enabled = $false
$chartarea.AxisX.MajorGrid.Enabled = $false
$chart1.ChartAreas.Add($chartarea)
# legend
$legend = New-Object system.Windows.Forms.DataVisualization.Charting.Legend
$legend.name = "Legend1"
$chart1.Legends.Add($legend)
# data series
[void]$chart1.Series.Add("PWWithin")
$chart1.Series["PWWithin"].ChartType = "$ChartType"
$chart1.Series["PWWithin"].BorderWidth = 10
$chart1.Series["PWWithin"].IsVisibleInLegend = $displayedinLegend
$chart1.Series["PWWithin"].chartarea = "ChartArea1"
$chart1.Series["PWWithin"].IsValueShownAsLabel = $true
$datasource | ForEach-Object { $chart1.Series["PWWithin"].Points.addxy( $_.$xValue , $_.$yValue) }
# save chart
$chart1.SaveImage($imagePath, "png")
}
#Function to Create a stacked patch compliance graph showing the past software update groups
Function CreateComplianceChart {
$datasource = $args[0]
$Pic_PatchComp = "PatchCompliance_Stacked100.png"
$Path_PatchComp = "$PSScriptRoot\$Pic_PatchComp"
[void][Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms.DataVisualization")
$scriptpath = $PSScriptRoot
# chart object
$chart1 = New-object System.Windows.Forms.DataVisualization.Charting.Chart
$chart1.Width = 800
$chart1.Height = 600
$chart1.BackColor = [System.Drawing.Color]::White
# title
[void]$chart1.Titles.Add("Past $patchNumberOfMonth Month Patch Compliance Development")
$chart1.Titles[0].Font = "Verdana,20pt"
$chart1.Titles[0].Alignment = "topCenter"
$chart1.Titles[0].ForeColor = $CorporateColor
# chart area
$chartarea = New-Object System.Windows.Forms.DataVisualization.Charting.ChartArea
$chartarea.Name = "ChartArea1"
$chartarea.AxisY.Title = "Compliance %"
$chartarea.AxisX.Title = "Month"
$chartarea.AxisY.Interval = 10
$chartarea.AxisX.Interval = 1
$chart1.ChartAreas.Add($chartarea)
# legend
$legend = New-Object system.Windows.Forms.DataVisualization.Charting.Legend
$legend.name = "Legend1"
$chart1.Legends.Add($legend)
# data series
[void]$chart1.Series.Add("Compliant")
$chart1.Series["Compliant"].ChartType = "StackedColumn100"
$chart1.Series["Compliant"].BorderWidth = 10
$chart1.Series["Compliant"].IsVisibleInLegend = $true
$chart1.Series["Compliant"].chartarea = "ChartArea1"
$chart1.Series["Compliant"].Legend = "Legend1"
$chart1.Series["Compliant"].color = "#2ECC71"
$chart1.Series["Compliant"].IsValueShownAsLabel = $true
$datasource | ForEach-Object { $chart1.Series["Compliant"].Points.addxy( $_.Month , $_.Compliant) }
# data series
[void]$chart1.Series.Add("NonCompliant")
$chart1.Series["NonCompliant"].ChartType = "StackedColumn100"
$chart1.Series["NonCompliant"].IsVisibleInLegend = $true
$chart1.Series["NonCompliant"].BorderWidth = 10
$chart1.Series["NonCompliant"].chartarea = "ChartArea1"
$chart1.Series["NonCompliant"].Legend = "Legend1"
$chart1.Series["NonCompliant"].color = "#E74C3C"
$chart1.Series["NonCompliant"].IsValueShownAsLabel = $true
$datasource | ForEach-Object { $chart1.Series["NonCompliant"].Points.addxy( $_.Month , $_.NonCompliant) }
# data series
[void]$chart1.Series.Add("Unknown")
$chart1.Series["Unknown"].ChartType = "StackedColumn100"
$chart1.Series["Unknown"].IsVisibleInLegend = $true
$chart1.Series["Unknown"].BorderWidth = 10
$chart1.Series["Unknown"].chartarea = "ChartArea1"
$chart1.Series["Unknown"].Legend = "Legend1"
$chart1.Series["Unknown"].color = "#CACFD2"
$chart1.Series["Unknown"].IsValueShownAsLabel = $true
$datasource | ForEach-Object { $chart1.Series["Unknown"].Points.addxy( $_.Month , $_.Unknown) }
# save chart
$chart1.SaveImage("$PSScriptRoot\PatchCompliance_Stacked100.png", "png")
}
# This function is used to send the email containing the report and attachments.
# The reason this one is used instead of Send-MailMessage is that .NET allows images to be embedded in the email using the cid tag
Function SendMail {
$mailbody = $args[0]
$mailattachments = $args[1]
$SmtpClient = New-Object System.Net.Mail.SmtpClient($smtpServer)
$MailMessage = New-object System.Net.Mail.MailMessage($mailinfo_from, $mailinfo_to, $Subject, $mailbody)
$MailMessage.IsBodyHtml = $true
$trimlenght = $PSScriptRoot.Length + 1 #have to add 1 because of the extra / in the path
Foreach ($attachment in $mailattachments) {
$attachmentID = $attachment.SubString($trimlenght) #This is to use only the actualy filename as ID
$obj_attachment = New-Object System.Net.Mail.Attachment($attachment)
$obj_attachment.ContentID = $attachmentID
$MailMessage.Attachments.Add($obj_attachment)
}
$SmtpClient.Send($MailMessage)
}
$Attachments = Add-Attachment "$PSScriptRoot\$logo"
#Get all Computers within the specified SearchBase excluding Servers
$Computers = Get-ADComputer -SearchBase $ADSearchBase -filter { (OperatingSystem -notlike "*Server*") } -properties Name, DistinguishedName, OperatingSystem, OperatingSystemServicePack, passwordLastSet, LastLogonDate, Description
AddTo-Table $tbl_ADSummary "ADHeading" "Number of computers in $OUName" "ADData" $Computers.Count
If ($printToConsole) {
Write-Host "Overview:"
Write-Host "--------------------"
Write-Host "Total number of computers: "$Computers.Count
}
#Count number of unique OS
If ($runOSCount -or $runEverything) {
#Change variable to UComputers and work with this
$UComputers = $Computers | select-object Name, OperatingSystem, OperatingSystemServicePack, passwordLastSet, LastLogonDate, DistinguishedName, CountryOUADvariable
$UniqueOS = $UComputers | Select-Object OperatingSystem | Sort OperatingSystem -Descending | Get-Unique -Asstring
#Count number of unique OS
$NumberofUniqueOS = 0
foreach ($uos in $UniqueOS) { $NumberofUniqueOS++ }
#AddTo-Table $tbl_ADSummary "ADHeading" "Number of different Operating Systems" "ADData" $NumberofUniqueOS
#Meassure/Count how many computer object of each OS type
foreach ($os in $UComputers | Select-Object OperatingSystem | Sort OperatingSystem -Descending | Get-Unique -Asstring) {
$count = ($UComputers | where { $_.OperatingSystem.ToString() -eq $os.OperatingSystem } | measure).Count
AddTo-Table $tbl_ostable "OSName" ($os.OperatingSystem.ToString()) "OSCount" $count
$count = 0
}
#CreateOSChart $tbl_ostable
CreateChart $tbl_ostable "Operating Systems" "Pie" "OSName" "OSCount" "$PSScriptRoot\OS_Pie.png" "400" "200" $true
$Attachments = Add-Attachment "$PSScriptRoot\OS_Pie.png"
}
CD $SiteCode':'
#Finding Computers that are within and outside the treshold of when Computer password was last set
If ($runComputerPasswordCount -or $runEverything) {
$ComputerStaleDate = (Get-Date).AddDays(-$ComputerPasswordAgeDays)
$PWWithin = $Computers | Where { $_.passwordLastSet -ge $ComputerStaleDate }
$PWOutside = $Computers | Where { $_.passwordLastSet -le $ComputerStaleDate }
AddTo-Table $tbl_piechart "Category" "Within Treshold" "Amount" $PWWithin.Count
AddTo-Table $tbl_piechart "Category" "Outside Treshhold" "Amount" $PWOutside.Count
If ($printToConsole) {
Write-Host "Computer Password:"
Write-Host "--------------------"
Write-Host "Within Treshold: "$PWWithin.Count
Write-Host "Outside Treshhold: "$PWOutside.Count
}
#CreateComputerPWChart $tbl_piechart
CreateChart $tbl_piechart "Computer Password" "Pie" "Category" "Amount" "$PSScriptRoot\ComputerPW_Pie.png" "400" "200" $true
$ComputersinSCCM = $PWOutside | Where-Object { $_ -ne $null } | Foreach-Object { Get-CMDevice -Name $_.Name }
AddTo-Table $tbl_ADSummary "ADHeading" "In SCCM but havent changed PW within $ComputerPasswordAgeDays days" "ADData" $ComputersinSCCM.Count
$Attachments = Add-Attachment "$PSScriptRoot\ComputerPW_Pie.png"
}
#Count number of computers that havent been rebooted within the number of days specified in $RebootTresholdDays
If ($runRebootCount -or $runEverything) {
$OUCanonicalName = (Get-ADOrganizationalUnit -Filter * -Properties CanonicalName -SearchBase "$ADSearchBase" -SearchScope Base).CanonicalName
$computersNotRebooted = (Get-WmiObject -namespace $SCCMNameSpace -computer $CMSiteServerFQDN -query "SELECT DISTINCT SMS_R_System.Name, SMS_G_System_OPERATING_SYSTEM.LastBootUpTime, SMS_G_System_OPERATING_SYSTEM.Caption
FROM SMS_R_System INNER JOIN SMS_G_System_OPERATING_SYSTEM ON SMS_G_System_OPERATING_SYSTEM.ResourceID = SMS_R_System.ResourceId
WHERE (DateDiff(day, SMS_G_System_OPERATING_SYSTEM.LastBootUpTime, GetDate()) >$RebootTresholdDays) AND SMS_R_System.SystemOUName = '$OUCanonicalName'").SMS_R_System | Select Name
AddTo-Table $tbl_ADSummary "ADHeading" "Not rebooted within the last $RebootTresholdDays days" "ADData" $computersNotRebooted.Count
If ($printToConsole) {
Write-Host "Computer Reboot:"
Write-Host "Computers not rebooted with $RebootTresholdDays : " $computersNotRebooted.Count
}
}
#Get the last 3 SoftwareUpdate Groups
If ($runPatchCompScan -or $runEverything) {
$SUGs = Get-CMSoftwareUpdateGroup | Sort-Object { $_.datecreated } -Descending | Select -First $patchNumberOfMonth
If ($printToConsole) {
Write-Host "Software Update Groups:"
Write-Host "-----------------------"
}
Foreach ($sug in $SUGs) {
$month = $sug.LocalizedDisplayName
$compliant = [math]::Round((($sug.NumCompliant / ($sug.NumTotal)) * 100), 2)
$noncompliant = [math]::Round((($sug.NumNonCompliant / ($sug.NumTotal)) * 100), 2)
$unknown = [math]::Round((($sug.NumUnknown / $sug.NumTotal) * 100), 2)
If ($printToConsole) {
Write-Host "Month: $month"
Write-Host "-Compliant: $Compliant"
Write-Host "-NonCompliant: $noncompliant"
Write-Host "-Unknown: $unknown"
}
$row = $tbl_Compliance.NewRow(); $row.Month = $month; $row.Compliant = $compliant; $row.NonCompliant = $noncompliant; $row.Unknown = $unknown
$tbl_Compliance.Rows.Add($row)
}
CreateComplianceChart $tbl_Compliance
$Attachments = Add-Attachment "$PSScriptRoot\PatchCompliance_Stacked100.png"
}
#Count number of Applications in SCCM
If ($runAppScan -or $runEverything) {
$AllApps = Get-CMApplication
$DeployedSuperseeded = $AllApps | Where-Object { <#($_.IsDeployed -eq $true) -and #>($_.IsSuperseded -eq $true) }
$DeployedExpired = $AllApps | Where-Object { <#($_.IsDeployed -eq $true) -and#> ($_.IsExpired -eq $true) }
$DeployedWorking = $AllApps | Where-Object { ($_.IsDeployed -eq $true) -and ($_.IsExpired -eq $false) -and ($_.IsSuperseded -eq $false) }
$NotDeployed = $AllApps | Where-Object { ($_.IsDeployed -eq $false) }
#AddTo-Table $tbl_AppsSummary "AppsHeading" "Total number of Applications in SCCM" "AppsData" $AllApps.Count
AddTo-Table $tbl_AppsSummary "AppsHeading" "Superseeded Applications" "AppsData" $DeployedSuperseeded.Count
AddTo-Table $tbl_AppsSummary "AppsHeading" "Expired Applications" "AppsData" $DeployedExpired.Count
AddTo-Table $tbl_AppsSummary "AppsHeading" "Active Applications" "AppsData" $DeployedWorking.Count
AddTo-Table $tbl_AppsSummary "AppsHeading" "Applications without deployment(s)" "AppsData" $NotDeployed.Count
CreateChart $tbl_AppsSummary "All Applications" "Pie" "AppsHeading" "AppsData" "$PSScriptRoot\Applications_Pie.png" "400" "200" $true
$Attachments = Add-Attachment "$PSScriptRoot\Applications_Pie.png"
If ($printToConsole) {
Write-Host "Applications:"
Write-Host "--------------------"
Write-Host "Superseeded Applications: "$DeployedSuperseeded.Count
Write-Host "Expired Applications: "$DeployedExpired.Count
Write-Host "Active Applications: "$DeployedWorking.Count
Write-Host "Applications without deployment(s): "$NotDeployed.Count
}
}
#Count devices in SCCM
If ($runClientScan -or $runEverything) {
$AllDevicesinSCCM = Get-CMDevice -CollectionName "$Collection"
$AciveDevices = $AllDevicesinSCCM | Where-Object { ($_.ClientActiveStatus -eq 1) }
$InaciveDevices = $AllDevicesinSCCM | Where-Object { ($_.ClientActiveStatus -eq 0) }
$ObsoleteDevices = $AllDevicesinSCCM | Where-Object { ($_.IsObsolete -eq $true) }
$NoSCCMClient = $AllDevicesinSCCM | Where-Object { ($_.IsClient -eq $false) }
AddTo-Table $tbl_DeviceSummary "DeviceHeading" "Active Devices" "DeviceData" $AciveDevices.Count
AddTo-Table $tbl_DeviceSummary "DeviceHeading" "Obsolete devices" "DeviceData" $ObsoleteDevices.Count
AddTo-Table $tbl_DeviceSummary "DeviceHeading" "Inactive Devices" "DeviceData" $InaciveDevices.Count
AddTo-Table $tbl_DeviceSummary "DeviceHeading" "Devices without Client" "DeviceData" $NoSCCMClient.Count
CreateChart $tbl_DeviceSummary "Devices in $Collection" "Pie" "DeviceHeading" "DeviceData" "$PSScriptRoot\Devices_Pie.png" "400" "200" $true
$Attachments = Add-Attachment "$PSScriptRoot\Devices_Pie.png"
If ($printToConsole) {
Write-Host "Devices:"
Write-Host "--------------------"
Write-Host "Active Devices: "$AciveDevices.Count
Write-Host "Obsolete devices: "$ObsoleteDevices.Count
Write-Host "Inactive Devices: "$InaciveDevices.Count
Write-Host "Devices without Client: "$NoSCCMClient.Count
}
}
CreateChart $tbl_ADSummary "Computer Info" "Bar" "ADHeading" "ADData" "$PSScriptRoot\ComputerInfo_Bar.png" "800" "300" $false
$Attachments = Add-Attachment "$PSScriptRoot\ComputerInfo_Bar.png"
#Convert All tables to HTML
#--------------------------------------------------------
#Convert the ostable to a HTML Fragment that can be inserted into the html document.
$osfragment = $tbl_ostable | Select @{Name = "Operating System"; Expression = { $_.OSName } }, @{Name = "Count"; Expression = { $_.OSCount } } | ConvertTo-Html -Fragment
$adfragment = $tbl_ADSummary | Select ADHeading, ADData | ConvertTo-Html -Fragment
$sccmfragment = $tbl_AppsSummary | Select AppsHeading, AppsData | ConvertTo-Html -Fragment
#Write results depending on parameter set
$footer = "Report ran from {3} initiated by {1}\{2} at {0}" -f (Get-Date), $env:USERDOMAIN, $env:USERNAME, $env:COMPUTERNAME
$fragments = @()
#Insert a graphic header
$fragments += "<Center><table>"
$fragments += "<tr><td><Img src='cid:$logo'></td></tr>"
$fragments += "<tr><td><H1>$Customername - Environment Summary</H1></td></tr>"
$fragments += "<tr><td ><h3>Computers in: $OUName</h3></td></tr>"
#Only show this section if any of the elements in it are choosen to be calculated
If ($runRebootCount -or $runComputerPasswordCount -or $runOSCount -or $runEverything) {
$fragments += "<tr><th><H2>Active Directory Summary</H2></th></tr>"
If ($runRebootCount -or $runEverything) {
$fragments += "<tr><td><Img src='cid:ComputerInfo_Bar.png'></td></tr>"
}
If ($runComputerPasswordCount -or $runOSCount -or $runEverything) {
$fragments += "<tr><td>"
If ($runOSCount -or $runEverything) {
$fragments += "<Img src='cid:OS_Pie.png'>"
}
If ($runComputerPasswordCount -or $runEverything) {
$fragments += "<Img src='cid:ComputerPW_Pie.png'>"
}
$fragments += "</td></tr>"
}
}
#Only show the SCCM Summary in the report if either runAppScan or runClientScan is enabled.
If ($runAppScan -or $runClientScan -or $runEverything) {
$fragments += "<tr><th><H2>SCCM Summary</H2></th></tr>"
$fragments += "<tr><td>"
If ($runAppScan -or $runEverything) {
$fragments += "<Img src='cid:Applications_Pie.png'>"
}
If ($runClientScan -or $runEverything) {
$fragments += "<Img src='cid:Devices_Pie.png'>"
}
$fragments += "</td></tr>"
}
#Only show the Patch Compliance Overview if runPatchCompScan is enabled
If ($runPatchCompScan -or $runEverything) {
$fragments += "<tr><th><H2>Patch Compliance Overview</H2></th></tr>"
$fragments += "<tr><td><Img src='cid:PatchCompliance_Stacked100.png'></td></tr>"
}
$fragments += "<tr><td><p>$footer</p></td></tr>"
$fragments += "</table></Center>"
CD c:\
#Write to Files
$DeployedSuperseeded | Select @{Name = "Superseeded Applications"; Expression = { $_.LocalizedDisplayName } } | Out-File $File_ExpSuperseededApps
$DeployedExpired | Select @{Name = "Expired Applications"; Expression = { $_.LocalizedDisplayName } } | Out-File $File_ExpSuperseededApps -Append
$NotDeployed | Select @{Name = "Applications without Deployments"; Expression = { $_.LocalizedDisplayName } } | Out-File $File_ExpSuperseededApps -Append
$computersNotRebooted | Out-File $File_CompNotBooted
#Adding files to attachment array if they have been created.
If ($runRebootCount) {
$Attachments = Add-Attachment $File_CompNotBooted
}
If ($runAppScan) {
$Attachments = Add-Attachment $File_ExpSuperseededApps
}
$body = ConvertTo-Html -Head $head -Title $ReportTitle -Body $fragments
#For the html report the cid is removed so the image src path is correct
$report = $fragments -replace "cid:", ""
ConvertTo-Html -Head $head -Title $ReportTitle -Body $report | Out-File $OutFile
$ArrayAttachment = $Attachments.Split(",")
If ($sendMail) {
sendmail $body $ArrayAttachment
}
Else {
Write-Host "Send Mail is disabled so no mail were sent."
}
Recent Comments