(May need to be Run As Administrator)

#
# ---------------------------------------------------------------------- 
# Volume and Volume Fragmentation Information
# Returns volume information. If being run as an Administrator, 
#   returns volume fragmentation information for each local disk.
# ---------------------------------------------------------------------- 
#                            MODIFICATION LOG
# ---------------------------------------------------------------------- 
# 2012-08-09 WGS Initial Creation.
# 2012-08-11 WGS The WMI Win32_Volume class is not exposed on all 
#                  operating systems. Check for if the class is exposed. 
#                Added check for running as an administrator.
#                 Include more volume information as a separate result.
#                 Perform and return fragmentation information for local
#                   volumes only.
# ----------------------------------------------------------------------
 
cls
# Set-StrictMode -version 2
$IsAdmin = ([Security.Principal.WindowsPrincipal]`
            [Security.Principal.WindowsIdentity]::GetCurrent()).`
            IsInRole([Security.Principal.WindowsBuiltInRole]`
                      "Administrator")
$Volumes = Get-WMIObject Win32_Volume `
              -errorAction SilentlyContinue | Sort-Object DriveLetter
 
if (!$Volumes) 
    {Write-Warning "The Win32_Volume WMI class is not exposed on this operating system.`n`nThis script cannot continue.`n "}
#elseif (([Security.Principal.WindowsPrincipal]`
#            [Security.Principal.WindowsIdentity]::GetCurrent()).`
#            IsInRole([Security.Principal.WindowsBuiltInRole]`
#                      "Administrator") -eq $False) 
#   {Write-Warning "You do not have Administrator rights to run this script!`n`nPlease re-run this script as an Administrator!`n "}
else
{
if ($IsAdmin -eq $False) 
    {Write-Warning "Running script under non-Administrator mode.
 
Fragmentation information not accessible.
 
Re-run this script as an Administrator to obtain the fragmentation information!
"}
 
# hash table to set what the columns in the format-table look like for volume information
$a = `
@{Expression={$_.DriveLetter};Label="Drive";width=5},`
@{Expression={$_.DriveTypeDesc};Label="Drive Type";width=17},
@{Expression={"{0:N0}" -f ($_.FileSystem)};Label="File System";width=11},
@{Expression={"{0:N0}" -f ($_.BlockSize)};Label="Block Size";width=10;align="right"},
@{Expression={"{0:N0}" -f ($_.Capacity)};Label="Capacity";width=18;align="right"},
@{Expression={"{0:N0}" -f ($_.FreeSpace)};Label="Free Space";width=18;align="right"},
@{Expression={"{0:N0}" -f ($_.FreeSpace/$_.Capacity*100)};Label="Free %";width=6;align="right"}
 
$b = `
@{Expression={$_.DriveLetter};Label="Drive";width=5},`
@{Expression={$_.DefragRecommended};Label="Defrag Needed";width=13},`
@{Expression={$_.FilePercentFragmentation};Label="File Fragmentation %";width=20},`
@{Expression={"{0:N0}" -f ($_.TotalFragmentedFiles)};Label="# Fragmented Files";width=18;align="right"},
@{Expression={"{0:N0}" -f ($_.ClusterSize)};Label="Volume Cluster Size";width=19;align="right"}
 
#This table is necessary to return data once vs. once per drive.
$ServerName = Get-WmiObject -Class Win32_ComputerSystem
$TableName = $ServerName.Caption
$Table = New-Object system.Data.DataTable "$TableName"
$col = $Table.Columns.Add("DriveLetter", [string])
$col = $Table.Columns.Add("DefragRecommended", [boolean])
$col = $Table.Columns.Add("FilePercentFragmentation", [uint32])
$col = $Table.Columns.Add("TotalFragmentedFiles", [uint64])
$col = $Table.Columns.Add("ClusterSize", [uint64])
$col = $Table.Columns.Add("BlockSize", [uint64])
$col = $Table.Columns.Add("Capacity", [uint64])
$col = $Table.Columns.Add("FreeSpace", [uint64])
$col = $Table.Columns.Add("FileSystem", [string])
$col = $Table.Columns.Add("DriveType", [uint32])
$col = $Table.Columns.Add("DriveTypeDesc", [string])
 
#Ensure volumes have a drive type of local disk.
foreach ($Drive in $Volumes)
{ #$Drive
    #Must run DefragAnalysis() in a foreach loop for each drive.
    #Add a new row to the DataTable, and populate it.
 
    #First, add the volume information
    $Row = $Table.NewRow()
    $Row.DriveLetter = $Drive.DriveLetter
    if ($Drive.BlockSize -ge 0)
        {$Row.BlockSize = $Drive.BlockSize}
    else {$Row.BlockSize = [DBNull]::Value}
    if ($Drive.Capacity -ge 0)
        {$Row.Capacity = $Drive.Capacity}
    else {$Row.Capacity = [DBNull]::Value}
    if ($Drive.FreeSpace -ge 0)
        {$Row.FreeSpace = $Drive.FreeSpace}
    else {$Row.FreeSpace = [DBNull]::Value}
    $Row.FileSystem = $Drive.FileSystem
    $Row.DriveType = $Drive.DriveType
    switch ($Drive.DriveType)
        {
            0 {$Row.DriveTypeDesc = "Unknown"}
            1 {$Row.DriveTypeDesc = "No Root Directory"}
            2 {$Row.DriveTypeDesc = "Removable Disk"}
            3 {$Row.DriveTypeDesc = "Local Disk"}
            4 {$Row.DriveTypeDesc = "Network Drive"}
            5 {$Row.DriveTypeDesc = "Compact Disk"}
            6 {$Row.DriveTypeDesc = "RAM Disk"}
            default {$Row.DriveTypeDesc = "Unknown"}
        }
 
    #If Admin and a local disk, get fragmentation information.
    if (($IsAdmin -eq $true) -and ($Drive.DriveType -eq 3))
    {
        "Performing Fragmentation Analysis for Drive: {0} ({1})" -f $Drive.Caption, $Drive.DriveLetter
        $Analysis = $Drive.DefragAnalysis()
        $Stats = $Analysis.DefragAnalysis
 
        $Row.DefragRecommended = $Analysis.DefragRecommended
        if ($Stats.FilePercentFragmentation -ge 0)
            {$Row.FilePercentFragmentation = $Stats.FilePercentFragmentation}
        else {$Row.FilePercentFragmentation = [DBNull]::Value}
        if ($Stats.TotalFragmentedFiles -ge 0)
            {$Row.TotalFragmentedFiles = $Stats.TotalFragmentedFiles}
        else {$Row.TotalFragmentedFiles = [DBNull]::Value}
        if ($Stats.ClusterSize -ge 0)
            {$Row.ClusterSize = $Stats.ClusterSize}
        else {$Row.ClusterSize = [DBNull]::Value}
    }
    $Table.Rows.Add($Row)
}
#Display all of the results.
"
Volume Information (All Volumes)"
$Table | format-table $a
if ($IsAdmin -eq $True) 
    {"Fragmentation Information (Local Volumes)
    "
    $Table | Where-Object {$_.DriveType -eq 3} | format-table $b}
}