SHIFT

--- Sjoerd Hooft's InFormation Technology ---

User Tools

Site Tools


Sidebar

Recently Changed Pages:

View All Pages


View All Tags


LinkedIn




WIKI Disclaimer: As with most other things on the Internet, the content on this wiki is not supported. It was contributed by me and is published “as is”. It has worked for me, and might work for you.
Also note that any view or statement expressed anywhere on this site are strictly mine and not the opinions or views of my employer.


Pages with comments

View All Comments

wsusreport

WSUS Reports

These are custom wsus reports, as wsus by default does not provide that many useful reports. Please note that the script is designed to run in two domains, and for versioning purposes you only have to maintain one copy. The script is being copied to the second domain, and then automatically run there as well. Note that the scheduling is done by Windows Task Schedular.

Note that the functions and scheduling is also explained in AD Controls

Script

# Author: Sjoerd Hooft / https://www.linkedin.com/in/sjoerdhooft/
 
### Versioning and functionality ##################################################################
### 2019 02 22 - Sjoerd Hooft ###
# Collect Evidence for ICT Control WSUS
### Shows the TOPdesk changes for the Windows Servers and Clients 
### Shows the Approved updates on the WSUS Server
### Shows the total number of clients that were processed 
### Shows per server per group the client with lots of update issues or that are considered stale (both settings are variables)
### Shows the update status per client 
### Makes a nice html email with all information 
###################################################################################################
 
### Bugs ##########################################################################################
### 
###################################################################################################
 
### How-To ########################################################################################
# Because there are multiple WSUS servers in different domains this scipt has been made multi-domain aware (sort-of). Because the script uses functionality that is not supported in remote sessions there is no way to run the script once. Therefore, if the script is run from the Production domain the script is copied to the Management domain. So you need to make sure that you always first run the script on the Production Domain before you run it in the Management Domain. 
###
# When changing and testing
## Disable the toemail variable and replace it with one that points just to you 
## Make a backup of the script in the Management domain as it gets overwritten 
###################################################################################################
 
### Script Overview ###############################################################################
### Fase 1
# Set script variables
# Start Logging
# Check for required modules
# All other Variables 
# Import default functions 
# Script specific functions
### Fase 2
# Get all TOPdesk Change Requests
### Fase 3
# Copy this script to the management domain  
### Fase 4
# Perform all WSUS scripting 
### Fase 5
# Collect all totals
### Fase 6
# Send the report
###################################################################################################
 
########################################## Start Fase 1 ###########################################
 
# Script Variables
$scriptname = [System.IO.Path]::GetFilenameWithoutExtension($MyInvocation.MyCommand.Path.ToString())
$scriptlocation = Split-Path $myinvocation.mycommand.path
 
# Start transcript for full logging capabilities
start-transcript -path "$scriptlocation\logtranscript.txt"
 
# Date & Time Variables
$timestamp = Get-Date -format "yyyyMMdd-HH.mm"
$readdate = Get-Date -format "d MMM yyyy"
$weekdate = Get-Date -uformat %V
$monthdate = Get-Date -format "MMMM-yyyy"
 
# Reporting Variables
### Email Variables
$mailserver = "smtp1.ad.shift.com"
$toemail = "s.hooft_getshifting.com"
$ccmail = "s.hooft_getshifting.com"
#$fromemail = "$scriptname_getshifting.com"
$fromemail = "$scriptname_getshifting.com"
# Make the email start specific for this control
$infoheader = "Dear $toemail , <br>"
$infoheader += "<br>"
$infoheader += "This is the automatic report as run for ICT Control Framework WSUS<br>"
$infoheader += "<i>What do you need to do:</i><br>"
$infoheader += "<i>What:</i> The Manager ICT Infrastructure checks monthly if: <br>
<ul>
<li> A patch planning is available and included in the Change Calendar; </li>
<li> Hard and software patches are implemented conform planning,  after testing and correct approvals; </li>
<li> Incidents are recorded in Topdesk and properly followed up. </li>
</ul>
In phase 1 this check is limited to the critical and security patches of the Windows Client Update and Windows Server Update. 
<br>"
$infoheader += "<i>Who:</i> Manager ICT Infrastructure<br>"
$infoheader += "<i>When:</i> Monthly. <br>"
$infoheader += "<br>"
$infoheader += "Check the wsus updates and information below. Upload the final report to SharePoint - WSUS<br><br>"
$infoheader += "<b>The following information was found:</b> <br>"
$infoheader += "<br>"
 
# Management Domain Variables 
$scripttocopy = "$scriptlocation\$scriptname.ps1"
$functiontocopy = "$scriptlocation\Functions.ps1"
$mgtuser = 'SHIFTMGT\sa_as'
$mgtscriptserver = "MGTSERVER.SHIFTMANAGEMENT.SHIFT.COM"
$mgtscriptserverdir = "C:\ICTControlFramework"
# Perform these two one-time actions to add the management domain server to the list of trusted hosts and make a protected password file 
### One-time: Set-Item wsman:\localhost\Client\TrustedHosts -value $mgtscriptserver -Force
### one-time per user per server: Read-Host "Enter Password" -AsSecureString |  ConvertFrom-SecureString | Out-File "mgtcreds.txt"
 
# Provide tableheader for WSUS Section
$infowsus += '<table style="width:100%; border: 1px solid #dddddd; text-align: left;">'
$infowsus += "<tr>"
$infowsus += '<th style="width: 100px; text-align: left;">'
$infowsus += "GroupName"
$infowsus += '</th>'
$infowsus += '<th style="width: 200px; text-align: left;">'
$infowsus += "ServerName"
$infowsus += '</th>'
$infowsus += '<th style="width: 100px; text-align: left;">'
$infowsus += "Last Reported Time"
$infowsus += '</th>'
$infowsus += '<th style="width: 100px; text-align: left;">'
$infowsus += "Last Sync Result On"
$infowsus += '</th>'
$infowsus += '<th style="width: 400px; text-align: left;">'
$infowsus += "Updates that are not installed"
$infowsus += '</th>'
$infowsus += '<th style="width: 400px; text-align: left;">'
$infowsus += "Updates that are waiting for a reboot"
$infowsus += '</th>'
$infowsus += '<th style="text-align: left;">'
$infowsus += "Unknown Updates"
$infowsus += '</th>'
$infowsus += "</tr>"
$infowsus += "</table>"
 
# Provide tableheader for Updates Section 
$infoupdates += '<table style="width:100%; border: 1px solid #dddddd; text-align: left;">'
$infoupdates += "<tr>"
$infoupdates += '<th style="width: 200px; text-align: left;">'
$infoupdates += "Server Name"
$infoupdates += '</th>'
$infoupdates += '<th style="text-align: left;">'
$infoupdates += "Last $updatesIwannaknowabout Approved Updates"
$infoupdates += '</th>'
$infoupdates += "</tr>"
$infoupdates += "</table>"
 
# Provide tableheader for Prio Section 
$infoprio += '<table style="width:100%; border: 1px solid #dddddd; text-align: left;">'
$infoprio += "<tr>"
$infoprio += '<th style="width: 200px; text-align: left;">'
$infoprio += "Server Name"
$infoprio += '</th>'
$infoprio += '<th style="width: 100px; text-align: left;">'
$infoprio += "Group Name"
$infoprio += '</th>'
$infoprio += '<th style="width: 100px; text-align: left;">'
$infoprio += "Number of clients in group"
$infoprio += '</th>'
$infoprio += '<th style="width: 300px; text-align: left;">'
$infoprio += "Clients with more then $maxissues update issues"
$infoprio += '</th>'
$infoprio += '<th style="text-align: left;">'
$infoprio += "Clients which reported over $staledays days ago"
$infoprio += '</th>'
$infoprio += "</tr>"
$infoprio += "</table>"
 
# TOPdesk (SQL) Variables
$SqlServer = "WIN-SQL-P01\SQL01"
$SqlDbName = "TopDeskDB"
$SqlUser = "TOPdesk_user"
 
# TOPdesk Search & Match Variables 		
$searchlap = 180
$matchchangeservers = "Windows Server Update"
$matchchangeclients = "Windows client and office security and critical updates"
 
# WSUS Variables
$wsusservers = "win-wsus-p01.ad.shift.com", "win-sccm-p01.ad.shift.com", "wsus1.SHIFTMANAGEMENT.SHIFT.COM"
# Default WSUS ports: #Old version: "80","443" New Version:"8350","8351"
$Port = 8530
$UseSSL = $False
 
# Control Framework variables
# How much time before a server gets listed in the findings
$staledays = 30
$stale = (get-date).adddays(-$staledays)
# How much issues before a server gets listed in the findings
$maxissues = 25
# How many updates to list in the approved updates section
$updatesIwannaknowabout = 10
 
# Other Variables
$computercount = 0
 
### Start Functions ###
# Import functions from global function file
. "$scriptlocation\Functions.ps1"
 
########################################## Start Fase 2 ###########################################
 
# If the script is not run in the management domain, search for TOPdesk Change Requests
 
if ($env:userdnsdomain -notlike "*management*"){
		#Copy this script to the management domain server  
		# NOTE: Run once per server per user: read-host -assecurestring | convertfrom-securestring | out-file "sqlcreds.txt"
		$SqlPassWord = get-content "$scriptlocation\sqlcreds.txt" | convertto-securestring
		$credentials = new-object -typename System.Management.Automation.PSCredential -argumentlist $SqlUser,$SqlPassWord
		$sqlusername = $credentials.UserName
		$sqlpass = $credentials.GetNetworkCredential().Password
 
		### Create TOPdesk data set with all changes 
		$searchdate = (Get-Date).adddays(-$searchlap).ToString('MM/dd/yyyy HH:mm:ss')
		$TOPdeskSQLQuery = $("SELECT number,status,calldate,briefdescription,unid FROM change WHERE status > 0 and calldate > '$searchdate'")
		$TOPdeskDataSet = TOPdesk-Query $TOPdeskSQLQuery
 
		$topdeskcrsservers = $TOPdeskDataSet | where {$_.briefdescription -like "*$matchchangeservers*"} | select number, briefdescription, unid | sort number
		$topdeskcrsclients = $TOPdeskDataSet | where {$_.briefdescription -like "*$matchchangeclients*"} | select number, briefdescription, unid | sort number
 
		# Create Report Table header for TOPdesk including results 
		$infotopdesk += '<table style="width:100%; border: 1px solid #dddddd; text-align: left;">'
		$infotopdesk += "<tr>"
		$infotopdesk += '<th style="width: 100px; text-align: left;">'
		$infotopdesk += "Servers / Clients"
		$infotopdesk += '</th>'
		$infotopdesk += '<th style="width: 200px; text-align: left;">'
		$infotopdesk += "Search Query"
		$infotopdesk += '</th>'
		$infotopdesk += '<th style="text-align: left;">'
		$infotopdesk += "All matching TOPdesk changes in the last $searchlap days:"
		$infotopdesk += '</th>'
		$infotopdesk += "</tr>"
		$infotopdesk += "</table>"
		$infotopdesk += '<table style="width:100%; border: 1px solid #dddddd; text-align: left;">'
		$infotopdesk += "<tr>"
		$infotopdesk += '<td style="width: 100px; text-align: left;">'
		$infotopdesk += "Servers"
		$infotopdesk += '</td>'
		$infotopdesk += '<td style="width: 200px; text-align: left;">'
		$infotopdesk += "$matchchangeservers"
		$infotopdesk += '</td>'
		$infotopdesk += '<td style="text-align: left;">'
		if ($topdeskcrsservers.count -ne 0){
			ForEach ($cr in $topdeskcrsservers){
				$TDCR = $cr.number
				$TDD = $cr.briefdescription
				$TCUNID = $cr.unid
				$infotopdesk += "<a href=http://topdesk/tas/secure/newchange?unid=$TCUNID>$TDCR</a> - $TDD <br>"
			}
		}else{
			$infotopdesk += "None matching TOPdesk changes found <br>"
			$infotopdesk += "Fill in TOPdesk reference: <br>"
		}
		$infotopdesk += '</td>'
		$infotopdesk += "</tr>"
		$infotopdesk += "</table>"
		$infotopdesk += '<table style="width:100%; border: 1px solid #dddddd; text-align: left;">'
		$infotopdesk += "<tr>"
		$infotopdesk += '<td style="width: 100px; text-align: left;">'
		$infotopdesk += "Clients"
		$infotopdesk += '</td>'
		$infotopdesk += '<td style="width: 200px; text-align: left;">'
		$infotopdesk += "$matchchangeclients"
		$infotopdesk += '</td>'
		$infotopdesk += '<td style="text-align: left;">'
		if ($topdeskcrsclients.count -ne 0){
			ForEach ($cr in $topdeskcrsclients){
				$TDCR = $cr.number
				$TDD = $cr.briefdescription
				$TCUNID = $cr.unid
				$infotopdesk += "<a href=http://topdesk/tas/secure/newchange?unid=$TCUNID>$TDCR</a> - $TDD <br>"
			}
		}else{
			$infotopdesk += "None matching TOPdesk changes found <br>"
			$infotopdesk += "Fill in TOPdesk reference: <br>"
		}
		$infotopdesk += '</td>'
		$infotopdesk += "</tr>"
		$infotopdesk += "</table>"
		$infotopdesk += "<br>"
}
 
 
 
########################################## Start Fase 3 ###########################################
 
# Make a session to the management server in the management domain if required to copy this script to the management domain. 
if ($env:userdnsdomain -notlike "*management*"){
	Write-Host "Copy $scripttocopy to $mgtscriptserver"
	$mgtpass =  Get-Content "$scriptlocation\mgtcreds.txt" | ConvertTo-SecureString
	$mgtcreds = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $mgtuser,$mgtpass
	$mgtsession = New-PSSession -ComputerName $mgtscriptserver -Credential $mgtcreds
	Copy-Item $scripttocopy -Destination $mgtscriptserverdir -ToSession $mgtsession
	Copy-Item $functiontocopy -Destination $mgtscriptserverdir -ToSession $mgtsession
	Remove-pssession $mgtsession
}
 
########################################## Start Fase 4 ###########################################
 
ForEach ($wsusserver in $wsusservers){
	# Match the user that runs the script with the correct servers 
	if ($wsusserver -like "*$env:userdnsdomain*"){
		[void][reflection.assembly]::LoadWithPartialName("Microsoft.UpdateServices.Administration")
		$wsus = [Microsoft.UpdateServices.Administration.AdminProxy]::getUpdateServer($wsusserver,$usessl,$port)
		$groups = $wsus.GetComputerTargetGroups()
		# Update scope properties: https://blogs.technet.microsoft.com/heyscriptingguy/2012/01/20/get-windows-update-status-information-by-using-powershell/ 
		$updateScope = New-Object Microsoft.UpdateServices.Administration.UpdateScope
		# https://docs.microsoft.com/en-us/previous-versions/windows/desktop/aa354552%28v%3dvs.85%29 - All, Downloaded, Failed, Installed, InstalledPendingReboot, NotApplicable, NotInstalled, Unknown
		#$updateScope.UpdateApprovalActions = [Microsoft.UpdateServices.Administration.UpdateApprovalActions]::Install
		$updateScope.UpdateApprovalActions = 'Install'
		$updateScope.IncludedInstallationStates = 'All'
		$updates = $wsus.GetUpdates($updateScope) | sort -descending creationdate | select -first $updatesIwannaknowabout @{N="KB";E={@($_.KnowledgebaseArticles[0])}},@{N="KBurl";E={@($_.AdditionalInformationUrls[0])}},creationdate,MsrcSeverity,UpdateClassificationTitle,Title
		$allapprovedupdates = $null
		ForEach ($update in $updates){
			#$updateinfo = $update.GetUpdate() | select @{N="KB";E={@($_.KnowledgebaseArticles[0])}},@{N="KBurl";E={@($_.AdditionalInformationUrls[0])}},creationdate,MsrcSeverity,UpdateClassificationTitle
			$updateinfo = $update
			$updatetitle = $update.title
			$updatekb = $updateinfo.kb
			$updatekburl = $updateinfo.kburl
			$updatekbcdate = $updateinfo.creationdate | get-date -Uformat "%d %b %Y"
			$severity = $updateinfo.MsrcSeverity
			$updatetype = $updateinfo.UpdateClassificationTitle
			$allapprovedupdates = $allapprovedupdates + "<a href=$updatekburl>$updatekb</a> - $updatekbcdate - $updatetitle - $severity - $updatetype <br>"
		}
		$infoupdates += '<table style="width:100%; border: 1px solid #dddddd; text-align: left;">'
		$infoupdates += "<tr>"
		$infoupdates += '<td style="width: 200px; text-align: left;">'
		$infoupdates += "$wsusserver"
		$infoupdates += '</td>'
		$infoupdates += '<td style="text-align: left;">'
		$infoupdates += "$allapprovedupdates"
		$infoupdates += '</td>'
		$infoupdates += "</tr>"
		$infoupdates += "</table>"
		foreach ($group in $groups){
			$targetgroup = $Group.Name
			#$groupclients = $group.Count
			#$allgroups = $allgroups + "$targetgroup; "
			#write-host "Starting target group $targetgroup"
			$stalecomputers = $null
			$stalecomputerscount = 0
			$maxissuecomputers = $null
			$maxissuecomputerscount = 0
			$groupclientscount = 0
			#Exclude All Computers from processing as we want to process all clients per group
			if ($targetgroup -ne "All Computers"){
				$computers = ($wsus.GetComputerTargetGroups() | Where {$_.Name -eq $TargetGroup }).GetComputerTargets() | Sort FullDomainName
				ForEach ($computer in $computers){
					$computercount ++
					$groupclientscount ++
					$computername = $computer.fulldomainname
					$lastsynctime = $computer.LastSyncTime | get-date -Uformat "%d %b %Y"
					$lastsyncresult = $computer.LastSyncResult
					$lastreportedstatustime = $computer.LastReportedStatusTime
					$lastreportedstatusdate = $computer.LastReportedStatusTime | get-date -Uformat "%d %b %Y"
					if ($lastreportedstatustime -le $stale){
						write-host "computer $computername did not report since $stale  Last report: $lastreportedstatusdate" 
						$stalecomputers = $stalecomputers + "$computername ($lastreportedstatusdate); "
						$stalecomputerscount ++
					}
					#write-host "Starting computer $computername"
					# Finding NotInstalled Updates
					$updateScope.IncludedInstallationStates = 'NotInstalled'
					$notinstalledupdates = $computer.GetUpdateInstallationInfoPerUpdate($updateScope)
					$allnotinstalledupdates = $null
					$countniu = 0
					ForEach ($update in $notinstalledupdates){
						$updateinfo = $update.GetUpdate() | select @{N="KB";E={@($_.KnowledgebaseArticles[0])}},@{N="KBurl";E={@($_.AdditionalInformationUrls[0])}},creationdate,MsrcSeverity,UpdateClassificationTitle
						$updatekb = $updateinfo.kb
						$updatekburl = $updateinfo.kburl
						$updatekbcdate = $updateinfo.creationdate | get-date -Uformat "%d %b %Y"
						$severity = $updateinfo.MsrcSeverity
						$updatetype = $updateinfo.UpdateClassificationTitle
						$allnotinstalledupdates = $allnotinstalledupdates + "<a href=$updatekburl>$updatekb</a> - $updatekbcdate - $severity - $updatetype <br>"
						$countniu ++
					}
					# Finding Unknown Updates
					$updateScope.IncludedInstallationStates = 'Unknown'
					$unknownupdates = $computer.GetUpdateInstallationInfoPerUpdate($updateScope)
					$allunknownupdates = $null
					$countuu = 0
					ForEach ($update in $unknownupdates){
						$updateinfo = $update.GetUpdate() | select @{N="KB";E={@($_.KnowledgebaseArticles[0])}},@{N="KBurl";E={@($_.AdditionalInformationUrls[0])}},creationdate,MsrcSeverity,UpdateClassificationTitle
						$updatekb = $updateinfo.kb
						$updatekburl = $updateinfo.kburl
						$updatekbcdate = $updateinfo.creationdate | get-date -Uformat "%d %b %Y"
						$severity = $updateinfo.MsrcSeverity
						$updatetype = $updateinfo.UpdateClassificationTitle
						$allunknownupdates = $allunknownupdates + "<a href=$updatekburl>$updatekb</a> - $updatekbcdate - $severity - $updatetype <br>"
						$countuu ++
					}
					# Finding Reboot Pensing Updates
					$updateScope.IncludedInstallationStates = 'InstalledPendingReboot'
					$rebootupdates = $computer.GetUpdateInstallationInfoPerUpdate($updateScope)
					$allrebootupdates = $null
					$countipr = 0
					ForEach ($update in $rebootupdates){
						$updateinfo = $update.GetUpdate() | select @{N="KB";E={@($_.KnowledgebaseArticles[0])}},@{N="KBurl";E={@($_.AdditionalInformationUrls[0])}},creationdate,MsrcSeverity,UpdateClassificationTitle
						$updatekb = $updateinfo.kb
						$updatekburl = $updateinfo.kburl
						$updatekbcdate = $updateinfo.creationdate | get-date -Uformat "%d %b %Y"
						$severity = $updateinfo.MsrcSeverity
						$updatetype = $updateinfo.UpdateClassificationTitle
						$allrebootupdates = $allrebootupdates + "<a href=$updatekburl>$updatekb</a> - $updatekbcdate - $severity - $updatetype <br>"
						$countipr ++
					}
					# Define the number of update issues for this computer
					$totalcount = $countniu + $countuu + $countipr
					if ($totalcount -ge $maxissues){
						write-host "computer $computername has $totalcount issue" 
						$maxissuecomputers = $maxissuecomputers + "$computername ($totalcount); "
						$maxissuecomputerscount ++
					}
					# Write-Host "Group: $targetgroup Laptop: $computername NotInstalledUpdates ($countniu): $allnotinstalledupdates UnknownUpdates ($countuu): $allunknownupdates InstalledPendingReboot ($countipr): $allrebootupdates"
					Write-Host "Group: $targetgroup Laptop: $computername "
					$infowsus += '<table style="width:100%; border: 1px solid #dddddd; text-align: left;">'
					$infowsus += "<tr>"
					$infowsus += '<td style="width: 100px; text-align: left;">'
					$infowsus += "$targetgroup"
					$infowsus += '</td>'
					$infowsus += '<td style="width: 200px; text-align: left;">'
					$infowsus += "$computername"
					$infowsus += '</td>'
					$infowsus += '<td style="width: 100px; text-align: left;">'
					$infowsus += "$lastreportedstatusdate"
					$infowsus += '</td>'
					$infowsus += '<td style="width: 100px; text-align: left;">'
					$infowsus += "$lastsyncresult On $lastsynctime"
					$infowsus += '</td>'
					$infowsus += '<td style="width: 400px; text-align: left;">'
					if ($countniu -ne 0){
						$infowsus += "($countniu): $allnotinstalledupdates"
					}else{
						$infowsus += "&#10004;"
					}
					$infowsus += '</td>'
					$infowsus += '<td style="width: 400px; text-align: left;">'
					if ($countipr -ne 0){
						$infowsus += "($countipr): $allrebootupdates"
					}else{
						$infowsus += "&#10004;"
					}
					$infowsus += '</td>'
					$infowsus += '<td style="text-align: left;">'
					if ($countuu -ne 0){
						$infowsus += "($countuu): $allunknownupdates"
					}else{
						$infowsus += "&#10004;"
					}
					$infowsus += '</td>'
					$infowsus += "</tr>"
					$infowsus += "</table>"
 
				}
			$infoprio += '<table style="width:100%; border: 1px solid #dddddd; text-align: left;">'
			$infoprio += "<tr>"
			$infoprio += '<td style="width: 200px; text-align: left;">'
			$infoprio += "$wsusserver"
			$infoprio += '</td>'
			$infoprio += '<td style="width: 100px; text-align: left;">'
			$infoprio += "$targetgroup"
			$infoprio += '</td>'
			$infoprio += '<td style="width: 100px; text-align: left;">'
			$infoprio += "$groupclientscount"
			$infoprio += '</td>'
			$infoprio += '<td style="width: 300px; text-align: left;">'
			$infoprio += "($maxissuecomputerscount) - $maxissuecomputers"
			$infoprio += '</td>'
			$infoprio += '<td style="text-align: left;">'
			$infoprio += "($stalecomputerscount) - $stalecomputers"
			$infoprio += '</td>'
			$infoprio += "</tr>"
			$infoprio += "</table>"
			}
		}
		$infoprio += "<br>"
		}
	else{
		write-host "$wsusserver and "$env:userdnsdomain" do not match"
	}
}
 
 
 
########################################## Start Fase 5 ###########################################
 
# Collecting the totals 
$infototal += "<br>"
$infototal += '<table style="width:100%; border: 1px solid #dddddd; text-align: left;">'
$infototal += "<tr>"
$infototal += '<th style="width: 300px; text-align: left;">'
$infototal += "Total number of clients processed:"
$infototal += '</th>'
$infototal += '<th style="text-align: left;">'
$infototal += "$computercount "
$infototal += '</th>'
$infototal += "</tr>"
$infototal += "</table>"
$infototal += "<br>"
 
########################################## Start Fase 6 ###########################################
 
# Set the subject and combine the email body collecting all information 
$subject = "ICT Control Framework WSUS for month $monthdate - $env:userdnsdomain"
$body = $infoheader + $infotopdesk + $infoupdates + $infototal + $infoprio + $infowsus
 
Send-Email $subject $body
 
# Stop Logging
stop-transcript
You could leave a comment if you were logged in.
wsusreport.txt · Last modified: 2021/09/24 00:25 (external edit)