Looking to write a powershell script to run chkdsk and read results

539 Views Asked by At

I am trying to write a powershell script that will run chkdsk to determine if there is an error on the drive. If an error exist then it would run add the parameter /f and tell it to run on the next reboot. What would be the simplest way to write a script like this?

3

There are 3 best solutions below

4
Chrisp On

You can capture the text output from running chkdsk like so, and parse with regex

$data = & chkdsk
$isActionRequired = $null -ne ($data |Select-String -Pattern "No Further action is required")
if ($isActionRequired) {
    & chkdsk /f # <- amend to schedule
}

As I'm sure you know, this process takes a while, and the output will no longer show in the console (unless you pipe to something like Tee-Object). FWIW, I did not inspect the output of chkdsk in different states, so the above should be tweaked.

3
iRon On

Although PowerShell can handle old-fasion DOS commands (external and native system commands) it is best to avoid them if there is a better alterative available, as in this case: Repair-Volume even I don't expect that it will add more value with regards to your specific task.

I don't think there is a clear list of general command alternatives and which one is preferred above the other, but I guess it something like this if you looking for a more direct interface with PowerShell:

  1. PowerShell Cmdlet
  2. .Net methods
  3. CimCmdlets
  4. ComObject methods
  5. Dynamic Link Library
  6. Pinvoke Win32 APIs
  7. System/External executables
0
mklement0 On
  • chkdsk.exe uses distinct exit codes to signal the outcome of a run.

    • 3 is used to signal the presence of errors that weren't fixed due to not having specified /f

    • Caveat: Running chkdsk without /f (or any of the other repair options that imply /f - /x, /r, /b) means that the target volume isn't getting locked (which wouldn't be possible for the system volume), which means that "it might report spurious errors." (from the linked docs, emphasis added).

  • In PowerShell, you can use the automatic $LASTEXITCODE variable to query the exit code of the most recently executed external program (child process).

  • You can schedule a chkdsk run with /f on the next reboot with a little trick, detailed in this serverfault answer:

    • Make sure that the target drive is in use (i.e. that files on it are open); while this is by definition true for the system drive, it may not be for others:
      • Simply making a directory on the target drive the working directory in a cmd.exe session is sufficient, such as by submitting D: to target the D: drive, for instance.[1]
    • Then invoke chkdsk /f, which - due to the in-use state of the target drive - will prompt for whether the error-correcting run should be performed on the next reboot.
    • You can automate the response to this Y/N prompt by piping echo Y to the call.

To put it all together:

#Requires -RunAsAdministrator

$targetDrive = 'C:' # Specify the target drive here.

# Run with checking only, not also fixing, i.e. do not use /f
chckdsk $targetDrive

if ($LASTEXITCODE -eq 3) {
  # Errors were found, schedule a run for the next reboot.
  # Note: /r also checks for physical disk errors.
  cmd /c "$targetDrive && echo Y| chkdsk $targetDrive /f /r"
}

# $LASTEXITCODE should now be 0 either way:
# Either no errors were found, or fixing on the next reboot was successfully scheduled.
if ($LASTEXITCODE -ne 0) {
  exit $LASTEXITCODE # Unexpected error.
}