functions/get-addchealth.ps1
Function Get-ADDomainControllerHealth { [cmdletbinding()] [OutputType("ADDomainControllerHealth")] Param( [Parameter(HelpMessage = "Specify a domain controller to query for a list of domain controllers.")] [alias("dc", "domaincontroller")] [string]$Server, [Parameter(HelpMessage = "Specify an alternate credential. This will be used to query the domain and all domain controllers.")] [alias("RunAs")] [PSCredential]$Credential ) Begin { Write-Verbose "[$((Get-Date).TimeofDay) BEGIN ] Starting $($myinvocation.mycommand)" #set some default parameter values if ($PSBoundParameters.ContainsKey("Server")) { Write-Verbose "[$((Get-Date).TimeofDay) BEGIN ] Adding 'Get-AD*:Server' to script PSDefaultParameterValues" $script:PSDefaultParameterValues["Get-AD*:Server"] = $PSBoundParameters.Item("server") } #use the credential with any command that supports alternate credentials if ($PSBoundParameters.ContainsKey("Credential")) { Write-Verbose "[$((Get-Date).TimeofDay) BEGIN ] Adding '*:Credential' to script PSDefaultParameterValues" $script:PSDefaultParameterValues["*:Credential"] = $PSBoundParameters.Item("Credential") } } #begin Process { Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Getting a list of all domain controllers" $dcs = Get-ADDomainController -Filter * Foreach ($dc in $dcs) { Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Getting health detail for $($dc.hostname)" #create a temporary cimSession Try { Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Creating a temporary CIMSession" $tmpCS = New-CimSession -ComputerName $dc.name -ErrorAction Stop $cimParam = @{ CimSession = $tmpCS Classname = "" Property = "" } } Catch { Write-Warning "Failed to create a temporary CIMSession to $($dc.name). $($_.Exception.message)" Remove-Variable -Name tmpCS -ErrorAction SilentlyContinue } if ($tmpCS) { #get additional information via CIM $cimParam["Classname"] = "win32_logicaldisk" $cimParam["filter"] = "deviceid='c:'" $cimParam["Property"] = "Freespace", "Size" Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Getting free space on C:" $c = Get-CimInstance @cimParam $cimParam["Classname"] = "win32_NTEventLogFile" $cimParam["filter"] = "logfilename='security'" $cimParam["Property"] = "FileSize", "MaxFileSize" Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Getting security log percent used" $seclog = Get-CimInstance @cimParam $cimParam["Classname"] = "win32_service" $cimParam["filter"] = "name='ntds' or name='kdc' or name='adws' or name='dfsr' or name='dfs' or name='netlogon' or name = 'samss' or name='w32time'" $cimParam["Property"] = "Displayname", "Name", "State", "ProcessID", "StartMode", "Started" Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Getting critical service satus" $services = Get-CimInstance @cimParam | ForEach-Object { #create a custom typed object for each service $h = [ordered]@{ PSTypename = "ADDomainControllerService" Computername = $dc.hostname } foreach ($p in $cimParam.property) { $h.Add($p, $_.$p) } New-Object -TypeName psobject -Property $h } $cimParam["Classname"] = "win32_operatingsystem" $cimParam.remove("filter") $cimParam["Property"] = "LastBootUpTime", "TotalVisibleMemorySize", "FreePhysicalMemory" Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Getting uptime and memory utilization" $os = Get-CimInstance @cimParam #remove the temporary cimsession Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Removing the temporary CIMSession" $tmpCS | Remove-CimSession } #create a custom object [pscustomobject]@{ PSTypename = "ADDomainControllerHealth" Hostname = $dc.hostname IPAddress = $dc.IPv4Address OperatingSystem = $dc.OperatingSystem Uptime = (New-TimeSpan -Start $os.LastBootUpTime -End (Get-Date)) PctFreespace = [math]::Round(($c.Freespace / $c.Size) * 100, 2) PctFreeMemory = [math]::Round(($os.FreePhysicalMemory / $os.TotalVisibleMemorySize) * 100, 2) PctSecurityLog = [math]::Round( ($seclog.filesize / $seclog.MaxFileSize) * 100, 2 ) Services = $Services Roles = $dc.OperationMasterRoles IsGlobalCatalog = $dc.IsGlobalCatalog IsReadOnly = $dc.IsReadOnly DistinguishedName = $dc.ComputerObjectDN } } #foreach DC } #process End { Write-Verbose "[$((Get-Date).TimeofDay) END ] Ending $($myinvocation.mycommand)" } #end } #close Get-ADDomainControllerHealth |