compwiz32 / PSADHealth

A toolkit of AD specific health checks that you can run in your environment to ensure your Active Directory is running optimally.
GNU General Public License v2.0
149 stars 19 forks source link

Improvments #107

Open Rapidhands opened 1 year ago

Rapidhands commented 1 year ago

Hi Mike, A long time ago, you wrote the module. Today, I've studied with attention, some of the internal functions. i.e. Test-AdServices. I've modified your code to

function Test-ADServices
{
    [cmdletBinding()]
    [OutputType([System.Object])]
    Param()

    begin
    {
        Import-Module ActiveDirectory
    }

    process
    {
        Write-Verbose -Message 'Restrieve Domain Controllers List from AD'
        $DClist = (Get-ADGroupMember 'Domain Controllers').name
        Write-Verbose -Message 'List of Services to monitor'
        $Collection = @('ADWS',
            'DHCPServer',
            'DNS',
            'DFS',
            'DFSR',
            'Eventlog',
            'EventSystem',
            'KDC',
            'LanManWorkstation',
            'LanManServer',
            'NetLogon',
            'NTDS',
            'RPCSS',
            'SAMSS',
            'W32Time')
        $Collection

        Write-Verbose -Message 'Retreive Info on each DC'
        forEach ($Server in $DClist)
        {
            Write-Verbose -Message "Retrieve Services Status for $Server"
            Write-Verbose -Message 'EmailBody and Subject initialization'
            $EmailBody = @'

'@
            $Subject = ''
            forEach ($Service in $Collection)
            {
                try
                {
                    $s = Get-Service -Name $Service -Computername $Server -ErrorAction Stop
                    $s
                }
                catch
                {
                    Out-Null
                }

                if ($s.status -eq 'Stopped')
                {
                    $Subject = 'Somme Windows Services for AD are stopped on Domain Controllers'
                    $EmailBody = @"
                                Service named <font color=Red><b>$($s.Displayname)</b></font> is stopped on $Server!
                                Time of Event: <font color=Red><b>"""$((Get-Date))"""</b></font><br/>
                                <br/>
"@
                    Write-Verbose -Message 'Adding EmailBody to previous (if existing)EmailBody'
                    $EmailBody += $EmailBody
                } #End If
            } #End Service Foreach
        } #End DCList Foreach
        If ($Null -ne $Subject)
        {
            <#
            By this way, There is only one single mail send if a service is stopped on one or more Domain Controller
            #>
            Write-Verbose -Message 'One or more Services are stopped. Send Mail'
            Write-Verbose 'Adding a final info into the EmailBody'
            $EmailBody += @'
                                <br/>
                                THIS EMAIL WAS AUTO-GENERATED. PLEASE DO NOT REPLY TO THIS EMAIL.
'@
            $MailParams = @{
                To         = $Configuration.MailTo
                From       = $Configuration.MailFrom
                SmtpServer = $Configuration.SmtpServer
                Subject    = $Subject
                Body       = $EmailBody
                BodyAsHtml = $true
            }
            Send-MailMessage @MailParams
        }
    } #End Process
} #End function

I've verified the code with the cmdlet Invole-ScriptAnalyzer (from PSScriptAnalyzer module), and now there are only 1 warning and 1 Information RuleName Severity ScriptName Line Message


PSUseSingularNouns Warning Test-ADSer 1 The cmdlet 'Test-ADServices' uses a plural noun. A singular vices.ps1 noun should be used instead. PSUseOutputTypeCorrectly Information Test-ADSer 32 The cmdlet 'Test-ADServices' returns an object of type
vices.ps1 'System.Object[]' but this type is not declared in the
OutputType attribute. For the second advice, it seems simple to resolve it. For the first one, this requires to change the name of the function.

Another generic potential issue : Often, I'm using an AD account from another domain. There is a Trust relationship between the 2 domain, and my account has admin rights on the domain i'm logged on. If i'm using Get-AdDomain, the cmdlet retreive the corresponding info from the domain where my account is, but not the info from the the domain im' currently logged on. The cmdlet has a parameter named -Current (possible values are LocalComputer or CurrentLoggedOnUser), it seems to me that you should add this parameter with value LocalComputer to avoid this issue, or add this parameter as a paramter for your function.

A last improvement will be to add a self help section in your function.

It's always a pleasure to read your posts on 4SysOp or other sites.

Regards P.S. : sorry if my english is not perfect, it's not my native tongue. I do my best :-)