DefragAnalysisReport.ps1
param([parameter(parameterSetName="T", Mandatory=$true)][string]$Server, `
[parameter(parameterSetName="F", Mandatory=$true)][String]$File, `
[parameter(parameterSetName="A", Mandatory=$true)][Switch]$AD, `
[parameter(parameterSetName="F", Mandatory=$true)][parameter(parameterSetName="A", Mandatory=$true)][String]$Output, `
[string]$OnlyDrive, `
[parameter(parameterSetName="H", Mandatory=$true)][Switch]$Help)
$USAGE = @"
#################################################################
#
# Outputs fragmentation levels on servers. Has the ability to output a single drive or all drives
# v1.1
#
#
# USAGE:
#
# .\DefragAnalysisReport.ps1 -Server <"ServerName"> [-OnlyDrive "DriveLetter:"]
# .\DefragAnalysisReport.ps1 -File <"Input file name"> -Output <"Output file name"> [-OnlyDrive "DriveLetter:"]
# .\DefragAnalysisReport.ps1 -AD -Output <"Output file name"> [-OnlyDrive "DriveLetter:"]
# .\DefragAnalysisReport.ps1 -Help
#
#
# Options:
# -Server "Server Name" : Use "Server Name" as input and output directly to screen.
# -File "FileName" : Use "FileName" as input.
# -Output "FileName" : Use "FileName" as output.
# -OnlyDrive : Report fragmentation levels on a single drive letter (such as C: or D:)
# -AD : Use Active directory as computer name input. Searches are based on OU strings and need to be edited per environment.
# Edit lines between #::OU-EDIT-START and #::OU-EDIT-END
# -Help : Display this usage message.
#
# NOTE: This script requires Quest AD Commandlets.
#
##::CHANGELOG @ EOF.
#
#################################################################
"@
if ($Help)
{
Write-Host $USAGE -ForegroundColor Cyan
exit
}
##
# F#
##
function PullADComputers ($ArryContainer, $OUString)
{
$ADObjects = @()
$ADObjects += Get-QADComputer -SizeLimit 0 -SearchRoot "$OUString"
foreach ($Obj in $ADObjects)
{
$ArryContainer += $Obj.Name
}
return $ArryContainer
}
function pingIT( $Target )
{
$alive_system = gwmi Win32_PingStatus -Filter "Address='$Target'"
$Ping_status = $alive_system.statusCode
return $Ping_Status
}
function getDriveL ($Target) {
return gwmi -ComputerName $Target win32_volume | ? {$_.driveType -eq 3} | Select-Object caption, capacity, freespace
}
##
# /F#
##
$Targets = @();
if ($Server)
{
$Targets += $Server
$TotalCount = 1
}
if ($File)
{
$Targets = gc $File
$TotalCount = $Targets.length
}
if ($AD)
{
#::OU-EDIT-START
# $Targets = PullADComputers $Targets "OU=San Diego,OU=Server OU,DC=MyDomain,DC=com"
# $Targets = PullADComputers $Targets "OU=Albuquerque,OU=Server OU,DC=MyDomain,DC=com"
#::OU-EDIT-END
$TotalCount = $Targets.length
}
$Count = 1
if ($Output) {
Add-Content $Output -Value "SERVER`tDRIVE`tCapacity (GB)`t%FileFragmentation`t% Freespace`tTotal Scan Seconds"
} else {
Write-Host "SERVER`tDRIVE`tCapacity (GB)`t%FileFragmentation`t% Freespace`tTotal Scan Seconds"
}
foreach ($item in $Targets) {
$PCT = [Math]::Round((($Count * 100) / $TotalCount), 0)
Write-Progress "Checking defragmentation across servers..." "Working on $item - $PCT%" -PercentComplete $PCT -Id 0
if ((pingIT $item) -eq 0) {
#If the $OnlyDrive Option was used, it needs to be handled differently...
if (!($OnlyDrive)) {
$sDrives = getDriveL $item
$totalDrives = $sDrives.Count
} else {
#Error handling for $OnlyDrive.
if (($OnlyDrive.length) -ne 2) {
Write-Host "`n"
Write-Host "[PARAMETER ERROR]:: -OnlyDrive argument should be formatted as `"C:`" or `"D:`"" -ForegroundColor Yellow -BackgroundColor Black
Write-Host "`n"
exit
}
$sDrives = gwmi -ComputerName $item win32_volume | ? {$_.driveletter -eq "$OnlyDrive"} | Select-Object caption, capacity, freespace
$totalDrives = 1
}
$dcount = 1
if ($sDrives) {
foreach ($Drive in $sDrives) {
$DrivePCT = [Math]::Round((($dcount * 100) / $totalDrives), 0)
$DrL = $Drive.caption
$DrCapGB = [Math]::Round(($Drive.Capacity / 1gb), 0)
$DRFsp = $Drive.freespace
#Write-Host "Freespace: $DRFsp" -ForegroundColor Green
$DRCapC = $Drive.capacity
#Write-Host "Capacity: $DRCapC" -ForegroundColor Green
$FreePCT = [Math]::Round((($DRFsp * 100) / $DRCapC), 0)
Write-Progress "Analyzing Drives" "Working on $DrL..." -PercentComplete $DrivePCT -ParentId 0 -Id 1
#Timestamp at the start of drive analysis.
$oTime = Get-Date
#If i used meqasure-command, I would not be able to pull stats from the gwmi, so i used this timepan object instead.
$DriveAnalysis = (gwmi -ComputerName $item Win32_Volume | ? {$_.caption -eq "$DrL"}).DefragAnalysis()
#Timestamp at the end of drive Analysis.
$cTime = Get-Date
$TotalSeconds = [Math]::Round((New-TimeSpan -Start $oTime -End $cTime).TotalSeconds, 2)
$FilePctFrag = $DriveAnalysis.DefragAnalysis.FilePercentFragmentation
#Output the information one way or another
if ($Output) {
Add-Content $Output -Value "$item`t$DrL`t$DrCapGB`t$FilePctFrag`t$FreePCT`t$TotalSeconds"
} else {
Write-Host "$item`t$DrL`t$DrCapGB`t$FilePctFrag`t$FreePCT`t$TotalSeconds"
}
#Clean up and Increment
$DrL = $null
$DrCapGB = $null
$FilePctFrag = $null
$TotalSeconds = $null
$dcount++
}
}
}
$Count++
}
#::CHANGELOG###############################################################
#
# v1.0 - Initial production script. -SS 5/12/11
# v1.1 - Added output for a single server -SS 5/13/11
#
###########################################################################