14

My hard drive started to fail recently. I've managed to copy almost all data to another drive, but 280 sectors (140kB) were corrupted. Since that drive also contains my Steam library, I want to check it for any corruption.

However, I don't want to right-click >200 game title's in my library, go to their properties, local data and verify the installation. Is there a way to check the integrity of all installed Steam games? Or do I have to check them one-by-one?

2
  • 1
    You can select multiple titles in Steam library by holding Shift + left mouse but unfortunately Steam only has options to "add to favorites" and "set categories" when several games are selected.
    – user598527
    Commented Sep 1, 2018 at 7:20
  • Still good to know, as my categories where gone from a unrelated experiment, thanks!
    – Zeta
    Commented Sep 1, 2018 at 7:25

4 Answers 4

6

Steam doesn't provide a way to check the integrity of all of your games at once. However, someone has made a script that you can try to run that verifies all of your games in one shot.

A link to the Reddit post can be found here. It gives an overview of what the script is. In order to run this script, you will need AutoIt. After downloading AutoIt, you can run the script. According to the post, you should be able to even see what the script is composed of as well.

The Reddit posts points out a few things to keep in mind:

  • Your computer should not be actively in use when the script is running
  • Steam windows showing the game that is being verified will still pop-up, but they should be automatically be closed upon completion. If you are using other programs with the tool running, it is possible it may close the wrong window
  • You can skip specific games if you wish by adding the games SteamId to the "validationBlacklist.txt" file in this format: 15620 20570 220240 19900 50130 50620

There is also a link to a self-contained .exe version of the script, however the link for that one does not appear to want to work (at least for me). Note that you should also be cautious when downloading files like this off the internet, so take any chances at your own risk! Also be sure to follow the instructions listed in the Reddit post. It is a bit of a lengthy one to post all of it here.

5

Here is a way to recheck and update all installed games, on Linux, using steamcmd.

Steamcmd is closed source and updates itself from the net, similar to the Steam client; the useful thing is that it works from the CLI.

Install steamcmd from Ubuntu multiverse or https://media.steampowered.com/installer/steamcmd_linux.tar.gz. It will self-update on first run.

If some of your libraries are on removable media, check that they are all active in Steam's settings, Download section. Close Steam.

Substitute your Steam login name in the following command, and run:

steamcmd +login $mylogin $(
  steamcmd +login $mylogin +apps_installed +quit \
  |grep -Po '(?<=^AppID )[0-9]+(?= : )' \
  |sort -V \
  |while read appid; do \
    echo +app_update "$appid" validate; done \
) +quit

The checks take some time, but should run unattended.

It's possible to get spurious errors if your connection is flaky; you can insert something like |awk 'f{print} /$lastsuccessappid/{f=1}' immediately after the |sort -V term to continue after the last successful check.

3
  • While this is a good hint for Linux users, my question is/was Windows specific (or rather: I'm not on Linux, so I can't use your awesome script :/ )
    – Zeta
    Commented Apr 1, 2021 at 18:54
  • 1
    steamcmd is available for windows, you'd just have to adapt the script to powershell or batch utilities. Commented Oct 20, 2021 at 22:25
  • Well. As someone who is running Linux and ran across this post a couple of years later .... This method worked great, thanks. Commented May 25, 2023 at 12:00
2

Building off of @Tobu 's answer, for windows, since similar utilities for parsing text is much harder on windows, I went for a cross-platform solution. You can follow the directions for installing steamcmd for your platform at https://developer.valvesoftware.com/wiki/SteamCMD (You'll need to run it once first to finish the install)

I'm looking at creating a github project for this, so I can auto-build deno binaries with this embedded so you wouldn't have to install deno to run this. I'll update if I finish that.

I have a slightly more complete script in a github gist if you want to look at that: https://gist.github.com/josh-hemphill/25f73281faf08f0be0ed72b2cd2aa1da

Using Deno for the scripting, I achieved the same thing with some code like this.

// ran using deno run -A ./this-script.ts <my username> <steam library directory>
let user = Deno.args[0]
let lib = Deno.args[1]
await Deno.run({cmd:['steamcmd','+login',user,'+quit']}).status()
const p = Deno.run({
  cmd: [
    "steamcmd",
    "+force_install_dir",
    lib,
    "+login",
    user,
    "+apps_installed",
    "+quit",
  ],
  stdout: "piped",
});
await p.status();
const output = new TextDecoder().decode(await p.output());

const games = output.split("\n").filter((v) => v.startsWith("AppID")).map(
  (v) => {
    const cols = v.split(" : ");
    return {
      id: cols[0].split(" ")[1],
      name: cols[1].slice(1, cols[1].length - 2),
      dir: cols[2].replace(" \r", ""),
    };
  },
);

for (const game of games) {
  await Deno.run({
    cmd: [
      "steamcmd",
      "+force_install_dir",
      lib,
      "+login",
      user,
      "+app_update",
      game.id,
      "validate",
      "+quit",
    ],
  }).status();
}
1
  • Updating what happened. Turns out steamcmd got stuck or errored on one without actually causing a non-zero exit code, so it tried to continue, and freaked out. I'm now looking at directly calling the steam api or DLLs myself, but that's not documented for this purpose. Commented Nov 11, 2021 at 10:39
-1

I made an updated version of the script, that doesn't get confused by dlc's. (EDIT: In case the link breaks again i embedded it below).

also, i'd recommend installing autoit with scoop, so it can be removed without side effects.

#include <Array.au3>
#include <File.au3>
#include <FileConstants.au3>
#include <MsgBoxConstants.au3>
#include <ScreenCapture.au3>

; This script validates all games in a user's Steam library
; Author: Shawn Maiberger
;         @ionblade (Twitter)
; By running this script, in whole or in part, you accept that the author is not acceptable for any damage to your computer or data caused by the script.



;_____USER-CONFIGURABLE VARIABLES__________________________________________________________________________________________________________________

; Sometimes, an application does not validate when you call the validation function, and instead immediately comes back as valid.
; Specify the *shortest* amount of time a validation can take to be considered valid in seconds.  Any validation that is shorter than this will
; be invalid, and will be retried, up to the $maxValidationAttempts value.
$minimumValidationTime = 1

; Set the maximum number of times that an application will attempt to be validated due to running too short before we move on and log an exception
$maxValidationAttempts = 3

; Set the amount of time in seconds that an app can stay at 0% complete validation before we assume it has hung (Steam bug that often occurs) and retry
$validationTimeout = 30

; Time to wait between scans in seconds.  Note: if this is set too low, every other scan will fail to execute, as Steam will not be ready and will not throw an error.
$timeBetweenScans = 5
;__________________________________________________________________________________________________________________________________________________

; Try to read in the validation blacklist file.  This file should contain one AppID per line.  Any AppIDs in this file, if present, will not be validated.
; This is useful in cases where some games (e.g. Far Cry 3 and the Dawn of War 2 series) will not silently validate.
$validationBlacklist = 0
If Not _FileReadToArray("validationBlacklist.txt", $validationBlacklist, 0) Then
   $validationBlacklist = 0
EndIf

; Try to read Steam directory from registry
$steamRegLocation = RegRead("HKEY_LOCAL_MACHINE\Software\Valve\Steam","InstallPath")
If @error Then
   $steamRegLocation = ""
Else
   $steamRegLocation = $steamRegLocation & "\steamapps"
EndIf

; Prompt user for the Steamapps directory, prepopulating with the location previously found in the registry, if any
$steamappsDirectory = FileSelectFolder("Please select the steamapps directory within your Steam install directory", $steamRegLocation)
If @error Then
   MsgBox($MB_SYSTEMMODAL, "", "No folder was selected.")
   Exit
EndIf

; Prompt user for location to log results
$loggingDirectory = FileSelectFolder("Please select a writable folder into which results will be logged", "")
If @error Then
   MsgBox($MB_SYSTEMMODAL, "", "No folder was selected.")
   Exit
EndIf

; Get a list of all the games installed in the steamapps directory
$acfFiles = _FileListToArray($steamAppsDirectory, "*.acf")
If @error Then
   MsgBox($MB_SYSTEMMODAL, "", "Either an invalid steamapps path was selected or there are no games installed.")
   Exit
EndIf

; For each of the games installed, get the game's name and Steam ID, then call the verify function on that game.  Wait for verification to complete,
; then take a screenshot of the verification window and continue to the next game.
$validationErrors = 0
$validationWarnings = 0
$validationBlacklistSkips = 0
$validationSuccesses = 0
For $currentFile = 1 to $acfFiles[0]
   ; Set tooltip to let user know progress in systemtray
   TraySetToolTip("Validating item " & $currentFile & "/" & $acfFiles[0] & ".  " & $validationErrors & " apps did not process, " & $validationWarnings & " apps validated too quickly, " & $validationBlacklistSkips & " skipped, " & $validationSuccesses & " successful.")

   $fullAcfPath = $steamappsDirectory & "\" & $acfFiles[$currentFile]

   $appID = ""
   $name = ""

   ; Read through the .acf file to get the AppID and name
   FileOpen($fullAcfPath, 0)
   For $currentLine = 1 to _FileCountLines($fullAcfPath)
      $line = FileReadLine($fullAcfPath, $currentLine)

      ; Isolate the AppID by trimming everything between the last <tab><tab>" and the final " character
      If StringInStr($line, '"appID"') Then
         $appID = StringTrimRight(StringTrimLeft($line, StringInStr($line, @TAB & @TAB & '"', 0, -1) + 2), 1)
      EndIf

      ; Isolate the name by trimming everything between the last <tab><tab>" and the final " character
      If StringInStr($line, 'name') Then
         $name = StringTrimRight(StringTrimLeft($line, StringInStr($line, @TAB & @TAB & '"', 0, -1) + 2), 1)
      EndIf
   Next
   FileClose($fullAcfPath)

      ; If the current game is in the list of games that do not silently validate, skip it and log to the logfile
   $skipValidation = 0
   For $i = 0 To UBound($validationBlacklist) - 1
      If StringCompare($validationBlacklist[$i], $appID) = 0 Then
         $skipValidation = 1
         ExitLoop
      EndIf
   Next
   If $skipValidation = 1 Then
      $hFileOpen = FileOpen($loggingDirectory & "\verificationLog.txt", $FO_APPEND)
      If $hFileOpen = -1 Then
         MsgBox($MB_SYSTEMMODAL, "", "Error writing the result to the selected log directory")
         Exit
      EndIf
      FileWriteLine($hFileOpen, "WARNING: " & $name & " (" & $appID & ") was skipped because it is in the validation blacklist."  & @CRLF)
      FileClose($hFileOpen)
      $validationBlacklistSkips += 1
      ContinueLoop
   EndIf

   ; Validate the game's files and wait for the validation to finish before continuing.  If this takes less than the user-specified minimum valid
   ; scan time, retry until the number of retries has been hit.
   $validationAttempts = 0
   $validationTime = 0
   $validationFailed = 0
   While $validationTime < $minimumValidationTime AND $validationAttempts < $maxValidationAttempts
      $validationAttempts += 1
      $timer = TimerInit()
      ShellExecute("steam://validate/" & $appID)

      ; Check once a second to see if we are making progress by looking at the % in the title bar of the validation window.
      ; If we hit the validation timeout and are still at 0%, abort and retry.
      While (TimerDiff($timer) / 1000 < $validationTimeout)
         If WinExists("Validating Steam files") Then
            $windowTitle = WinGetTitle("Validating Steam files")

            ; Get how many percent we are through validation
            $EndOfPct = StringInStr($windowTitle, "%", 0, -1) - 1
            $StartOfPct = StringInStr($windowTitle, " ", 0, -1, $EndOfPct) + 1
            $percentageComplete = StringMid($windowTitle, $StartOfPct, $EndOfPct - $StartOfPct + 1)

            If $percentageComplete > 0 Then
               ExitLoop
            EndIf
         EndIf
         Sleep(1000)
      Wend

      ; If we are still at 0% when we hit this point, then we timed out, and we need to abort this validation and retry.
      If $percentageComplete = 0 Then
         ; If we're out of tries to validate this file, log that it failed to validate.
         If $validationAttempts >= $maxValidationAttempts Then
            $hFileOpen = FileOpen($loggingDirectory & "\verificationLog.txt", $FO_APPEND)
            If $hFileOpen = -1 Then
               MsgBox($MB_SYSTEMMODAL, "", "Error writing the result to the selected log directory")
               Exit
            EndIf
            FileWriteLine($hFileOpen, "ERROR: " & $name & " (" & $appID & ") failed to progress past 0% on all attempts."  & @CRLF)
            $validationErrors += 1
            $validationFailed = 1
            FileClose($hFileOpen)
         EndIf

         ; Abort the in-progress validation and move to the next iteration of the loop
         $SteamResults = WinGetHandle("Validating Steam files")
         ControlSend($SteamResults, "", "", "!+{F4}",0)
         Sleep($timeBetweenScans * 1000)
         ContinueLoop
      EndIf

      ; Since we've hit this point, we must be past 0%, so we wait on the validation to complete before moving on
      WinWait("Validating Steam files - 100% complete")
      $validationTime = TimerDiff($timer) / 1000

      ; Sometimes Steam hits 100% validation before it has *actually* finished displaying the progress bar.  Wait a few seconds to ensure we
      ; are really done before continuing
      Sleep(3000)

      ; Save a screenshot of the results
      WinActivate("Validating Steam files - 100% complete")
      $SteamResults = WinGetHandle("Validating Steam files - 100% complete")
      _ScreenCapture_CaptureWnd($loggingDirectory & "\" & StringRegExpReplace($name, '[ /:*?"<>|]', '_') & ".jpg", $SteamResults)

      ; Close the validation window
      ControlSend($SteamResults, "", "", "!+{F4}",0)
   WEnd

   ; Log the validation completed
   $hFileOpen = FileOpen($loggingDirectory & "\verificationLog.txt", $FO_APPEND)
   If $hFileOpen = -1 Then
        MsgBox($MB_SYSTEMMODAL, "", "Error writing the result to the selected log directory")
        Exit
   EndIf
   If $validationFailed = 0 Then
      If $validationTime < $minimumValidationTime Then
            FileWriteLine($hFileOpen, "WARNING: " & $name & " (" & $appID & ") had abnormally quick validation of " & $validationTime & " seconds."  & @CRLF)
            $validationWarnings += 1
      Else
         FileWriteLine($hFileOpen, $name & " (" & $appID & ") validated in " & $validationTime & " seconds."  & @CRLF)
         $validationSuccesses += 1
      EndIf
   EndIf
FileClose($hFileOpen)

   ; Give Steam client enough time to prepare for the next scan
   Sleep($timeBetweenScans * 1000)
Next
2
  • 1
    Can you copy paste the script? since the repo is removed? this is why we do not use links, but instead paste the script here. Commented Jul 29, 2023 at 15:40
  • thanks, just updated my answer
    – bernstein
    Commented Apr 24 at 23:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.