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
#
###########################################################################