我想通过命令行更新我的所有 Steam 游戏,以便打开 Steam 时一切准备就绪。
我正在调查此事,发现steam命令这给出了更新反恐精英的示例app_update 740 validate
。要使用它,我首先需要某种方式获取已安装 Steam 游戏的所有 ID。
答案1
带有登录的版本,它将要求进行双因素验证,我不知道您是否可以以某种方式让它记住(没有探索过,我认为它可以或应该)该登录。
Add-Type -AssemblyName System.Windows.Forms
$host.ui.RawUI.WindowTitle = "SteamCMD autoupdater"
function Check-LogExistsAndClean {
param(
[string]$logFile
)
if (Test-Path $logFile) {
$choice = [System.Windows.Forms.MessageBox]::Show("Log file already exists. Do you want to clean it?", "Log File Exists on path:$logFile`nDo you want to clean it?", "YesNo", "Warning")
if ($choice -eq "Yes") {
Clear-Content $logFile
Write-Host "Log file cleaned."
}
} else {
Write-Log -Message "Log file does not exist. Creating new log file." -LogFile $logFile
}
}
function Get-PathForThis {
param(
[string]$description
)
$folderBrowser = New-Object System.Windows.Forms.FolderBrowserDialog
$folderBrowser.Description = $description
$folderBrowser.RootFolder = "MyComputer"
$folderBrowser.ShowNewFolderButton = $false
[void]$folderBrowser.ShowDialog()
return $folderBrowser.SelectedPath
}
function Write-Log {
param(
[string]$Message,
[string]$LogFile
)
Add-content -Path $LogFile -Value $Message
}
function Get-SteamCredentials {
$form = New-Object System.Windows.Forms.Form
$form.Text = "Enter Steam Credentials"
$form.Size = New-Object System.Drawing.Size(300,200)
$form.StartPosition = "CenterScreen"
$form.Topmost = $true
$labelName = New-Object System.Windows.Forms.Label
$labelName.Location = New-Object System.Drawing.Point(10,20)
$labelName.Size = New-Object System.Drawing.Size(280,20)
$labelName.Text = "Name (Default: anonymous):"
$form.Controls.Add($labelName)
$textBoxName = New-Object System.Windows.Forms.TextBox
$textBoxName.Location = New-Object System.Drawing.Point(10,40)
$textBoxName.Size = New-Object System.Drawing.Size(260,20)
$textBoxName.Text = "anonymous"
$form.Controls.Add($textBoxName)
$labelPassword = New-Object System.Windows.Forms.Label
$labelPassword.Location = New-Object System.Drawing.Point(10,70)
$labelPassword.Size = New-Object System.Drawing.Size(280,20)
$labelPassword.Text = "Password (Press No to continue or enter credentials):"
$form.Controls.Add($labelPassword)
$textBoxPassword = New-Object System.Windows.Forms.TextBox
$textBoxPassword.Location = New-Object System.Drawing.Point(10,90)
$textBoxPassword.Size = New-Object System.Drawing.Size(260,20)
$textBoxPassword.Text = "Press No to continue or enter credentials"
$textBoxPassword.Add_Click({
if ($textBoxPassword.Text -eq "Press No to continue or enter credentials") {
$textBoxPassword.Text = ""
$buttonYes.Enabled = $true
}
}) # Clear text when clicked
$form.Controls.Add($textBoxPassword)
$buttonYes = New-Object System.Windows.Forms.Button
$buttonYes.Location = New-Object System.Drawing.Point(10,120)
$buttonYes.Size = New-Object System.Drawing.Size(75,23)
$buttonYes.Text = "Yes"
$buttonYes.Enabled = $false # Disable button initially
$form.Controls.Add($buttonYes)
$buttonYes.Add_Click({
$form.Close()
})
$buttonNo = New-Object System.Windows.Forms.Button
$buttonNo.Location = New-Object System.Drawing.Point(90,120)
$buttonNo.Size = New-Object System.Drawing.Size(75,23)
$buttonNo.Text = "No"
$buttonNo.Add_Click({
$form.Close()
$global:cancelled = $true
})
$form.Controls.Add($buttonNo)
$buttonCancel = New-Object System.Windows.Forms.Button
$buttonCancel.Location = New-Object System.Drawing.Point(170,120)
$buttonCancel.Size = New-Object System.Drawing.Size(75,23)
$buttonCancel.Text = "Cancel"
$buttonCancel.Add_Click({
$form.Close()
[Environment]::Exit(0)
})
$form.Controls.Add($buttonCancel)
$form.Add_Shown({$textBoxName.Focus()})
$form.ShowDialog() | Out-Null
if ($global:cancelled) {
return $null
}
$steamUser = $textBoxName.Text
$steamPass = $textBoxPassword.Text
return $steamUser, $steamPass
}
$logFile = "$PSScriptRoot\SteamUpdateLog.txt"
Check-LogExistsAndClean -logFile $logFile
$steamcmdAppRoot = Get-PathForThis -description "Select SteamCMD folder"
if ($steamcmdAppRoot -eq "") {
exit
}
$steamPath = Get-PathForThis -description "Select Steam folder"
if ($steamPath -eq "") {
exit
}
$steamAppsPath = "$steamPath\steamapps"
$steamCommonPath = "$steamAppsPath\common"
$steamUser = "anonymous"
$steamPass = "Press No to continue or enter credentials"
$userInput = Get-SteamCredentials
if ($userInput -ne $null) {
$steamUser = $userInput[0]
$steamPass = $userInput[1]
}
function Get-InstallDirectoryFromACF {
param(
[string]$acfFilePath
)
Write-Host "Reading content of ACF file: $acfFilePath"
$content = Get-Content -Path $acfFilePath -Raw
$matches = $content | Select-String '"name"\s+"(.*?)"'
if ($matches) {
$installDir = $matches.Matches.Groups[1].Value
Write-Host "Install Directory found: $installDir"
return $installDir
} else {
Write-Host "No install directory found."
return $null
}
}
function Get-AppIdsFromACFFiles {
param(
[string]$directory,
[string]$logFile
)
$acfFiles = Get-ChildItem -Path $directory -Filter "appmanifest_*.acf" -File
$appIds = @()
foreach ($file in $acfFiles) {
$content = Get-Content -Path $file.FullName -Raw
$appIdMatch = [regex]::Match($content, '"appid"\s+"(\d+)"')
$nameMatch = [regex]::Match($content, '"name"\s+"(.*?)"')
if ($appIdMatch.Success -and $nameMatch.Success) {
$appId = $appIdMatch.Groups[1].Value
$name = $nameMatch.Groups[1].Value
Write-Log -Message "Found app with ID:$appId and name:$name" -LogFile $logFile
$appInfo = [PSCustomObject]@{
AppId = $appId
Name = $name
}
$appIds += $appInfo
}
}
return $appIds
}
$appIds = Get-AppIdsFromACFFiles -directory $steamAppsPath -logFile $logFile
if ($appIds.Count -eq 0) {
Write-Log -Message "No app IDs found in ACF files." -LogFile $logFile
exit
}
$errorCount = 0
foreach ($appIdInfo in $appIds) {
$appId = $appIdInfo.AppId
$name = $appIdInfo.Name
$acfFilePath = "$steamAppsPath\appmanifest_$appId.acf"
$installDir = Get-InstallDirectoryFromACF -acfFilePath $acfFilePath
if ($installDir) {
$gameInstallPath = "$steamCommonPath\$installDir"
Write-Log -Message "Updating game on path: $gameInstallPath" -LogFile $gameInstallPath
# Check if default credentials are used or if user entered custom credentials
if ($steamUser -eq "anonymous" -and $steamPass -eq "Press No to continue or enter credentials") {
$arguments = "+force_install_dir $gameInstallPath +login anonymous +app_update $appId validate +quit"
} else {
$arguments = "+force_install_dir $gameInstallPath +login $steamUser $steamPass +app_update $appId validate +quit"
}
try {
Start-Process -FilePath $steamcmdAppRoot\steamcmd.exe -ArgumentList $arguments -NoNewWindow -Wait
Write-Log -Message "Game with ID:$appId and name:$name updated at path:$gameInstallPath" -LogFile $logFile
} catch {
$errorCount++
Write-Log -Message "Failed to update game with ID:$appId and name:$name. Error: $_" -LogFile $logFile
}
} else {
$errorCount++
Write-Log -Message "Failed to find install directory for app ID:$appId and name:$name." -LogFile $logFile
}
}
Write-Log -Message "Steam games updated." -LogFile $logFile
if ($errorCount -eq 0) {
Write-Log -Message "There were no errors." -LogFile $logFile
} else {
Write-Log -Message "There were a total of $errorCount errors." -LogFile $logFile
}
pause
答案2
我没有添加用户名和密码,因为理论上不需要,但如果事实证明需要,我会进一步扩展脚本。
创建新的 Named.ps1 脚本并将整个代码粘贴到其中,保存文件。然后在文件上单击鼠标右键,选择“使用 PowerShell 运行”选项。
当您运行脚本时,它会询问您 SteamCMD 的位置以及 Steam 的安装位置。它会扫描您的 steamapps 文件夹以查找 .vcf 文件(如果安装了游戏,这些文件应该存在)。从 .vcf 文件中提取必要信息后,它会尝试更新您的应用程序。我注意到有一次 SteamCMD 超时,但在第二次和第三次测试中正常运行。
Add-Type -AssemblyName System.Windows.Forms
function Check-LogExistsAndClean {
param(
[string]$logFile
)
if (Test-Path $logFile) {
$choice = [System.Windows.Forms.MessageBox]::Show("Log file already exists. Do you want to clean it?", "Log File Exists on path:$logFile`nDo you want to clean it?", "YesNo", "Warning")
if ($choice -eq "Yes") {
Clear-Content $logFile
Write-Host "Log file cleaned."
}
} else {
Write-Log -Message "Log file does not exist. Creating new log file." -LogFile $logFile
}
}
function Get-PathForThis {
param(
[string]$description
)
$folderBrowser = New-Object System.Windows.Forms.FolderBrowserDialog
$folderBrowser.Description = $description
$folderBrowser.RootFolder = "MyComputer"
$folderBrowser.ShowNewFolderButton = $false
[void]$folderBrowser.ShowDialog()
return $folderBrowser.SelectedPath
}
function Write-Log {
param(
[string]$Message,
[string]$LogFile
)
Add-content -Path $LogFile -Value $Message
}
$logFile = "$PSScriptRoot\SteamUpdateLog.txt"
Check-LogExistsAndClean -logFile $logFile
$steamcmdAppRoot = Get-PathForThis -description "Select SteamCMD folder"
$steamPath = Get-PathForThis -description "Select Steam folder"
$steamAppsPath = "$steamPath\steamapps"
$steamCommonPath = "$steamAppsPath\common"
function Get-InstallDirectoryFromACF {
param(
[string]$acfFilePath
)
Write-Host "Reading content of ACF file: $acfFilePath"
$content = Get-Content -Path $acfFilePath -Raw
$matches = $content | Select-String '"name"\s+"(.*?)"'
if ($matches) {
$installDir = $matches.Matches.Groups[1].Value
Write-Host "Install Directory found: $installDir"
return $installDir
} else {
Write-Host "No install directory found."
return $null
}
}
function Get-AppIdsFromACFFiles {
param(
[string]$directory,
[string]$logFile
)
$acfFiles = Get-ChildItem -Path $directory -Filter "appmanifest_*.acf" -File
$appIds = @()
foreach ($file in $acfFiles) {
$content = Get-Content -Path $file.FullName -Raw
$appIdMatch = [regex]::Match($content, '"appid"\s+"(\d+)"')
$nameMatch = [regex]::Match($content, '"name"\s+"(.*?)"')
if ($appIdMatch.Success -and $nameMatch.Success) {
$appId = $appIdMatch.Groups[1].Value
$name = $nameMatch.Groups[1].Value
Write-Log -Message "Found app with ID:$appId and name:$name" -LogFile $logFile
$appInfo = [PSCustomObject]@{
AppId = $appId
Name = $name
}
$appIds += $appInfo
}
}
return $appIds
}
$appIds = Get-AppIdsFromACFFiles -directory $steamAppsPath -logFile $logFile
if ($appIds.Count -eq 0) {
Write-Log -Message "No app IDs found in ACF files." -LogFile $logFile
exit
}
$errorCount = 0
foreach ($appIdInfo in $appIds) {
$appId = $appIdInfo.AppId
$name = $appIdInfo.Name
$acfFilePath = "$steamAppsPath\appmanifest_$appId.acf"
$installDir = Get-InstallDirectoryFromACF -acfFilePath $acfFilePath
if ($installDir) {
$gameInstallPath = "$steamCommonPath\$installDir"
Write-Log -Message "Updating game on path: $gameInstallPath" -LogFile $gameInstallPath
$arguments = "+force_install_dir $gameInstallPath +login anonymous +app_update $appId validate +quit"
try {
Start-Process -FilePath $steamcmdAppRoot\steamcmd.exe -ArgumentList $arguments -NoNewWindow -Wait
Write-Log -Message "Game with ID:$appId and name:$name updated at path:$gameInstallPath" -LogFile $logFile
} catch {
$errorCount++
Write-Log -Message "Failed to update game with ID:$appId and name:$name. Error: $_" -LogFile $logFile
}
} else {
$errorCount++
Write-Log -Message "Failed to find install directory for app ID:$appId and name:$name." -LogFile $logFile
}
}
Write-Log -Message "Steam games updated." -LogFile $logFile
if ($errorCount -eq 0) {
Write-Log -Message "There were no errors." -LogFile $logFile
} else {
Write-Log -Message "There were a total of $errorCount errors." -LogFile $logFile
}
pause
答案3
没有直接命令一次性更新所有 Steam 游戏。然而,这是列表中的每个 SteamCMD 命令,您可以使用变通方法一次性更新所有 Steam 游戏。