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)
}