My boss asked me to build a report consisting of the Forefront status for each workstation and server on our network. Herein lies a subset of everything I've learned about working with WSUS through PowerShell.
Taking your first steps - Install the WSUS 3.0 SP2 client administration tools : http://www.microsoft.com/...e40&displaylang=en
- This code does not have to be run as administrator
- Load the PowerShell Snapin:
- [reflection.assembly]::LoadWithPartialName("Microsoft.UpdateServices.Administration") | out-null;
- Add-PSSnapin Quest.ActiveRoles.ADManagement -ErrorAction SilentlyContinue;
- Connect to the WSUS Server:
- $wsus = [Microsoft.UpdateServices.Administration.AdminProxy]::GetUpdateServer(<WSUS Server Name>,<Use HTTPS>,<WSUS Port Number>);
- Begin querying against WSUS directly
How to Query WSUS through PowerShell Once you have a connection to the WSUS server, let your imagination run wild. This $wsus object that we've built here is the foundation for everything else you will want to know or do with WSUS. Try running "$wsus | Get-Member Get*". Many of these will return objects with their own set of properties. Sometimes a returned object doesn't tell you much. There might be a Get-* method of the $wsus object that will pull more information from the WSUS database about the object you're interested in; more on this later...
Does a computer exist within WSUS?
$ErrorActionPreference = "SilentlyContinue";
&{#Contain the scope of the Try Block
#If you don't, this single Trap will trap
#all errors for the entire program. This is a Very Bad Thing.
#http://huddledmasses.org/trap-exception-in-powershell/
&{#Try
$WSUScomputer = $wsus.GetComputerTargetByName("ComputerName.Domain.com");
#The above command might throw an error.
#If it does, the trap section will be activated
#If not, then we know the computer is in WSUS
<Do stuff here...>
}
### CATCH NullReference and IndexOutOfRange, etc
trap [SystemException] {
$Error.Clear();
# It turns out that this machine was not found in WSUS
<Do stuff here...>
}
}
Get all updates installed on a single computer In this block of code we are going to create an object for a single computer in the WSUS database. Then we are going to enumerate all installed updates on it. But the information about the update is rather limited. We will pass what little information we have about any particular update back in to the $wsus object and retrieve tons more data from the database.
#Create An Update Scope Object
$updateScope = new-object Microsoft.UpdateServices.Administration.UpdateScope;
#Create a filter within the Update Scope Object
#Only list updates that are installed
$updateScope.IncludedInstallationStates = [Microsoft.UpdateServices.Administration.UpdateInstallationStates]::Installed;
#Grab the computer using the $wsus object.
$Computer = $wsus.GetComputerTargetByName($ComputerName);
#Get the list of INSTALLED updates
$InstalledUpdates = $Computer.GetUpdateInstallationInfoPerUpdate($updateScope);
#Run through each update in $InstalledUpdates
ForEach ($InstalledUpdate in $InstalledUpdates) {
<Do stuff here...>
#Want to take a look at the details of each Update Object? Try this..
$InstalledUpdate | GM
$InstalledUpdate | Format-List [a-z]*
#Doesn't tell you much, right? We need to pass this information back in
#to the $wsus object to pull more information about it.
$UpdateObject = $wsus.GetUpdate($InstalledUpdate.UpdateId)
#Now try running the following command...
$UpdateObject | Format-List [a-z]*
#See how much information you can pull back about each update?
}
In the previous example, you saw me use an update scope object. -->
$updateScope = new-object Microsoft.UpdateServices.Administration.UpdateScope;
This update scope object is only one of many objects used to filter the data returned by your query. Try typing "New-Object Microsoft.UpdateServices.Administration." and scroll down through the list of items in the auto-complete box. Those items that end with "Scope" can be used for filtering results. Or if you prefer MSDN...
UpdateScope Class Once you've selected the filter type you want to use, there (are/should be) different ways to filter. I know from personal experience you can filter updates on installation state or a textual search. For example, if you want to filter by installation states: using PowerGUI, begin typing
$updateScope.IncludedInstallationStates = [Microsoft.UpdateServices.Administration.
Auto-complete boxes will begin appearing at each level. Select the path you want, and finish it off by typing "]::" Constants will be enumerated within another auto-complete box. This is one of the best ways to find out what your options are when writing code within PowerGUI. Some of the installation states are "Installed", "Failed", "NotInstalled". Check PowerGUI or MSDN for more (
UpdateInstallationState Enumeration). If you want to filter by text, try this:
$updateScope.TextIncludes = "Forefront"
You can combine the two filters.
Finally, apply the filter to a search like this:
#Grab the computer using the $wsus object.
$Computer = $wsus.GetComputerTargetByName($Computers[$i].Name);
#Get the list of INSTALLED updates with the text "Forefront"
$InstalledUpdates = $Computer.GetUpdateInstallationInfoPerUpdate($updateScope);
This wasn't meant to be a front-to-back covering of WSUS + Powershell, but rather a short tutorial to help you get over the initial learning curve of working within the WSUS provider. I hope it helps.
The code I run on a daily basis to generate a report:
cls
[reflection.assembly]::LoadWithPartialName("Microsoft.UpdateServices.Administration") | out-null;
Add-PSSnapin Quest.ActiveRoles.ADManagement -ErrorAction SilentlyContinue;
function Write-Header {
Param ([System.String]$HeaderText,
[System.Int32]$LineSize,
[System.Int32]$BorderSize,
[System.Boolean]$IncludeUnderline,
[System.String]$TextAlign)
if ($IncludeUnderline -eq $null) { $IncludeUnderline = $true }
if (($TextAlign -eq "left") -or ($TextAlign -eq "center") -or ($TextAlign -eq "right")) {}
else {$TextAlign = "center"}
if ($LineSize -gt 80) {$LineSize = 80}
if ($LineSize -lt 10) {$LineSize = 10}
if ($BorderSize -gt [System.Int32]($LineSize * .4)) {$BorderSize = [System.Int32]($LineSize * .4)}
if ($BorderSize -lt 0) {$BorderSize = 0}
$HeaderArray = $HeaderText.Split(' ');
ForEach ($Word in $HeaderArray) {
If ($Word.Length -gt ($LineSize - 2*($BorderSize))) {
$LineSize = $Word.Length + 2*($BorderSize);
}
}
$MaxTextLength = $LineSize - 2*($BorderSize);
$OutputText = "";
For ($Word = 0; $Word -lt $HeaderArray.Count; $Word++) {
If ($HeaderArray[$Word] -eq ' ') {$HeaderArray[$Word] = ''}
If ($OutputText.length -ne 0) { $OutputText += ' ' }
# If there is room to add another word to $OutputText, do so.
If (($OutputText + $HeaderArray[$Word]).length -le $MaxTextLength) {
$OutputText += $HeaderArray[$Word];
}
# If there is not enough room to add another word to $OutputText or
# there are no more words left, write out $OutputText
$WriteOutput = $false;
If (($Word + 1) -eq $HeaderArray.Count) { $WriteOutput = $true }
ElseIf (($OutputText + ' ' + $HeaderArray[$Word + 1]).length -gt $MaxTextLength) { $WriteOutput = $true }
If ($WriteOutput) {
$OutputText = $OutputText.Trim()
Switch ($TextAlign)
{
"left" {$padding = "";}
"center" {$padding = $(" " * [System.Int32]($LineSize/2 - $OutputText.length/2));}
"right" {$padding = $(" " * ($LineSize - $OutputText.length));}
}
Write-Host ($padding + $OutputText);
$OutputText = "";
}
}
If ($IncludeUnderline) { Write-Host ("=" * $LineSize) }
}
function Get-LatestForefrontDefinitionVersions {
Param([System.Object]$WSUSserver)
$SecurityState = 0;
$AntiMalware = 1;
$LatestDefinitions = @();
$LatestDefinitions += $null;
$LatestDefinitions += $null;
$updates = $WSUSserver.GetUpdates() |
Where-Object { `
($_.ProductTitles -contains 'Forefront Client Security') `
-and ($_.IsDeclined -eq $False) `
-and ($_.IsLatestRevision -eq $true) `
-and ($_.IsSuperseded -eq $false) `
}
ForEach ($update in $updates) {
If ($update.Title.Contains('Definition')) {
If ($update.Title.Contains('Security State Assessment')) {
If ($LatestDefinitions[$SecurityState] -eq $null) {
$LatestDefinitions[$SecurityState] = $update;
}
else {
#Example String:
# Definition Update for Microsoft Forefront Client Security (Security State Assessment 1.0.1710.41 Full)
If ($LatestDefinitions[$SecurityState].CreationDate -lt $update.CreationDate) {
$LatestDefinitions[$SecurityState] = $update;
}
}
}
If ($update.Title.Contains('Antimalware')) {
If ($LatestDefinitions[$AntiMalware] -eq $null) {
$LatestDefinitions[$AntiMalware] = $update;
}
else {
#Example String:
# Definition Update for Microsoft Forefront Client Security (Antimalware 1.59.592.0)
If ($LatestDefinitions[$AntiMalware].CreationDate -lt $update.CreationDate) {
$LatestDefinitions[$AntiMalware] = $update;
}
}
}
}
}
Return $LatestDefinitions;
}
Function Test-DotNotation {
Param ( $NumberLeft = "",
$Test = "",
$NumberRight = "" )
# Examples how to use this code:
# cls
# $NumberOne = "1.1.10.0";
# $NumberTwo = "1.1.1.3"
# Write-Host "Equals";
# Test-DotNotation $NumberOne "=" $NumberTwo "dotted";
# Test-DotNotation $NumberOne "-eq" $NumberTwo "dotted";
# Write-Host "`nLess Than";
# Test-DotNotation $NumberOne "<" $NumberTwo "dotted";
# Test-DotNotation $NumberOne "-lt" $NumberTwo "dotted";
# Write-Host "`nGreater Than";
# Test-DotNotation $NumberOne ">" $NumberTwo "dotted";
# Test-DotNotation $NumberOne "-gt" $NumberTwo "dotted";
# Write-Host "`nLess Than or Equals";
# Test-DotNotation $NumberOne "<=" $NumberTwo "dotted";
# Test-DotNotation $NumberOne "=<" $NumberTwo "dotted";
# Test-DotNotation $NumberOne "-le" $NumberTwo "dotted";
# Write-Host "`nGreater Than or Equals";
# Test-DotNotation $NumberOne ">=" $NumberTwo "dotted";
# Test-DotNotation $NumberOne "=>" $NumberTwo "dotted";
# Test-DotNotation $NumberOne "-ge" $NumberTwo "dotted";
If (($NumberLeft -eq "") `
-or ($Test -eq "") `
-or ($NumberRight -eq ""))
{ Return -1; }
# Manipulate $NumberLeft and $NumberRight into a type that can be
# used internally within this function with ease
$SegmentCountLeft = ([string]$NumberLeft).Split(".").count;
$SegmentCountRight = ([string]$NumberRight).Split(".").count;
if ($SegmentCountLeft -gt $SegmentCountRight) {$CounterMax = $SegmentCountLeft;}
else {$CounterMax = $SegmentCountRight;}
$StringLeft = "";
$StringRight = "";
For ($Counter = 0; $Counter -lt $CounterMax; $Counter++) {
Switch ($true)
{
($Counter -eq 0) {
$StringLeft += ([string]$NumberLeft).Split(".")[$Counter];
$StringRight += ([string]$NumberRight).Split(".")[$Counter];
}
($Counter -ge $SegmentCountLeft) {
$StringLeft += ("0" * ([string]$NumberRight).Split(".")[$Counter].length);
$StringRight += ([string]$NumberRight).Split(".")[$Counter];
}
($Counter -ge $SegmentCountRight) {
$StringLeft += ([string]$NumberLeft).Split(".")[$Counter];
$StringRight += ("0" * ([string]$NumberLeft).Split(".")[$Counter].length);
}
default {
if ((([string]$NumberLeft).Split(".")[$Counter].length) `
-gt (([string]$NumberRight).Split(".")[$Counter].length)) {
$StringLeft += ([string]$NumberLeft).Split(".")[$Counter];
$StringRight += ("0" * (([string]$NumberLeft).Split(".")[$Counter].length - ([string]$NumberRight).Split(".")[$Counter].length));
$StringRight += ([string]$NumberRight).Split(".")[$Counter];
}
else {
$StringLeft += ("0" * (([string]$NumberRight).Split(".")[$Counter].length - ([string]$NumberLeft).Split(".")[$Counter].length));
$StringLeft += ([string]$NumberLeft).Split(".")[$Counter];
$StringRight += ([string]$NumberRight).Split(".")[$Counter];
}
}
}
}
$NumberLeft = [System.Double]$StringLeft;
$NumberRight = [System.Double]$StringRight;
Switch ($Test)
{
"=" {Return $NumberLeft -eq $NumberRight}
"-eq" {Return $NumberLeft -eq $NumberRight}
">" {Return $NumberLeft -gt $NumberRight}
"-gt" {Return $NumberLeft -gt $NumberRight}
"<" {Return $NumberLeft -lt $NumberRight}
"-lt" {Return $NumberLeft -lt $NumberRight}
"<=" {Return $NumberLeft -le $NumberRight}
"=<" {Return $NumberLeft -le $NumberRight}
"-le" {Return $NumberLeft -le $NumberRight}
">=" {Return $NumberLeft -ge $NumberRight}
"=>" {Return $NumberLeft -ge $NumberRight}
"-ge" {Return $NumberLeft -ge $NumberRight}
default { Return -1; }
}
}
$Computers = @();
#Status Values
$UnScanned = 0;
$Not_In_WSUS = 1;
$In_WSUS = 2;
$Forefront_Installed_And_Up2Date = 3;
$Forefront_Installed_But_Not_Up2Date = 4;
$Forefront_Not_Installed = 5;
# Constants
$SecurityState = 0;
$AntiMalware = 1;
$WsusServerName = '<wsus server>.<DOMAIN>.com';
$WsusServerPort = 8530
#Step 01: Connect to WSUS. Get the Newest Forefront Client Versions (NFCV).
# The First number is the Security State version. The second is the Antimalware version.
$wsus = [Microsoft.UpdateServices.Administration.AdminProxy]::GetUpdateServer($WsusServerName,$false,$WsusServerPort);
$ForefrontDefinitionVersions = Get-LatestForefrontDefinitionVersions $wsus;
#Step 02: Build a list of all computers in the domain.
ForEach ($computer in Get-QADComputer) {
$Computers += New-Object psObject;
$LastElement = $Computers.length -1;
$Computers[$LastElement] = Add-Member `
-PassThru `
-InputObject $Computers[$LastElement] `
-MemberType NoteProperty `
-Name "Name" `
-Value $($computer.Name + ".<DOMAIN>.com");
$Computers[$LastElement] = Add-Member `
-PassThru `
-InputObject $Computers[$LastElement] `
-MemberType NoteProperty `
-Name "Status" `
-Value $UnScanned;
$Computers[$LastElement] = Add-Member `
-PassThru `
-InputObject $Computers[$LastElement] `
-MemberType NoteProperty `
-Name "ForefrontInstalled" `
-Value $false;
$Computers[$LastElement] = Add-Member `
-PassThru `
-InputObject $Computers[$LastElement] `
-MemberType NoteProperty `
-Name "ForefrontUp2Date" `
-Value $false;
$Computers[$LastElement] = Add-Member `
-PassThru `
-InputObject $Computers[$LastElement] `
-MemberType NoteProperty `
-Name "ForefrontSecurityStateDate" `
-Value "0";
$Computers[$LastElement] = Add-Member `
-PassThru `
-InputObject $Computers[$LastElement] `
-MemberType NoteProperty `
-Name "ForefrontAntimalwareDate" `
-Value "0";
$Computers[$LastElement] = Add-Member `
-PassThru `
-InputObject $Computers[$LastElement] `
-MemberType NoteProperty `
-Name "ForefrontSecurityStateVersion" `
-Value "0";
$Computers[$LastElement] = Add-Member `
-PassThru `
-InputObject $Computers[$LastElement] `
-MemberType NoteProperty `
-Name "ForefrontAntimalwareVersion" `
-Value "0";
}
#Step 03: Lookup each computer in WSUS to see if it exists there.
#Step 03: Does it exist within WSUS? Yes -> Mark the status as being in WSUS.
#Step 03: Does it exist within WSUS? No -> Mark the status as not being in WSUS.
$ErrorActionPreference = "SilentlyContinue";
$Error.Clear();
For ($i = 0; $i -lt $Computers.Count; $i++) {
# Try finding $Computers[$i].Name in WSUS
# If $Computers[$i].Name is not found, an error will be thrown
&{#Contain the scope of the Try Block
#If you don't, this single Trap will trap
#all errors for the entire program. Bad.
#http://huddledmasses.com/trap-exception-in-powershell/
&{#Try
$WSUScomputer = $wsus.GetComputerTargetByName($Computers[$i].Name);
#The above command might throw an error. Even if it does,
# continue like it didn't. If it does, the trap section
# that follows immediately will overwrite the status of
# $Computers[$i].Status
$Computers[$i].Status = $In_WSUS;
}
### CATCH NullReference and IndexOutOfRange, etc
trap [SystemException] {
$Error.Clear();
# It turns out that this machine was not found in
# WSUS. Mark the status as not being in WSUS.
$Computers[$i].Status = $Not_In_WSUS;
}
}
}
$ErrorActionPreference = "Stop";
#Step 04: Find the installed 'Security State' and 'Antimalware' versions for
# each computer that has the status of $In_WSUS.
#Search only installed updates that include the text 'Forefront'.
$updateScope = new-object Microsoft.UpdateServices.Administration.UpdateScope;
$updateScope.IncludedInstallationStates = `
[Microsoft.UpdateServices.Administration.UpdateInstallationStates]::Installed;
$updateScope.TextIncludes = "Forefront";
For ($i = 0; $i -lt $Computers.Count; $i++) {
#Only inspect the computer if it is in WSUS
If ($Computers[$i].Status -eq $In_WSUS) {
Write-Host `n`n===============================
#Grab the computer using the $wsus object.
$Computer = $wsus.GetComputerTargetByName($Computers[$i].Name);
#Get the list of INSTALLED updates with the text "Forefront"
$InstalledUpdates = $Computer.GetUpdateInstallationInfoPerUpdate($updateScope);
#Run through each update in $InstalledUpdates
#Pass the UpdateID to $wsus.GetUpdate() to retrieve the title
#In the title are the key words we are looking for:
# * "Security State Assessment"
# * "Antimalware"
ForEach ($InstalledUpdate in $InstalledUpdates) {
$UpdateObject = $wsus.GetUpdate($InstalledUpdate.UpdateId)
$UpdateTitle = $UpdateObject.Title;
$UpdateCreationDate = $UpdateObject.CreationDate;
switch ($true)
{
#More than one AntiMalware version may be installed.
$($UpdateTitle.contains("Antimalware")) {
#Example String:
# Definition Update for Microsoft Forefront Client Security (Antimalware 1.59.592.0)
#Extract and compare the DotNotation version number
$DottedNumberOne = [system.Text.RegularExpressions.Regex]::Replace($UpdateTitle.split(" ")[8],"[^0-9.]","");
$DottedNumberTwo = [system.Text.RegularExpressions.Regex]::Replace($Computers[$i].ForefrontAntimalwareVersion,"[^0-9.]","");
if (Test-DotNotation $DottedNumberOne "-gt" $DottedNumberTwo) {
$Computers[$i].ForefrontAntimalwareDate = $UpdateCreationDate.ToString();
$Computers[$i].ForefrontAntimalwareVersion = $DottedNumberOne;
}
#Write-Host $($Computers[$i].Name + " ForefrontAntimalware " + $UpdateCreationDate.ToString() + " " + $Computers[$i].ForefrontAntimalwareVersion);
}
$($UpdateTitle.contains("Security State Assessment")) {
#Example String:
# Definition Update for Microsoft Forefront Client Security (Security State Assessment 1.0.1710.41 Full)
#Extract and compare the DotNotation version number
$DottedNumberOne = [system.Text.RegularExpressions.Regex]::Replace($UpdateTitle.split(" ")[10],"[^0-9.]","");
$DottedNumberTwo = [system.Text.RegularExpressions.Regex]::Replace($Computers[$i].ForefrontSecurityStateVersion,"[^0-9.]","");
if (Test-DotNotation $DottedNumberOne "-gt" $DottedNumberTwo) {
$Computers[$i].ForefrontSecurityStateDate = $UpdateCreationDate.ToString();
$Computers[$i].ForefrontSecurityStateVersion = $DottedNumberOne;
}
#Write-Host $($Computers[$i].Name + " ForefrontSecurityState " + $UpdateCreationDate.ToString() + " " + $Computers[$i].ForefrontSecurityStateVersion);
}
}
}
#Write-Host "Winner: " + $Computers[$i].ForefrontAntimalwareVersion + " " + $Computers[$i].ForefrontSecurityStateVersion
}
}
#Step 05: For each client in WSUS query WSUS to see if it has the latest Forefront Updates
#Step 05: Does it have the latest versions installed? Yes -> Update the status to $Forefront_Installed_And_Up2Date
#Step 05: Does it have the latest versions installed? No -> Update the status to $Forefront_Installed_But_Not_Up2Date
$updateScope = new-object Microsoft.UpdateServices.Administration.UpdateScope;
$updateScope.IncludedInstallationStates = `
[Microsoft.UpdateServices.Administration.UpdateInstallationStates]::Installed
For ($i = 0; $i -lt $Computers.Count; $i++) {
#Only inspect the computer if it is in WSUS
If ($Computers[$i].Status -eq $In_WSUS) {
#Mark the Up2Date property as true.
#If any of the updates are not installed, then mark the flag false.
$Computers[$i].ForefrontUp2Date = $true;
#Grab the computer using the $wsus object.
$Computer = $wsus.GetComputerTargetByName($Computers[$i].Name);
#Does this computer have ANY Forefront Updates installed?
$updateScope.TextIncludes = "Forefront";
$InstalledUpdates = $Computer.GetUpdateInstallationInfoPerUpdate($updateScope);
For ($j = 0; $j -lt $InstalledUpdates.Count; $j++) {
If ($InstalledUpdates[$j].UpdateInstallationState -eq "Installed") {
#An installed Forefront update was found.
#Mark the flag that signals so.
$Computers[$i].ForefrontInstalled = $true;
#Set the status that Forefront is installed but not up to date.
#We will verify "up2dateness" next.
$Computers[$i].Status = $Forefront_Installed_But_Not_Up2Date;
#FastForward the counter $j beyond $InstalledUpdates.Count so we may exit from this loop
$j = $InstalledUpdates.Count + 1;
}
}
#Loop through each of the updates as defined within $ForefrontDefinitionVersions
For ($j = 0; $j -lt $ForefrontDefinitionVersions.Count; $j++) {
#To narrow the scope of the search so it returns just one update,
#make sure $updateScope.TextIncludes the entire title of the update.
$updateScope.TextIncludes = $ForefrontDefinitionVersions[$j].Title;
#Check each update to make sure it is installed.
If ($($Computer.GetUpdateInstallationInfoPerUpdate($updateScope)).UpdateInstallationState -ne "Installed") {
$Computers[$i].ForefrontUp2Date = $false;
}
}
#Now that we've this computer against all of the latest Forefront version updates,
# Is this computer Up2Date?
If ($Computers[$i].ForefrontUp2Date) {
$Computers[$i].Status = $Forefront_Installed_And_Up2Date;
}
}
}
# How to read this report
Write-Header "How to Read This Report" 80 5 $true
Write-Header "This is report displays the current status of the Forefront Security Suite." 80 0 $false "left"
Write-Output ""
Write-Header "You may see computers without Forefront installed, or without an entry in WSUS, or have out of date definitions. Here is the reason why: The computers mentioned herein were generated by obtaining a list of all computer objects registered in <DOMAIN>'s Active Directory. Many of these computers are active on our network. These active machines will update themselves on a regular basis. But others are virtual machines used for testing and therefore are only turned on when needed. These virtual machines may appear to be out of date, but will obtain the latest definitions the next time they are turned on. Some computers in the list don't physically exist anymore, but their entry in Active Directory remains. These non-existant machines will never be up to date. Some are project owned computers that were prepared on this network and then sent to remote users. These will obtain updates directly from Microsoft automtically but cannot update their status in our WSUS server. These remote machines will appear to be out of date. The last are laptops and were distributed to local and remote users. These laptops will receive updates directly from Microsoft when they are not on our network, and from us when they are plugged into Contoso's network. These laptops can only update their status in WSUS when they are on our network." 80 0 $false "left"
Write-Output ""
Write-Header "A computer is up to date if its 'Anti-Malware' and 'Security State' dates match the dates listed in the 'Latest Published Definitions' section below." 80 0 $false "left"
Write-Output ""
Write-Output ""
#Step 06: Write Header for the latest definitions.
#Step 06: Write contents of the latest definitions.
Write-Header "Latest Published Definitions" 80 5 $true "center"
Write-Host "Anti-Malware: " $ForefrontDefinitionVersions[$AntiMalware].creationdate;
Write-Host "Security State: " $ForefrontDefinitionVersions[$SecurityState].creationdate;
Write-Host "`n"
#Step 06: Write Header for the Installed_And_Pass list.
#Step 06: Write contents of the Installed_And_Pass list.
Write-Header "Computers With Forefront and Up2Date" 80 5 $true "center"
$Computers |
Where-Object {$_.Status -eq $Forefront_Installed_And_Up2Date} |
Where-Object {($_.ForefrontSecurityStateDate -ne 0) -or ($_.ForefrontAntimalwareDate -ne 0)} |
Sort-Object -Descending ForefrontAntimalwareDate |
Format-Table Name, ForefrontSecurityStateDate, ForefrontAntimalwareDate -AutoSize
Write-Host `n`n`n
#Step 07: Write Header for the Installed_But_Fail list.
#Step 07: Write contents of the Installed_But_Fail list.
Write-Header "Computers With Forefront Installed But at Least One Update Has Not Been Applied" 80 5 $true "center"
$Computers |
Where-Object {$_.Status -eq $Forefront_Installed_But_Not_Up2Date} |
Where-Object {($_.ForefrontSecurityStateDate -ne 0) -or ($_.ForefrontAntimalwareDate -ne 0)} |
Sort-Object -Descending ForefrontAntimalwareDate |
Format-Table Name, ForefrontSecurityStateDate, ForefrontAntimalwareDate -AutoSize
Write-Host `n`n`n
#Step 08: Write Header for the Unscanned computers list.
#Step 08: Write contents of the Unscanned computers list.
Write-Header "Computers UnScanned" 36 5 $true "center"
For ($i = 0; $i -lt $Computers.Count; $i++) {
If ($Computers[$i].Status -eq $UnScanned) {
Write-Host $Computers[$i].Name;
}
}
Write-Host `n`n`n
#Step 09: Write Header for the list of computers not in WSUS.
#Step 09: Write contents of the list of computers not in WSUS.
Write-Header "Computers Not In WSUS" 36 5 $true "center"
For ($i = 0; $i -lt $Computers.Count; $i++) {
If ($Computers[$i].Status -eq $Not_In_WSUS) {
Write-Host $Computers[$i].Name;
}
}
Write-Host `n`n`n
#Step 10: Write Header for the list of computers not in WSUS.
#Step 10: Write contents of the list of computers not in WSUS.
Write-Header "Computers Without Forefront Installed" 36 5 $true "center"
For ($i = 0; $i -lt $Computers.Count; $i++) {
If ($Computers[$i].Status -eq $In_WSUS) {
Write-Host $Computers[$i].Name;
}
}
#Step 11: Exit
Exit;