Updated SCOM Agent Installation and Reporting Script

I found the following Script: Installation and Reporting Script. I found that in a big environment there was no error checking for installation status. Also found few other issues with how the AD query was done. Here is an Updated version of the Script to run in a LAB environment. This has been tested and functions in a SCOM 2012 r2 Environment with a large number of clients. This script will report on and automatically install agents on machines. The script can do more for machines that have failed installs (currently not included) that will be a future update. Please let me know your thoughts.

$DebugPreference = ‘continue’

$VerbosePreference = ‘continue’

Function Get-Server {

$strCategory = “computer”

$strOS = “Windows*Server*”

$objSearcher = [adsisearcher]“”

$objSearcher.Filter = (“(&(objectCategory=$strCategory)(OperatingSystem=$strOS))”)

$objSearcher.pagesize = 10

$objsearcher.sizelimit = 5000

$objSearcher.PropertiesToLoad.Add(“dnshostname”) | Out-Null

$objSearcher.Sort.PropertyName = “dnshostname”

$colResults = $objSearcher.FindAll()

foreach ($objResult in $colResults) {

if ($objResult.properties.dnshostname -ne $NULL)

{$objComputer = $objResult.Properties

$objComputer.dnshostname}

}

}

function Set-AlternatingCSSClasses {

[CmdletBinding()]

param(

[Parameter(Mandatory=$True,ValueFromPipeline=$True)]

[string]$HTMLFragment,

[Parameter(Mandatory=$True)]

[string]$CSSEvenClass,

[Parameter(Mandatory=$True)]

[string]$CssOddClass

)

[xml]$xml = $HTMLFragment

$table = $xml.SelectSingleNode(‘table’)

$classname = $CSSOddClass

foreach ($tr in $table.tr) {

if ($classname -eq $CSSEvenClass) {

$classname = $CssOddClass

} else {

$classname = $CSSEvenClass

}

$class = $xml.CreateAttribute(‘class’)

$class.value = $classname

$tr.attributes.append($class) | Out-null

}

$xml.innerxml | out-string

}

Write-Verbose (“[{0}] Reviewing user defined parameters” -f (Get-Date))

###User Defined Parameters

#SCOM Management Server

$SCOMMgmtServer = $NULL

#SCOM RMS Server

$SCOMRMS = $NULL

#Systems to Exempt from SCOM

$Exempt = Get-Content .\Exempt.txt

$Emailparams = @{

To = $NULL

From = $NULL

SMTPServer = $NULL

Subject = ‘SCOM Agent Audit’

BodyAsHtml = $True

}

#Get list of AD Servers

Write-Verbose (“[{0}] Getting list of servers from Active Directory” -f (Get-Date))

$ADServers = Get-Server

#Initialize SCOM SnapIn

Write-Verbose (“[{0}] Loading SCOM SnapIn” -f (Get-Date))

Add-PSSnapin Microsoft.EnterpriseManagement.OperationsManager.Client -ErrorAction SilentlyContinue

#Make SCOM Connection

Write-Verbose (“[{0}] Connecting to SCOM RMS Server: {1}” -f (Get-Date),$SCOMRMS)

New-ManagementGroupConnection -ConnectionString $SCOMRMS | Out-Null

#Connect to SCOM Provider

Write-Verbose (“[{0}] Connecting to SCOM Provider” -f (Get-Date))

Push-Location ‘OperationsManagerMonitoring::’

Write-Verbose (“[{0}] Connecting to SCOM Server: {1}” -f (Get-Date),$SCOMMgmtServer)

$MgmtServer = Get-ManagementServer | Where {$_.Name -eq $SCOMMgmtServer}

#Get all SCOM Agent Servers

Write-Verbose (“[{0}] Gathering all SCOM managed systems” -f (Get-Date))

$SCOMServers = Get-Agent | Select -Expand NetworkName | Sort

#Compare list to find servers not in SCOM

Write-Verbose (“[{0}] Filtering out all Non SCOM managed systems to audit” -f (Get-Date))

$NonSCOMTEMP1 = @(Compare-Object -ReferenceObject $SCOMServers -DifferenceObject $ADServers | Where {

$_.SideIndicator -eq ‘=>’

} | Select -Expand Inputobject)

$pendingactions1 = Get-SCOMPendingManagement | where {$_.AgentPendingActionType -eq “PushInstall”}

$pendingactions = $pendingactions1.agentname

#Compare list to find servers not already in pending action

Write-Verbose (“[{0}] Filtering out all SCOM pending action systems” -f (Get-Date))

if($pendingactions) {$NonSCOMTEMP = @(Compare-Object -ReferenceObject $pendingactions -DifferenceObject $nonSCOMTemp1 | Where {

$_.SideIndicator -eq ‘=>’

} | Select -Expand Inputobject)

}

else { $NonSCOMTEMP = $NonSCOMTEMP1 }

$NonSCOMTEMP

#Attempt to Discover Systems

Write-Verbose (“[{0}] Configuring SCOM discovery prior to use” -f (Get-Date))

$Discover = New-WindowsDiscoveryConfiguration -ComputerName $NonSCOMTemp -PerformVerification -ComputerType “Server”

$Discover.ComputerNameDiscoveryCriteria.getComputernames() | ForEach {Write-Verbose (“{0}: Attempting to discover” -f $_)}

Write-Verbose (“[{0}] Beginning SCOM discovery” -f (Get-Date))

$DiscResults = @(Start-Discovery -WindowsDiscoveryConfiguration $Discover -ManagementServer $MgmtServer)

#Check Alert history for failed Discoveries

Write-Verbose (“[{0}] Checking for failed Discoveries” -f (Get-Date))

$alerts = @(Get-Alert -Criteria “PrincipalName = ‘$SCOMMgmtServer‘ AND MonitoringClassId=’ab4c891f-3359-3fb6-0704-075fbfe36710’`

AND Name=’An error occurred during computer verification from the discovery wizard'”) | Where {

#Look for unresolved alerts

$_.ResolutionState -eq 0

}

If ($Alerts.count -gt 0) {

#Start processing the failed discovery alerts

$alert = $alerts | Select -Expand Parameters

$alert = $alert | Where-object {$_ } | sort -unique

$Pattern = “Machine Name: ((\w+|\.|\-)*)\s”

$FailedDiscover = $alert | ForEach { $Server = ([regex]::Matches($_,$Pattern))[0].Groups[1].Value

Try {

$ServerIP = ([net.dns]::Resolve($Server).AddressList[0])

} Catch {

$ServerIP = $Null

}

If (-Not ([string]::IsNullOrEmpty($Server))) {

New-Object PSObject -Property @{

Server = $Server

Reason = $_

IP = $ServerIP

}

}

}

<#

Resolve the alerts for failed discoveries, otherwise we will have false positives that there were no failed discoveries.

#>

Write-Verbose (“[{0}] Resolving active alerts” -f (Get-Date))

$Alerts | ForEach {

Resolve-Alert -Alert $_ | Out-Null

}

}

#Install Agent on Discovered Servers

Write-Verbose (“[{0}] Beginning installation of SCOM Agent on discovered systems” -f (Get-Date))

$DiscResults.custommonitoringobjects | ForEach {Write-Verbose (“{0}: Attempting Agent Installation” -f $_.Name)}

$Results = Install-Agent -ManagementServer $MgmtServer -AgentManagedComputer: $DiscResults.custommonitoringobjects

#Check for failed installations

$FailedInstall = @{}

$SuccessInstall = @{}

Write-Verbose (“[{0}] Checking for Failed and Successful installations” -f (Get-Date))

$Results.MonitoringTaskResults | ForEach {

$result = $_

If (([xml]$result.Output).DataItem.ErrorCode -ne 0) {

#Failed Installation

$FailedInstall[([xml]$result.Output).DataItem.PrincipalName] = `

(([xml]$result.output).DataItem.Description.“#cdata-section” -split “\s{2,}”)[0]

} Else {

#Successful Installation

$SuccessInstall[([xml]$_.Output).DataItem.PrincipalName] = `

Get-Date ([xml]$result.output).DataItem.Time

}

}

$head=@”

<style>

h1 {

text-align:center;

border-bottom:1px solid #666666;

color:green;

}

TABLE {

TABLE-LAYOUT: fixed;

FONT-SIZE: 100%;

WIDTH: 100%

}

* {

margin:0

}

.pageholder {

margin: 0px auto;

}

td {

VERTICAL-ALIGN: TOP;

FONT-FAMILY: Tahoma

}

th {

VERTICAL-ALIGN: TOP;

COLOR: #018AC0;

TEXT-ALIGN: left;

background-color:LightSteelBlue;

color:Black;

}

body {

text-align:left;

font-smoothing:always;

width:100%;

}

.odd { background-color:#ffffff; }

.even { background-color:#dddddd; }

</style>

“@

$htmlFragment =

If ($SuccessInstall.Count -gt 0) {

Write-Verbose (“[{0}] Adding {1} Successful installations to report” -f $SuccessInstall.Count,(Get-Date))

$pre = “<h2>The following servers were found in Active Directory and had the <font color=’green’>SCOM Agent successfully installed</font>:</h2>”

$post = “<br>”

$body = ($SuccessInstall.GetEnumerator() | Select Name, @{L=‘Date’;E={$_.Value}} | Sort Name |

ConvertTo-Html -Fragment | Out-String | Set-AlternatingCSSClasses -CSSEvenClass ‘even’ -CssOddClass ‘odd’)

$htmlFragment += $pre,$body,$post

}

If ($FailedInstall.Count -gt 0) {

Write-Verbose (“[{0}] Adding {1} Failed installations to report” -f $FailedInstall.Count,(Get-Date))

$pre = “<h2>The following servers are in Active Directory and were discovered, but <font color=’red’>failed to install the SCOM Agent</font>:</h2>”

$post = “<br>”

$body = ($FailedInstall.GetEnumerator() | Select Name, @{L=‘Reason’;E={$_.Value}} | Sort Name |

ConvertTo-Html -Fragment | Out-String | Set-AlternatingCSSClasses -CSSEvenClass ‘even’ -CssOddClass ‘odd’)

$htmlFragment += $pre,$body,$post

}

If ($FailedDiscover.Count -gt 0) {

Write-Verbose (“[{0}] Adding {1} Failed Discoveries to report” -f $FailedDiscover.Count,(Get-Date))

$pre = “<h2>The following servers are in Active Directory but <font color=’red’>failed to be Discovered by SCOM</font>:</h2>”

$post = “<br>”

$body = ($FailedDiscover | Sort Server |

ConvertTo-Html -Fragment | Out-String | Set-AlternatingCSSClasses -CSSEvenClass ‘even’ -CssOddClass ‘odd’)

$htmlFragment += $pre,$body,$post

}

If ($FailedDiscover.Count -ge 0 -OR $FailedInstall.Count -ge 0 -OR $SuccessInstall.Count -ge 0) {

$report = ConvertTo-Html -Head $head -Title “Cluster Report” -PreContent “<H1><font color=’white’>Please view in html!</font><br>SCOM Agent Installation Report</H1>” `

-PostContent $($htmlFragment)<i>Report generated on $((Get-Date).ToString())</i>” | Out-String

$Emailparams.Body = $report

Write-Verbose (“[{0}] Sending Audit report to list of recipients.” -f (Get-Date))

Send-MailMessage @Emailparams

}

#Back to starting location

Pop-Location

 

 

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s