Monitor Disk Freespace

Monitor Disk in all Servers

#Get a list of all servers then go through that list and get all local drives and email a report with 

#a summary of the most critical drives and errors and attach the full list

IF (Get-PSSnapin | where {$_.name -eq "quest.activeroles.admanagement"}) 

    {write-host "Quest Active Roles snapin already loaded"}

Else

    {add-PSSnapin  quest.activeroles.admanagement}

$CriticalFreeSpaceGB = .5

$WarningFreeSpacePercent = 5

$smtpServer = "mail.blah.com"

#$To = "Kevin Curran <kcurran@blah.com>"

$From = "AD Reporting <ADReporting@blah.com>"

$OutputFile = "c:\Temp\ServerDriveUsage.csv"

$Counter = $null

Function check-even ($num) {[bool]!($num%2)}

$WindowsServers = Get-QADComputer -SizeLimit 0 -OSName "*windows*server*" | select Name, OperatingSystem

#Testing

#$WindowsServers = Get-QADComputer -SizeLimit 0 -OSName "*windows*server*" | select Name, OperatingSystem -First 30

#$WindowsServers | Group-Object -Property operatingsystem | select count, name

$DriveReport =@()

foreach ($Server in $WindowsServers)

{

    $DNS = $null

    $pingable = $null

    $WMIError = $null

    $ErrorString = $null

    $ErrorMessage = ""

    $Counter ++

    Write-Host $Counter $Server.Name

    

    $DNS = [System.Net.Dns]::GetHostByName($Server.Name)

    If ($DNS) 

    {

        $pingable=$(Test-Connection -Quiet -count 2 -ComputerName $Server.Name)

        If ($pingable)

        {

            #Add a where filter to exclude drives in the non active cluster node

            $DriveReport += Get-WmiObject -ErrorVariable WMIError -ErrorAction SilentlyContinue Win32_LogicalDisk -Filter "DriveType='3'" -ComputerName $Server.Name | 

                Where {$_.Size -ne $null} |

                select @{Name='Machine';Expression={$Server.Name}}, 

                @{Name='Drive';Expression={$_.DeviceID}},

                @{Name='SizeGB';Expression={[Math]::Round($($_.Size / 1GB),1)}},

                @{Name='FreespaceGB';Expression={[Math]::Round($($_.FreeSpace / 1GB ),1)}},

                @{Name='PercentFree';Expression={[Math]::Round($($_.FreeSpace /$_.Size * 100),1)}},

                @{Name='ErrorMessage';Expression={""}}

            $ErrorMessage = If ($WMIError)

            {

                $ErrorString = "$WMIError"

                If($ErrorString -like '*Access is denied*'){"WMI Error - Access is denied"}

                ElseIf($ErrorString -like '*OutOfMemoryException*'){"WMI Error - OutOfMemoryException"}

                ElseIf($ErrorString -like '*Server execution failed*'){"WMI Error - Server execution failed"}

                ElseIf($ErrorString -like '*RPC server is unavailable*'){"WMI Error - RPC server is unavailable"}

                ElseIf($ErrorString -like '*Not Found*'){"WMI Error - Not Found"}

                Else 

                {

                    #return the errorstring to ErrorMessage variable and write the new WMI error to a log file

                    $ErrorString

                    #$WMIError | Out-File .\$($Server.Name)_error.txt

                }

            }

        }

        Else

        {

            #Write Error unable to ping server

            $ErrorMessage = "Error unable to ping Server $($Server.Name)"

        }

    }

    Else

    {

        #Write Error no DNS entry found

        $ErrorMessage = "Error unable to find DNS entry for $($Server.Name)"

    }

    

    IF ($ErrorMessage)

    {

        $DriveReport +=  $Server.Name | select @{Name='Machine';Expression={$Server.Name}},

            @{Name='Drive';Expression={""}},

            @{Name='SizeGB';Expression={""}},

            @{Name='FreespaceGB';Expression={""}},

            @{Name='PercentFree';Expression={""}},

            @{Name='ErrorMessage';Expression={$ErrorMessage}}

    }

}

$DriveReport | Export-Csv -NoTypeInformation -Path $OutputFile

$CriticalDrives = $DriveReport | where {$_.ErrorMessage -eq "" -and $_.FreespaceGB -le $CriticalFreeSpaceGB} | Sort-Object -Property FreespaceGB

$WarningDrives = $DriveReport | where {$_.ErrorMessage -eq "" -and $_.FreespaceGB -gt $CriticalFreeSpaceGB -and $_.PercentFree -le $WarningFreeSpacePercent} | Sort-Object -Property PercentFree

$ErrorDrives = $DriveReport | where {$_.ErrorMessage -ne ""}

$Message = $CriticalDrives | ConvertTo-Html -Fragment -Property Machine, Drive, SizeGB, FreespaceGB, PercentFree -PreContent "<b>Critical Drives (less than $CriticalFreeSpaceGB GB freespace) </b>" | ForEach-Object {$_}

$Message += $WarningDrives | ConvertTo-Html -Fragment -Property Machine, Drive, SizeGB, FreespaceGB, PercentFree -PreContent "<br><b>Warning Drives (less than $WarningFreeSpacePercent Percent freespace)</b>" | ForEach-Object {$_}

$Message += $ErrorDrives | ConvertTo-Html -Fragment -Property Machine, ErrorMessage -PreContent "<br><b>Errors</b> <br>If these machines do not exist please decommission them and remove from Active Directory" | ForEach-Object {$_}

$Counter = $null

#Modify HTML alternate row color

$ModifiedHTML=ForEach ($line in $Message)

{

    $counter++

    if (check-even $counter)

     {$line.replace('<tr><td>','<tr class="d0"><td>')}

    Else

     {$line.replace('<tr><td>','<tr class="d1"><td>')}

}

$PreMessage = @" 

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">

<head>

<title>HTML TABLE</title>

<style>

    BODY{background-color:white;}

    TABLE{border-width: 1px;border-style: solid;border-color: black;border-collapse: collapse;}

    TH{border-width: 1px;padding: 5px;border-style: solid;border-color: black;background-color:MidnightBlue; color:Yellow}

    TD{border-width: 1px;padding: 5px;border-style: solid;border-color: black;background-color:PaleGoldenrod}

    TR.D0 TD {background-color: White; color: black;}

    TR.D1 TD {background-color: LawnGreen; color: black;}

    TR.Crit TD {background-color: Red; color: black;}

</style>

</head><body>

"@

$PostMessage = "<br>This script was run by " + $env:username + " on " + $env:COMPUTERNAME

$PostMessage += "<br>ScriptName: $($MyInvocation.MyCommand) "

$PostMessage += "<br>Script path: $(Split-Path -Parent $MyInvocation.MyCommand.Path)"

$PostMessage += "</body></html>"

$HTML = $PreMessage +  $($ModifiedHTML | out-string) + $PostMessage

Send-MailMessage -From $From -To $To -SmtpServer $smtpServer -Attachments $OutputFile `

    -Subject "$Env:userdomain Domain Server Drive Usage Report" -BodyAsHtml $HTML

Disk Free Space Alert

This script will send an email alert for low disk freespace

$MinimumFreePercent = 20

$Alert = $false

$smtpServer = "mail.blah.com"

$To   = "Kevin Curran <kcurran@blah.com>"

$From = "Reporting <Reporting@blah.com>"

$LocalDisks = Get-WmiObject Win32_LogicalDisk -Filter "DriveType='3'" | select DeviceID, 

    @{Name='SizeGB';Expression={[Math]::Round($($_.Size / 1GB),1)}},

    @{Name='FreespaceGB';Expression={[Math]::Round($($_.FreeSpace / 1GB ),1)}},

    @{Name='PercentFree';Expression={[Math]::Round($($_.FreeSpace /$_.Size * 100),1)}} 

Function check-even ($num) {[bool]!($num%2)}

$PreMessage = @" 

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">

<head>

<title>HTML TABLE</title>

<style>

    BODY{background-color:white;}

    TABLE{border-width: 1px;border-style: solid;border-color: black;border-collapse: collapse;}

    TH{border-width: 1px;padding: 0px;border-style: solid;border-color: black;background-color:MidnightBlue; color:Yellow}

    TD{border-width: 1px;padding: 0px;border-style: solid;border-color: black;background-color:PaleGoldenrod}

    TR.D0 TD {background-color: White; color: black;}

    TR.D1 TD {background-color: LawnGreen; color: black;}

</style>

</head><body>

“@

    

foreach ($Drive in $LocalDisks)

{

    IF ($Drive.PercentFree -LT $MinimumFreePercent) {$Alert = $true}

}

If ($Alert) 

{

    

    

    $PostMessage += "<br>This script was run by " + $env:username + " on " + $env:COMPUTERNAME

    $PostMessage += "<br>ScriptName: $($MyInvocation.MyCommand) "

    $PostMessage += "<br>Script path: $(Split-Path -Parent $MyInvocation.MyCommand.Path)"

    $PostMessage += "</body></html>"

    $Message= $LocalDisks | sort -Property DeviceID | ConvertTo-Html -Property DeviceID, SizeGB, FreespaceGB, PercentFree  -PreContent `

        "Please look into the lack of available disk space on this machine. <H2>Local Drives on $($env:COMPUTERNAME) </H2>" | ForEach-Object {$_}

    $ModifiedHTML=ForEach ($line in $Message)

{

    $counter++

    if (check-even $counter)

        {$line.replace('<tr><td>','<tr class="d0"><td>')}

    Else

        {$line.replace('<tr><td>','<tr class="d1"><td>')}

}

$html = $PreMessage + $($ModifiedHTML | out-string) + $PostMessage

    #Send Email

    Send-MailMessage -From $From -To $To -SmtpServer $smtpServer -bodyashtml -Body $html `

        -Subject "$($env:COMPUTERNAME) has at least one disk with less than $MinimumFreePercent% freespace" 

}

Same Alert Via GMail

$MinimumFreePercent = 10

$Alert = $false

$LogFileDir = "C:\Scripts\DiskUsageLogs"

$To = "foo@gmail.com","kevin@blah.com"

$From = "reporting@gmail.com" 

$BadPassword = "badcleartextpassword"

$LocalDisks = Get-WmiObject Win32_LogicalDisk -Filter "DriveType='3'" | select DeviceID, 

    @{Name='SizeGB';Expression={[Math]::Round($($_.Size / 1GB),1)}},

    @{Name='FreespaceGB';Expression={[Math]::Round($($_.FreeSpace / 1GB ),1)}},

    @{Name='PercentFree';Expression={[Math]::Round($($_.FreeSpace /$_.Size * 100),1)}} 

Function check-even ($num) {[bool]!($num%2)} 

Function out-zip { 

  Param([string]$path) 

  if (-not $path.EndsWith('.zip')) {$path += '.zip'} 

  if (-not (test-path $path)) { 

    set-content $path ("PK" + [char]5 + [char]6 + ("$([char]0)" * 18)) 

  } 

  $ZipFile = (new-object -com shell.application).NameSpace($path) 

  $input | foreach {$zipfile.CopyHere($_.fullname)} 

#Log Disk usage to a .csv file to see growth over time

Foreach ($Disk in $LocalDisks)

{

    $LogFilePath = "$LogFileDir\$($env:COMPUTERNAME)_$($Disk.DeviceID.substring(0,1))_DriveUsage.csv"

    write-host $LogFilePath

    If((Test-path $LogFilePath) -eq $false)

    {

        "Date,Drive,SizeGB,FreespaceGB,PercentFree" | Out-File $LogFilePath

    }

    "$(get-date -UFormat "%m/%d/%Y %r"),$($Disk.DeviceID),$($Disk.SizeGB),$($Disk.FreespaceGB),$($Disk.PercentFree)" | Out-File -Append $LogFilePath

    

}

$PreMessage = @" 

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">

<head>

<title>HTML TABLE</title>

<style>

    BODY{background-color:white;}

    TABLE{border-width: 1px;border-style: solid;border-color: black;border-collapse: collapse;}

    TH{border-width: 1px;padding: 0px;border-style: solid;border-color: black;background-color:MidnightBlue; color:Yellow}

    TD{border-width: 1px;padding: 0px;border-style: solid;border-color: black;background-color:PaleGoldenrod}

    TR.D0 TD {background-color: White; color: black;}

    TR.D1 TD {background-color: LawnGreen; color: black;}

</style>

</head><body>

“@

    

foreach ($Drive in $LocalDisks)

{

    IF ($Drive.PercentFree -LT $MinimumFreePercent) {$Alert = $true}

}

If ($Alert) 

{

    $CompressedLogs = "$LogFileDir\CompressedLogs.zip"

    If (test-path $CompressedLogs) {Remove-item $CompressedLogs}

    #Not sure why this fails on multiple files changed it to do foreach file

    #Get-item $LogFileDir\*.csv| out-zip $CompressedLogs

    $Logfiles = Get-item $LogFileDir\*.csv

    foreach ($file in $Logfiles) {get-item $file.fullname | out-zip $CompressedLogs}

    

    

    

    

    $PostMessage += "<br>This script was run by " + $env:username + " on " + $env:COMPUTERNAME

#    $PostMessage += "<br>ScriptName: $($MyInvocation.MyCommand) "

#    $PostMessage += "<br>Script path: $(Split-Path -Parent $MyInvocation.MyCommand.Path)"

    $PostMessage += "</body></html>"

    $Message= $LocalDisks | sort -Property DeviceID | ConvertTo-Html -Property DeviceID, SizeGB, FreespaceGB, PercentFree  -PreContent `

        "Please look into the lack of available disk space on this machine. <H2>Local Drives on $($env:COMPUTERNAME) </H2>" | ForEach-Object {$_}

    $ModifiedHTML=ForEach ($line in $Message)

    {

    $counter++

    if (check-even $counter)

        {$line.replace('<tr><td>','<tr class="d0"><td>')}

    Else

        {$line.replace('<tr><td>','<tr class="d1"><td>')}

    }

    $html = $PreMessage + $($ModifiedHTML | out-string) + $PostMessage

    #Send Email

    #Send-MailMessage -From $From -To $To -SmtpServer $smtpServer -bodyashtml -Body $html `

    #    -Subject "$($env:COMPUTERNAME) has at least one disk with less than $MinimumFreePercent% freespace" 

    

 

    $Subject = "$($env:COMPUTERNAME) has at least one disk with less than $MinimumFreePercent% freespace"  

    $SMTPServer = "smtp.gmail.com" 

    #$SMTPMessage = New-Object System.Net.Mail.MailMessage($From,$To,$Subject,$HTML)

    $SMTPMessage = New-Object System.Net.Mail.MailMessage

    $SMTPMessage.From = $From

    Foreach ($email in $To)

    {

        $SMTPMessage.To.Add($email)

    }

    $SMTPMessage.Subject = $Subject

    $SMTPMessage.body = $HTML

    $SMTPMessage.IsBodyHtml = $true

    $attachment = New-Object System.Net.Mail.Attachment($CompressedLogs)

    $SMTPMessage.Attachments.Add($attachment)

    $SMTPClient = New-Object Net.Mail.SmtpClient($SmtpServer, 587) 

    $SMTPClient.EnableSsl = $true 

    $SMTPClient.Credentials = New-Object System.Net.NetworkCredential($From, $BadPassword); 

    $SMTPClient.Send($SMTPMessage)    

}