Audit-Local-Admins.ps1

Param(
    [Switch]$Debug = $false,
    [Switch]$Console = $False,
    [Switch]$UseExcel = $True,
    [Switch]$IncludeAdmins = $False,    
    [Switch]$LongReport = $False    
    )

<#==============================================================================
          File Name : Audit-Local-Admins.ps1
    Original Author : Kenneth C. Mazie
                    :
        Description : Queries the local admins group on all domain computers and emails a report on findings.
                    :
              Notes : Normal operation is with no command line options. Basic log is written to C:\Scripts
                    : Optional argument: -Debug $true (defaults to false. Changes runtime options, email recipient, sets UseExcel to false)
                    : -Console $true (displays runtime info on console)
                    : -UseExcel $false (defaults to $true. Creates an Excel spreadsheet and stores the last 10. Attaches to outgoing email by default.)
                    : -IncludeAdmins $true (defaults to $false. Will include entries on the administrators array in the final report)
                    : -LongReport $true (defaults to $false. Will include ALL systems. Short report only adds a system to the output if anomalies are found)
                    :
           Warnings : None
                    :
              Legal : Public Domain. Modify and redistribute freely. No rights reserved.
                    : SCRIPT PROVIDED "AS IS" WITHOUT WARRANTIES OR GUARANTEES OF
                    : ANY KIND. USE AT YOUR OWN RISK. NO TECHNICAL SUPPORT PROVIDED.
                    :
            Credits : Code snippets and/or ideas came from many sources including but
                    : not limited to the following:
                    : N/A
                    :
     Last Update by : Kenneth C. Mazie
    Version History : v1.00 - 09-16-13 - Original
     Change History : v1.10 - 04-19-15 - Edited to allow color coding of HTML output, only keep 10 XLSX files.
                    : v1.20 - 02-02-16 - Fixed lock up after closing Excel.
                    : v1.30 - 03-10-16 - Corrected spreadsheet attachment error. Added admin ignore option
                    : v2.00 - 02-02-18 - Major rewrite for PS 5.1. Added external config file to genericize script.
                    : Altered report output formatting.
                    : v2.10 - 03-15-18 - Tweaked for upload to PS Gallery.
                    : v2.20 - 06-18-18 - Adjusted local administrator decoy detection so if a local user named "administrator"
                    : is found with a non-standard SID it gets flagged.
                    :
#===============================================================================#>

<#PSScriptInfo
.VERSION 2.20
.GUID 77f578dc-4887-44b2-b981-783aba19755d
.AUTHOR Kenneth C. Mazie (kcmjr AT kcmjr.com)
.DESCRIPTION
Queries the local admins group on all domain computers and emails a report on findings..
#>

#requires -version 5.1
Clear-Host 
    
If ($Debug){$Script:Debug = $True}
If ($Console){$Script:Console = $True}
If ($UseExcel){$Script:UseExcel = $True} 
If ($IncludeAdmins){$Script:IncludeAdmins = $True} 
If ($Debug){$Script:UseExcel = $False} 
If ($LongReport){$Script:LongReport = $True}

$ErrorActionPreference = "silentlycontinue"

#--[ Manual bypass options ]--
#$Script:Console = $True
#$Script:Debug = $True
#$Script:UseExcel = $true
#$Script:IncludeAdmins = $True

#--[ Functions ]-------------------------------------------------------------------------
Function LoadModules {
    If (!(Get-module ActiveDirectory)){Import-Module ActiveDirectory}
}    

Function LoadConfig { #--[ Read and load configuration file ]-----------------------------------------
    If (!(Test-Path $Script:ConfigFile)){       #--[ Error out if configuration file doesn't exist ]--
        $Script:EmailBody = "---------------------------------------------`n" 
        $Script:EmailBody += "--[ MISSING CONFIG FILE. Script aborted. ]--`n" 
        $Script:EmailBody += "---------------------------------------------" 
        #SendEmail #--[ No email without the settings file. Preset the options if you like ]--
        Write-Host $EmailBody -ForegroundColor Red
        break
    }Else{
        [xml]$Script:Configuration = Get-Content $Script:ConfigFile      
        $Script:DebugTarget = $Script:Configuration.Settings.General.DebugTarget
        $Script:ExclusionList = ($Script:Configuration.Settings.General.Exclusions).Split(",")
        $Script:ValidAdmins = ($Script:Configuration.Settings.General.ValidAdmins).Split(",")
        $Script:ReportName = $Script:Configuration.Settings.General.ReportName
        $Script:Domain = $Script:Configuration.Settings.General.Domain
        $Script:DebugEmail = $Script:Configuration.Settings.Email.Debug 
        $Script:eMailTo = $Script:Configuration.Settings.Email.To
        $Script:eMailFrom = $Script:Configuration.Settings.Email.From    
        $Script:eMailHTML = $Script:Configuration.Settings.Email.HTML
        $Script:eMailSubject = $Script:Configuration.Settings.Email.Subject
        $Script:SmtpServer = $Script:Configuration.Settings.Email.SmtpServer
        $Script:UserName = $Script:Configuration.Settings.Credentials.Username
        $Script:EncryptedPW = $Script:Configuration.Settings.Credentials.Password
        $Script:Base64String = $Script:Configuration.Settings.Credentials.Key   
        $ByteArray = [System.Convert]::FromBase64String($Base64String)
        $Script:Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $UserName, ($EncryptedPW | ConvertTo-SecureString -Key $ByteArray)
        $Script:Password = $Credential.GetNetworkCredential().Password    
    }
}

Function SendEmail {
    $email = $null
    If ($Script:Debug){$ErrorActionPreference = "stop"}
    $eMailBody = "Local Administrator Report."
    If ($Script:Debug){
        $eMailRecipient = $Script:DebugEmail                                        #--[ Debug destination email address
    }Else{    
        $eMailRecipient = $Script:eMailRecipient                                    #--[ Destination email address
    }
    $emailFrom = $Script:eMailFrom                                                  #--[ Sender address.
    $email = New-Object System.Net.Mail.MailMessage
    $email.From = $Script:eMailFrom
    $email.IsBodyHtml = $Script:eMailHTML
    $email.To.Add($Script:eMailTo)
    $email.Subject = $Script:eMailSubject
    If ($Script:UseExcel){
        $email.Attachments.Add($Script:FileName)
    }      
    $email.Body = $Script:ReportBody 
    $smtp = new-object Net.Mail.SmtpClient($Script:SmtpServer)
    $smtp.Send($email)
    If ($Script:Console){Write-Host "`n--[ Email sent ]--" -ForegroundColor Green}
}

Function GetTargets {
    $Script:TargetList =  ""
    If ($Script:Debug){
        $Script:TargetList = @(Get-ADComputer -Credential $Credential  -Filter "Name -Like '*$Script:DebugTarget*'" -ErrorAction 0 | Select Name | Sort Name)
        Write-Host "-- DEBUG MODE --" -ForegroundColor red 
    }Else{
        $Script:TargetList = @(Get-ADComputer -Credential $Credential -Filter * | select name | sort name)
    }    
    $Script:Count = $Script:TargetList.count
}

#==[ Main Body ]================================================================
$Script:ReportBody = ""
$HtmlData = ""
$DayOfWeek = (get-date).DayOfWeek
$StartTime = [datetime]::Now
# $Domain = (Get-ADDomain).DNSroot #--[ Alternate ]--
$Computer = $Env:ComputerName
$Script:Message = ""
$ScriptName = ($MyInvocation.MyCommand.Name).split(".")[0] 
$Script:LogFile = "$PSScriptRoot\$ScriptName-{0:MM-dd-yyyy_HHmmss}.html" -f (Get-Date)  
$Script:ConfigFile = "$PSScriptRoot\$ScriptName.xml"  
LoadConfig 
LoadModules
GetTargets

#--[ Add header to html log file ]--
$Script:ReportBody = @() 
$Script:ReportBody += '
<style type="text/css">
    table.myTable { border:5px solid black;border-collapse:collapse; }
    table.myTable td { border:2px solid black;padding:5px;background: #E6E6E6 }
    table.myTable th { border:2px solid black;padding:5px;background: #B4B4AB }
    table.bottomBorder { border-collapse:collapse; }
    table.bottomBorder td, table.bottomBorder th { border-bottom:1px dotted black;padding:5px; }
</style>'


$Script:ReportBody += '<table class="myTable">'
$Script:ReportBody += '<tr><td colspan=4><center><h1>-- '+$Script:ReportName+' Report --</h1></center></td></tr>'
If ($Script:ShortReport ){
    $Script:ReportBody += "<tr><td colspan=4><center>The following report displays members of the local administrators group for servers and/or PCs that don't belong.</center></td></tr>"
}Else{
    $Script:ReportBody += '<tr><td colspan=4><center>The following report displays all members of the local administrators group for every server and PC in the domain.</center></td></tr>'
}

#--[ Excel Non-Interactive Fix ]------------------------------------------------
#--[ Excel will crash when run non-interactively via a scheduled task if these folders don't exist. Folder permissions may cause this to fail. Creation may fail due to permission issues. ]--
Try{
    If (!(Test-path -Path "C:\Windows\System32\config\systemprofile\Desktop")){New-Item -Type Directory -Name "C:\Windows\System32\config\systemprofile\Desktop" -ErrorAction "SilentlyContinue" -Force}
    If (!(Test-path -Path "C:\Windows\SysWOW64\config\systemprofile\Desktop")){New-Item -Type Directory -Name "C:\Windows\SysWOW64\config\systemprofile\Desktop" -ErrorAction "SilentlyContinue" -Force}
}Catch{}    

#--[ Detect Excel, use it and send attachment if found, otherwise only create HTML ]--
$Script:NoExcel = $False
if (!(get-itemproperty hklm:\software\microsoft\windows\currentversion\uninstall\* | select displayname | where {$_.displayname -like "*Office*"} -ne "")){
    $Script:UseExcel = $False
    $Script:NoExcel = $True
    $Script:ReportBody += '<tr><td colspan=4><center>NOTICE: Excel was not located on the system running this report. No spreadsheet will be included.</center></td></tr>'
}

If ($Script:UseExcel){
    $Row = 0
    $Col = 1
    #--[ Create a new Excel object ]--
    $Excel = New-Object -Com Excel.Application
    If ($Script:Console -or $Script:Debug){
        $Excel.visible = $True
        $Excel.DisplayAlerts = $true
        $Excel.ScreenUpdating = $true
        $Excel.UserControl = $true
        $Excel.Interactive = $true
    }Else{
        $Excel.visible = $False
        $Excel.DisplayAlerts = $false 
        $Excel.ScreenUpdating = $false 
        $Excel.UserControl = $false
        $Excel.Interactive = $false
    }
    $Workbook = $Excel.Workbooks.Add()
    $WorkSheet = $Workbook.WorkSheets.Item(1)
   
    #--[ Write Worksheet title ]--
    $WorkSheet.Cells.Item($Row,1) = "Local Administrator Audit Report - $DateTime"
    $WorkSheet.Cells.Item($Row,1).font.bold = $true
    $WorkSheet.Cells.Item($Row,1).font.underline = $true
    $WorkSheet.Cells.Item($Row,1).font.size = 18
    #--[ Write worksheet column headers ]--
    $Row ++
    $WorkSheet.Cells.Item($Row,$Col) = "TARGET:"
    $WorkSheet.Cells.Item($Row,$Col).font.bold = $true
    $WorkSheet.Cells.Item($Row,$Col).HorizontalAlignment = 1
# $WorkSheet.Cells.Item($Row,$Col).Borders.Item(10).LineStyle = 1 #--[ optional formatting ]--
# $WorkSheet.Cells.Item($Row,$Col).Borders.Item(10).Weight = 4
    $Col++
    $WorkSheet.Cells.Item($Row,$Col) = "STATUS:"
    $WorkSheet.Cells.Item($Row,$Col).font.bold = $true
    $WorkSheet.Cells.Item($Row,$Col).HorizontalAlignment = 1
# $WorkSheet.Cells.Item($Row,$Col).Borders.Item(10).LineStyle = 1
# $WorkSheet.Cells.Item($Row,$Col).Borders.Item(10).Weight = 4
    $Col++
    $WorkSheet.Cells.Item($Row,$Col) = "USER:"
    $WorkSheet.Cells.Item($Row,$Col).font.bold = $true
    $WorkSheet.Cells.Item($Row,$Col).HorizontalAlignment = 1
# $WorkSheet.Cells.Item($Row,$Col).Borders.Item(10).LineStyle = 1
# $WorkSheet.Cells.Item($Row,$Col).Borders.Item(10).Weight = 4
    $WorkSheet.application.activewindow.splitcolumn = 0
    $WorkSheet.application.activewindow.splitrow = 1
    $WorkSheet.application.activewindow.freezepanes = $true
    $Resize = $WorkSheet.UsedRange
    [void]$Resize.EntireColumn.AutoFit()
}

$Script:ReportBody += '<tr><th>Target System</th><th>Account Name</th><th>Account Location</th><th>Account Type</th></tr>'
    
$Row ++
If ($Script:Console){Write-Host "`nTotal Target Systems = $Count" -ForegroundColor Cyan }
$Remaining = $Count

ForEach ($Target in $TargetList){
    $AddRow = $False
    $HtmlData = ""
    $list = ""
    $user = ""
    $Col = 1
    $Target = $Target.name
    $ExcludeFlag = $false
    #If ($Remaining -le 0){$Remaining = 0}
    
    If ($Script:Console){Write-Host "`nTarget System = $Target ("($Remaining-1)" Remaining )" -ForegroundColor Cyan }
    
    $Script:ExclusionList | foreach{
        if ($Target -match $_){$ExcludeFlag = $true} 
    } 
    
    $WorkSheet.Cells.Item($row,$col) = $Target
    $Col ++
        
    If ($ExcludeFlag){          #--[ Bypass these systems ]--
        if ($Script:Console){Write-Host " BYPASSING "$Target -ForegroundColor Magenta}
        $WorkSheet.Cells.Item($row,$col) = "BYPASSED";$Col ++
        If ($Script:Debug){
            $HtmlData += '<tr><td><font color=darkcyan><strong>' + $Target.ToUpper() + '</strong></td><td colspan=3><font color=darkred>Target BYPASSED</font>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color=#a0a0a0>( Target '+($Count-($Remaining-1)) +' of '+$Count+' Targets Total, '+($Remaining-1)+' Remaining. )</font></td></tr>'
        }Else{    
            $HtmlData += '<tr><td><font color=darkcyan><strong>' + $Target.ToUpper() + '</strong></td><td colspan=3><font color=darkred>Target BYPASSED</font></td></tr>'
        }    
    }Else{
            if (Test-Connection -ComputerName $Target -count 1 -BufferSize 16 -ErrorAction SilentlyContinue){ 
            $WorkSheet.Cells.Item($row,$col) = "OK";$Col ++
            If ($Script:Debug){
                $HtmlData += '<tr><td><font color=darkcyan><strong>' + $Target.ToUpper() + '</strong></td><td colspan=3>Connection: <font color=darkgreen>OK</font>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color=#a0a0a0>( Target '+($Count-($Remaining-1)) +' of '+$Count+' Targets Total, '+($Remaining-1)+' Remaining. )</font></td></tr>'
            }Else{
                $HtmlData += '<tr><td><font color=darkcyan><strong>' + $Target.ToUpper() + '</strong></td><td colspan=3>Connection: <font color=darkgreen>OK</font></td></tr>'
            }
            
            #--[ Start of User Processing ]------------------------------------------------------------------------------------------
            
            #--[ Get list of users in local admin group with WMI ]--
            #$UserList = Get-WmiObject -computername $Target -Class win32_groupuser -ErrorAction "SilentlyContinue" -Credential $Script:Credential | WHERE {$_.groupcomponent -match 'administrators' } | foreach {[WMI]$_.partcomponent }
            $UserList = Invoke-Command -ScriptBlock {Get-LocalGroupMember -Group "Administrators"} -ComputerName $Target -Credential $Credential
            #--[ Get list of local users with WMI to check for decoy account. ]--
            [Array]$LocalAccounts = Get-WmiObject -Class Win32_UserAccount -Namespace "root\cimv2" -Filter "LocalAccount='$True'" -ComputerName $Script:Target -Credential $Script:Credential -ErrorAction silentlycontinue 
            ForEach ($User in $LocalAccounts){
                If ($User.Name -eq "Administrator"){
                    If (($User.SID.SubString(0,6) -eq "S-1-5-") -and ($User.SID.SubString($User.SID.Length - 4) -eq "-500")){
                        $Decoy = $False
                    }Else{
                        $Decoy = $True
                    }
                }
            }
               
            ForEach ($User in $UserList){ 
                $UserName = $User.Name.Split("\")[1]
                $UserLocation = $User.Name.Split("\")[0]
                $UserClass = $user.ObjectClass #.ToLower()
                $SearchDomain = "*"+$Script:Domain.Split(".")[0]+"*"
                If($UserLocation -eq $Target){
                    $UserSource = $Target
                }Else{    
                    $UserSource = "ActiveDirectory"
                }
                
                If ($Script:IncludeAdmins){   
                    If ($Script:ValidAdmins -Contains $UserName){  
                        $AddRow = $True
                        $HtmlData += '<tr><td>&nbsp;</td><td><font color=darkgreen>' + $UserName + '</td><td><font color=darkgreen>' + $UserSource + '</td>'
                    }Else{    
                        $AddRow = $True
                        #--[ Test for decoy admin account ]--
                        If (($UserName -eq "Administrator") -and ($Decoy)){
                            $HtmlData += '<tr><td>&nbsp;</td><td><font color=darkred>' + $UserName + ' (DECOY)</td><td><font color=darkred>' + $UserSource + '</td>'
                        }Else{
                            $HtmlData += '<tr><td>&nbsp;</td><td><font color=darkred>' + $UserName + '</td><td><font color=darkred>' + $UserSource + '</td>' 
                        }    
                    }                        
                    
                    If ($UserLocation -like $SearchDomain){
                        $HtmlData += '<td><font color=darkblue>Domain '+$UserClass+'</td></tr>'
                    }Else{
                        $HtmlData += '<td><font color=#ff8000>Local '+$UserClass+'</td></tr>'
                    }
                    
                    if ($Script:Console){
                        If (($UserName -eq "Administrator") -and ($Decoy)){
                            Write-Host " Found: "$User.Name -ForegroundColor Yellow -NoNewline
                            Write-host " -- DECOY ADMIN ACCOUNT IDENTIFIED --" -ForegroundColor Magenta                        
                        }Else{
                            Write-Host " Found: "$User.Name -ForegroundColor Yellow 
                        }
                    }
                    $WorkSheet.Cells.Item($row,$col) = $User.Name
                    $Col ++
                }Else{
                    If ($Script:ValidAdmins -Contains $UserName){ 
                        if ($Script:Console){Write-Host " Ignored: "$User.Name -ForegroundColor Gray }
                    }Else{
                        $AddRow = $True
                        #--[ Test for decoy admin account ]--
                        If (($UserName -eq "Administrator") -and ($Decoy)){
                            $HtmlData += '<tr><td>&nbsp;</td><td><font color=darkred>' + $UserName + ' (DECOY)</td><td><font color=darkred>' + $UserClass + '</td>'
                        }Else{
                            $HtmlData += '<tr><td>&nbsp;</td><td><font color=darkred>' + $UserName + '</td><td><font color=darkred>' + $UserSource + '</td>' 
                        }    


                        If ($UserLocation -like $SearchDomain){
                            $HtmlData += '<td><font color=darkblue>Domain '+$UserClass+'</td></tr>'
                        }Else{
                            $HtmlData += '<td><font color=#ff8000>Local '+$UserClass+'</td></td></tr>'
                        }


                        If (($UserName -eq "Administrator") -and ($Decoy)){
                            if ($Script:Console){
                                Write-Host " Found: "$User.Name -ForegroundColor Yellow -NoNewline
                                Write-host " -- DECOY ADMIN ACCOUNT IDENTIFIED --" -ForegroundColor Magenta                                                     
                            }
                            $WorkSheet.Cells.Item($row,$col) = $User.Name+" (DECOY)" 
                            $Col ++
                        }Else{ 
                            if ($Script:Console){Write-Host " Found: "$User.Name -ForegroundColor Yellow }
                            $WorkSheet.Cells.Item($row,$col) = $User.Name 
                            $Col ++
                        }
                    }
                }
            }
            #--[ End of User Processing ]------------------------------------------------------------------------------------------
        }Else{
            if ($Script:Console){Write-Host " System is not reachable online..." -ForegroundColor Red }
            $WorkSheet.Cells.Item($row,$col) = "OFFLINE"
            $HtmlData += '<tr><td><font color=darkcyan><strong>' + $Target + '</td><td colspan=3>Connection:<font color=darkred> FAILED</font>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color=#909090>( Target '+($Count-($Remaining-1)) +' of '+$Count+' Targets Total, '+($Remaining-1)+' Remaining. )</font></td></tr>'
        } 
        
        If ($AddRow -or $Script:LongReport){    
            $Script:ReportBody += $HtmlData
        }        
        $Remaining --
    }
    $Row ++
    $Resize = $WorkSheet.UsedRange
    [void]$Resize.EntireColumn.AutoFit()
}

$Script:ReportBody += '</table>'
$Script:ReportBody += '<br><font color=#909090>Script "'+$MyInvocation.MyCommand.Name+'" executed from "'+$env:computername+'".<br>'

$Resize = $WorkSheet.UsedRange
[Void]$Resize.EntireColumn.AutoFit()

[string]$DateTime = Get-Date -Format MM-dd-yyyy_HHmmss 
[string]$Script:FileName = "$PSScriptRoot\LocalAdminUserAudit_$DateTime.xlsx"
If ($UseExcel){    
    Try{
        $Workbook.SaveAs($Script:FileName)
        $Workbook.Saved = $true 
        $Workbook.Close() 
        $Excel.Quit()
        $Excel = $Null
        if ($Script:Debug){Write-host "`nExcel Closed and Saved...`n" -ForegroundColor Cyan}
    }Catch{    
        if ($Script:Debug){Write-host "`nThere was a problem closing and/or Saving the Excel spreadsheet...`n" -ForegroundColor Red}
    }    
}    

#--[ Removing any older Excel files. Retaining ten most recent. ]--
###Get-ChildItem -Path "$PSScriptRoot\*.xlsx" | Where-Object { -not $_.PsIsContainer } | Sort-Object -Descending -Property LastTimeWrite | Select-Object -Skip 10 | Remove-Item
If (!$Script:Debug){Get-ChildItem -Path "$PSScriptRoot\" | Where-Object { -not $_.PsIsContainer -and $_.name -like "*.xlsx" } | Sort-Object -Descending -Property LastTimeWrite | Select-Object -Skip 10 | Remove-Item }

$Script:ReportBody += '</table><br>'
$x = 0
If ($Script:NoExcel){
    $Script:ReportBody += '<br>NOTICE: Spreadsheet not included because Excel was not found on the system running this script. Install Excel to include the spreadsheet.<br>'
}    
$Script:ReportBody += 'The following list contains all users/groups that are ignored by this report unless the "includeadmins" option is expressly selected.'
$Script:ReportBody += '<br>If "Administrator" is noted as (DECOY) it means an admin account was detected but has a non-default SID. These are usually decoy'
$Script:ReportBody += '<br>accounts but should NOT be in the local admin group.'
$Script:ReportBody += '<br><br>These are considered "known" accounts and are expected to be found. All others are anomalous:<br>'

if ($Script:Debug){Write-host "`nIgnored Admin Accounts:" }
While ($x -lt $Script:ValidAdmins.Count ){
    if ($Script:Debug){Write-host "-- "$Script:ValidAdmins[$x] }
    $Script:ReportBody += " - "+$Script:ValidAdmins[$x]+"<br>"
    $x++
}

$Script:ReportBody += '<br>Color scheme:<br> - Green User = Expected<br> - Red User = Investigate'
$Script:ReportBody += '<br> - Gray User = Ignored<br> - Orange Type = Local Resource<br> - Blue Type = Domain Resource'
If ($Debug){
    $Script:ReportBody += '<br><br>Script runtime options:'
    If ($Debug){$Script:ReportBody += '<br> - Debug option ENABLED'}
    If ($Console){$Script:ReportBody += '<br> - Console option ENABLED'}
    If (!$Script:UseExcel){$Script:ReportBody += '<br> - Excel option DISABLED'}
    If ($IncludeAdmins){$Script:ReportBody += '<br> - IncludeAdmins option ENABLED'}
    If ($Script:LongReport){$Script:ReportBody += '<br> - LongReport option ENABLED'}
    $Script:ReportBody += '<br>'
}

SendEmail 

[gc]::Collect()
[gc]::WaitForPendingFinalizers()

if ($Script:Debug){Write-host "`nCompleted..." }


<#--[ XML Config File Example ]-------------------------------------------------------------------------
 
<!-- Settings & Configuration File -->
<Settings>
    <General>
        <ReportName>Local Administrator Audit</ReportName>
        <DebugTarget>testpc</DebugTarget> <!-- Partial names OK to include a group -->
        <ValidAdmins>Local_Admin_Grp-1,Local_Admin_Grp-2,localadmin,administrator</ValidAdmins>
        <Exclusions>pc27,pc01</Exclusions>
        <Domain>mydomain.com</Domain>
    </General>
    <Email>
        <From>MonthlyReports@mydomain.com</From>
        <To>admin@mydomain.com</To>
        <Debug>me@mydomain.com</Debug>
        <Subject>Local Administrator Audit</Subject>
        <HTML>$true</HTML>
        <SmtpServer>10.10.5.5</SmtpServer>
    </Email>
    <Credentials>
        <UserName>domain\serviceaccount</UserName>
        <Password>766743f0423413AegMAYQBhAGEAYQBhAGQANQBkADQAZQAzAGYANAAyADUGIATgiAwADYAZAA3AGUAZgGADQAYwBkADYAZQBmAGQAOAA0ADEANgBiAAYQA2AGQAZAA2B2AHYAZQAxAGIATgBaADAEcAaAB1AFEAPQA9AHwAYwAzADQANgADAANwAGQAZgA3ADIAYQABkAGYAZAA=</Password>
        <Key>kdhICvLO+eJ76/AWnHbXN0IObEyjuTie8mE=</Key>
    </Credentials>
</Settings>
 
 
 
 
#>