вторник, 23 мая 2023 г.

Steam validate all games

Requires administrator priveleges to run 

 

last version published here https://github.com/dreamer2/steambulkvalidate

 

When manually closing the validate window, the process will stop and cannot resume automatically.

 

1. Install python. 

2. Install python modules :

pip install vdf
pip install pywin32


3. Create two files and run in admin console python.exe validate.py


steamfolders.json

[
  "c:\\Program Files (x86)\\Steam\\steamapps\\",
  "d:\\SteamLibrary\\steamapps\\"
]


---------------------------

validate2.py - updated version, testing needed


import os
import re
import time
import vdf
import json
import winreg
import win32api
import datetime
from datetime import datetime as dt


def formatTime(elapsed_time):
if elapsed_time < 3600:
minutes, seconds = divmod(elapsed_time, 60)
return "{:.0f}m ".format(minutes)
elif elapsed_time < 86400:
hours, remainder = divmod(elapsed_time, 3600)
minutes, seconds = divmod(remainder, 60)
return "{:.0f}h {:.0f}m".format(hours, minutes)
else:
days, remainder = divmod(elapsed_time, 86400)
hours, remainder = divmod(remainder, 3600)
minutes, seconds = divmod(remainder, 60)
return "{:.0f}d {:.0f}h {:.0f}m".format(days, hours, minutes)


def waitForLogFile(appID, filePosition):
currentLogSize = os.path.getsize(logFilename)
while True:
if os.path.getsize(logFilename) > currentLogSize:
with open(logFilename, 'r') as log_file:
log_file.seek(filePosition)
for line in log_file:
logMatch = re.search(
r'.+AppID '+str(appID)+' scheduler finished : removed from schedule \(result (.+),.+\)', line)
if logMatch:
result = logMatch.group(1)
return result
currentLogSize = os.path.getsize(logFilename)
filePosition = currentLogSize
time.sleep(0.5)


def ProcessSteamFolder(directory):

global current

for filename in os.listdir(directory):
if filename.endswith('.acf'):

filepath = os.path.join(directory, filename)

with open(filepath, 'r') as f:
acf_data = vdf.load(f)

app_id = acf_data['AppState']['appid']
name = acf_data['AppState']['name']
installdir = '"' + \
os.path.join(directory, 'common',
acf_data['AppState']['installdir'])+'"'

ctime = dt.now()
ftime= f'{ctime.hour:02}:{ctime.minute:02}'

if app_id in finishedData:
print(
f'{current:02}/{total:02} {ftime} Пропуск {name} : {app_id} : {installdir}, уже в списке завершенного.')
else:
print(
f'{current:02}/{total:02} {ftime} Запуск проверки {name} : {app_id} : {installdir}, ожидаю завершения.')

cmd = f'/c start steam://validate/{app_id}'

filePosition = os.path.getsize(logFilename)

win32api.ShellExecute(0, "open", 'cmd.exe', cmd, "", 1)

result = waitForLogFile(app_id, filePosition)

ctime = dt.now()
ftime= f'{ctime.hour:02}:{ctime.minute:02}'

print(
f'{current:02}/{total:02} {ftime} проверка завершена {name} : {app_id} : {installdir}, {result}.')

finishedData[app_id] = name

if storeFinished:
try:
with open(finishedPath, 'w') as f:
json.dump(finishedData, f, indent=4)
except:
pass

time.sleep(4)

current += 1


storeFinished = True

key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE,
"SOFTWARE\\WOW6432Node\\Valve\\Steam")

steamFolder = winreg.QueryValueEx(key, "InstallPath")[0]
logFilename = os.path.join(steamFolder, "logs", "content_log.txt")

currentDate = datetime.date.today().strftime("%Y-%m-%d")
finishedPath = f"finished-{currentDate}.json"
finishedData = {}

if storeFinished:
try:
with open(finishedPath, 'r') as f:
finishedData = json.load(f)
except:
pass

alreadyProcessed = len(finishedData)

folderErrors = 0
total = 0
current = 1
startTime = time.time()

with open("steamfolders.json", 'r') as f:
steamFolders = json.load(f)
for folder in steamFolders:
if os.path.isdir(folder):
for filename in os.listdir(folder):
if filename.endswith('.acf'):
total += 1

with open("steamfolders.json", 'r') as f:
steamFolders = json.load(f)
for folder in steamFolders:
if os.path.isdir(folder):
ProcessSteamFolder(folder)
else:
folderErrors += 1


endTime = time.time()
elapsedTime = endTime - startTime

print(f'Работа завершена, время '+formatTime(elapsedTime) +
f', всего игр {len(finishedData)}, пропущено {alreadyProcessed}, ошибок пути {folderErrors}.')


---------------------------


 validate.py - Old version

Not work starting 2023jun15 steam client update :(

import os
import time
import vdf
import json
import winreg
import win32api
import win32gui
import win32con
import datetime


def formatTime(elapsed_time):
    if elapsed_time < 3600:
        minutes, seconds = divmod(elapsed_time, 60)
        return "{:.0f}m ".format(minutes)
    elif elapsed_time < 86400:
        hours, remainder = divmod(elapsed_time, 3600)
        minutes, seconds = divmod(remainder, 60)
        return "{:.0f}h {:.0f}m".format(hours, minutes)
    else:
        days, remainder = divmod(elapsed_time, 86400)
        hours, remainder = divmod(remainder, 3600)
        minutes, seconds = divmod(remainder, 60)
        return "{:.0f}d {:.0f}h {:.0f}m".format(days, hours, minutes)


def ProcessSteamFolder(directory):

    global current

    for filename in os.listdir(directory):
        if filename.endswith('.acf'):

            filepath = os.path.join(directory, filename)

            with open(filepath, 'r') as f:
                acf_data = vdf.load(f)

                app_id = acf_data['AppState']['appid']
                name = acf_data['AppState']['name']
                installdir = '"' + \
                    os.path.join(directory, 'common',
                                 acf_data['AppState']['installdir'])+'"'


                if app_id in finishedData:
                    print(f'{current}/{total} Пропуск {name} : {app_id} : {installdir}, уже в списке завершенного.')
                else:
                    print(
                        f'{current}/{total} Запуск проверки {name} : {app_id} : {installdir}, ожидаю окно завершения.')

                    cmd = f'/c start steam://validate/{app_id}'

                    #print(f'cmd.exe' + cmd)
                    win32api.ShellExecute(0, "open", 'cmd.exe', cmd, "", 1)

                    finished = False

                    while not finished:
                        time.sleep(10)
                        hwnd1 = win32gui.FindWindow(
                            None, 'Проверка файлов Steam — 100% завершено')
                        hwnd2 = win32gui.FindWindow(
                            None, 'Validating Steam files - 100% complete')
                        #print("ru win: "+str(hwnd1)+" en win: "+str(hwnd2))
                        if hwnd1:
                            win32gui.PostMessage(hwnd1, win32con.WM_CLOSE, 0, 0)
                            finished = True
                        elif hwnd2:
                            win32gui.PostMessage(hwnd2, win32con.WM_CLOSE, 0, 0)
                            finished = True

                    finishedData[app_id]=name

                    if storeFinished:
                        try:
                            with open(finishedPath, 'w') as f:
                                json.dump(finishedData, f, indent=4)
                        except:  
                            pass

                    time.sleep(4)

                current+=1


storeFinished=True

key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE,
                     "SOFTWARE\\WOW6432Node\\Valve\\Steam")

value = winreg.QueryValueEx(key, "InstallPath")[0]
steam_path = value + "\\Steam.exe"

currentDate=datetime.date.today().strftime("%Y-%m-%d")
finishedPath=f"finished-{currentDate}.json"
finishedData={}

if storeFinished:
    try:
        with open(finishedPath, 'r') as f:
            finishedData = json.load(f)
    except:  
        pass      

alreadyProcessed=len(finishedData)
                     
folderErrors=0
total=0
current=1
startTime = time.time()

with open("steamfolders.json", 'r') as f:
    steamFolders = json.load(f)
    for folder in steamFolders:
        if os.path.isdir(folder):
            for filename in os.listdir(folder):
                if filename.endswith('.acf'):
                    total+=1

with open("steamfolders.json", 'r') as f:
    steamFolders = json.load(f)
    for folder in steamFolders:
        if os.path.isdir(folder):
            ProcessSteamFolder(folder)
        else:
            folderErrors+=1


endTime = time.time()
elapsedTime = endTime - startTime

print(f'Работа завершена, время '+formatTime(elapsedTime)+f', всего игр {len(finishedData)}, пропущено {alreadyProcessed}, ошибок пути {folderErrors}.')