Last Update: Sep 04, 2024 | Published: Dec 10, 2012
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.
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.
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.
This means you can evaluate the return value either by string:
Or by the value.
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.
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.
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.
If there are no errors, the command will tell you.
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.