How to Defrag Drives using Powershell in Windows Server 2012

I’ve written about how you can use PowerShell to repair disk volumes, but another common server maintenance task is identifying and defragmenting drives. There are a number of enterprise solutions available on the market which might make sense for many organizations. But if you lack the budget, run a smaller shop, or prefer to do your own thing, managing this task is a little more difficult. There has been the command line tool, defrag.exe, but it needs to be combined with other techniques to handle remote systems.

With Windows Server 2012 and Windows 8, we have some new tools at our disposal for managing the defrag task using PowerShell v3. I should point out that even though you need PowerShell v3, this is operating system-specific, as it uses the new Storage module that is only available on Windows Server 2012 and Windows 8. Don’t have that? I’ll offer you an Powershell alternative later in the article.

Defrag Drives with Optimize-Volume

The new cmdlet we will use is called Optimize-Volume. It is part of the Storage module which utilizes the new CIM infrastructure. You can use this cmdlet to analyze and defrag all types of volumes.
Help optimize volume
We’ll focus on logical drives like C:.

How to Run an Analysis

To run an analysis all you need to do is run a command like this:

PS C:\> Optimize-Volume G –Analyze

But for some reason unknown to me, the cmdlet doesn’t write any sort of result to the pipeline! Instead you have to use the –Verbose parameter.

PS C:\> Optimize-Volume G –Analyze -verbose

You should get something like Figure 2:
Optimize Volume Verbose
So you can get the information you need, but it takes an extra step. If you want to save the results, you’ll need to redirect the verbose output.

PS C:\> Optimize-Volume G –Analyze –verbose 4>c:\work\GDrive.txt

On the positive side, you can specify a remote computer using –CIMSession. The remote computer must be running Windows Server 2012 or Windows 8.

PS C:\> Optimize-Volume C –Analyze –Cimsession CHI-DC03 –verbose 4>c:\work\dc03-c.txt

You can either specify a computer name, as I’ve done here, or an existing CIM session object. This makes it (sort of) easy to analyze the same drive across multiple computers.

How to Defrag a Drive

When the time comes to perform the defrag, we can use the same cmdlet, but without the –Analyze parameter.

PS C:\> Optimize-Volume d -Verbose -CimSession novo8

Again, I used –Verbose so I can see what happened in Figure 3.
Optimize Volume Novo8
Optimize-Volume will automatically perform additional operations such as trimming, depending on the drive type. So for an SSD drive the cmdlet should automatically retrim, but you can specify –Retrim if you want.

Defragmenting Drives: A PowerShell Alternative

Now, you could set up a scheduled task to use Optimize-Volume to defrag key volumes on your servers on a regular basis, regardless of whether they need them, but personally, I’d like a bit more control. And what if you don’t have Windows Server 2012? Either way, you’ll need an alternative.
I wrote a PowerShell function called Get-DefragAnalysis that works with PowerShell v2. You can download the Get-DefragAnalysis function. Once loaded into your PowerShell session, you can specify a drive and computers to scan.

PS C:\> $analysis = Get-DefragAnalysis -Driveletter C: -Computername chi-dc01,chi-dc02,chi-dc03

The function writes an object like this to pipeline:

AverageFileSize               : 64
AverageFragmentsPerFile       : 1
AverageFreeSpacePerExtent     : 17002496
ClusterSize                   : 4096
ExcessFolderFragments         : 0
FilePercentFragmentation      : 0
FragmentedFolders             : 0
FreeSpace                     : 161816576
FreeSpacePercent              : 77
FreeSpacePercentFragmentation : 29
LargestFreeSpaceExtent        : 113500160
MFTPercentInUse               : 100
MFTRecordCount                : 511
PageFileSize                  : 0
TotalExcessFragments          : 0
TotalFiles                    : 182
TotalFolders                  : 11
TotalFragmentedFiles          : 0
TotalFreeSpaceExtents         : 8
TotalMFTFragments             : 1
TotalMFTSize                  : 524288
TotalPageFileFragments        : 0
TotalPercentFragmentation     : 0
TotalUnmovableFiles           : 4
UsedSpace                     : 47894528
VolumeName                    :
VolumeSize                    : 209711104
Driveletter                   : E:
DefragRecommended             : False
Computername                  : NOVO8

This gives you information that you can base management decisions on. It also means I can take my results and get a quick report of where I need to defrag.

PS C:\> $analysis | Select Computername,Driveletter,FreespacePercent,DefragRecommended
Computername         Driveletter        FreeSpacePercent   DefragRecommended
------------         -----------        ----------------   -----------------
CHI-DC01             C:                                19              False
CHI-DC02             C:                                29               True
CHI-DC03             C:                                68               True

You can easily defrag volumes remotely with a command like this:

PS C:\> Get-WmiObject win32_volume -filter "driveletter='c:'" -ComputerName chi-dc02 | Invoke-WmiMethod -Name Defrag

PowerShell continues to be a blessing for IT pros, especially when it comes to managing Windows Server 2012. Granted, there are some limitations with Optimize-Volume, at least the way I would expect to use it, but it is a relatively easy way to get a handle on what volumes need to be defragged. It also handles the variety of storage types you most likely have in your environment. For everything else, I hope my Get-DefragAnalysis tool helps fill in the gaps.