Performing Disk Repair with PowerShell Cmdlets in Windows Server 2012

computer repair help

As careful as we might be, sometimes things go wrong with disks or volumes. In the past this meant turning to command line tools such as chkdsk.exe to scan and repair problems. You might run a command like this:
​C:\> chkdsk c: /r

With Windows Server 2012 and even Windows 8, you can still run such commands. But a better approach would be to use a repair-volume PowerShell cmdlet from the Storage module. Note that this is not a PowerShell v3 feature — it requires PowerShell v3 but you’ll only see the module on Windows Server 2012 or Windows 8.
In this article, we’ll cover the usage of the repair-volume Powershell cmdlet, the –OfflineScanAndFix parameter, the –SpotFix Powershell cmdlet, and the Get-VolumeScan Powershell cmdlet.

The Storage module is a collection of CIM-based functions for managing files, volumes, and disks, and it should be installed by default on PowerShell v3 systems. The command we’re interested in is called Repair-Volume. You will need to run it in an elevated PowerShell session with administrative privileges.

How to scan for problems with the Repair-Volume Powershell cmdlet

Even though the cmdlet name implies an active process, i.e. repair, it can also be used like chkdsk.exe to simply scan a volume for problems. The easiest approach is to use drive letter.

​PS C:\> Repair-Volume e -Scan
NoErrorsFound

Note that you only use the drive letter. Because the underlying command is using CIM, you can specify a remote computer running PowerShell v3 either by name or an existing CIM session.

​PS C:\> Repair-Volume d -Scan -CimSession Novo8
NoErrorsFound

You can combine this with Get-Volume, another command from the Storage module. You might think a command like this would work:

​PS C:\> get-volume -CimSession Novo8 | where drivetype -eq 'fixed' | repair-volume -Scan -CimSession Novo8

And sure, it probably will if you only get a single volume. But it will otherwise fail because you can only run a single instance of Repair-Volume at a time. The solution is to use ForEach-Object.

​PS C:\> get-volume -CimSession Novo8 | where drivetype -eq 'fixed' | foreach { repair-volume -driveletter $_.driveletter -Scan -CimSession Novo8}

For big jobs, you might want to take advantage of the –AsJob parameter.

PS C:\> Repair-Volume C -Scan -asjob

The output when using –Scan looks like a string.

​PS C:\> repair-volume E -scan
NoErrorsFound

But this is actually a Microsoft.PowerShell.Cmdletization.GeneratedTypes.Volume.RepairStatus object with an underlying integer value.
Microsoft.PowerShell.Cmdletization.GeneratedTypes.Volume.RepairStatus object
This means you can evaluate the return value either by string:

PS C:\> $s = repair-volume e –scan PS C:\> if ($s -ne “NoErrorsFound”) { write-warning $s } else {“Drive is OK”} Drive is OK

Or by the value.

PS C:\> if ($s.value__ -gt 0) { write-warning $s } else {“Drive is OK”}

How to Scan and Repair with the –OfflineScanAndFix Powershell cmdlet

If you run into problems, you will naturally want to repair the damage. Now, if you suspect a problem and want to scan and fix it at the same time, you have a few options available. First, you can elect to force Windows to temporarily take the drive offline to be scanned and repaired using the –OfflineScanAndFix parameter.

PS C:\> repair-volume -DriveLetter E -OfflineScanAndFix -CimSession NOVO8

Because the drive is offline, even temporarily, all open file handles will be closed, so you need to take that into account.
For system drives like C:, the command will inevitably fail. However, the disk will be marked; the next time you reboot, the disk will be checked and repaired. When you try this sort of thing with Chkdsk.exe, you get a prompt if you want to mark the disk and handle the scan or repair on reboot. But I have yet to find that sort of prompt with Repair-Volume. The assumption is that if you specify a volume that can’t be dismounted while the operating system is running, then you understand and accept that it will be scanned on next reboot.

How to repair from a previous scan with the –SpotFix Powershell cmdlet

If Repair-Volume, or even chkdsk.exe, discovers an error, it will be recorded in a hidden system file $corrupt. This is a literal name, not a PowerShell variable. You can elect to fix the errors using the Powershell cmdlet –SpotFix, which skips running any sort of scan.

PS C:\> repair-volume -DriveLetter E –spotfix -asjob

If there are no errors, the command will tell you.

How to repair from a previous scan with the Get-VolumeScan Powershell cmdlet

Having a PowerShell cmdlet to check and repair volume problems is very handy, especially one that supports remoting. With a little planning you can report on the state of volumes and plan remediation as necessary. I’ll leave you with a PowerShell function you can use as a starting point:

​
#requires -version 3.0
Function Get-VolumeScan {
[cmdletbinding()]
Param (
[Parameter(Position=0,ValueFromPipeline=$True)]
[ValidateNotNullorEmpty()]
[string]$Computername = $env:computername
)
Begin {
 Import-Module Storage
}
Process {
Write-Verbose "Getting volumes from $Computername"
#get fixed volumes
$volumes = Get-volume -CimSession $computername |
where {$_.DriveType -eq 'Fixed' -AND $_.Driveletter}
| Sort DriveLetter
foreach ($volume in $volumes) {
    Write-Verbose "Scanning $($volume.driveletter)"
    $scan = Repair-Volume -DriveLetter $volume.driveletter -Scan -CimSession $Computername
    $Hash=[ordered]@{
     Computername=$volume.PSComputername
     Driveletter=$volume.driveletter
     Status=$scan
     Label=$volume.FileSystemLabel
     FileSystem=$volume.FileSystem
     ScanDate=Get-Date
    }
   #Write a custom object to the pipeline
   New-Object -TypeName PSobject -Property $hash
}
} #Process
End {}
} #end function

The function writes an object like this to the pipeline:

​
Computername : NOVO8 Driveletter  : C Status       : NoErrorsFound Label        : Drive_C FileSystem   : NTFS ScanDate     : 12/4/2012 5:36:34 PM

Once loaded into your session you should be able to remotely build a report for all your Windows Server 2012 systems.

​PS C:\> $data = get-content Win2012Servers.txt | get-volumescan

You can then slice and dice $data as necessary to discover where you have problems.
You can download the get-volume-scan here. It is a basic script with no real error handling so be sure to test it out in a non-production environment first.