Compare commits

...
3 Commits
Author SHA1 Message Date
esefandClaude Opus 5.5 d84d736846 windows: write steam_appid.txt before starting (the cause of the Steam error box); start the server window minimized
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 21:22:41 +03:00
esefandClaude Opus 5.5 7d8aa4a029 windows: find the Steam error box among all server windows, up to 3 starts
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 21:15:20 +03:00
esefandClaude Opus 5.5 1cf0032927 windows: retry the first start instead of hiding a Steam setting
The 'Unable to initialize Steam' box comes from the server's first start after
an install, with or without Steam running; the registry workaround was not the fix.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 21:09:54 +03:00
4 changed files with 53 additions and 25 deletions

No files matched your search

+2 -2
View File
@@ -15,7 +15,7 @@ What you get:
You need 64-bit Windows 10 or 11 and about 1.5 GB of free space. You need 64-bit Windows 10 or 11 and about 1.5 GB of free space.
1. Click **Download ZIP** on this page and unzip it (Downloads is fine). 1. Click **Download ZIP** on this page and unzip it (Downloads is fine).
2. Double-click `setup.cmd`. Answer the questions or press Enter to keep the defaults. It downloads the game (about 600 MB) and starts the server in its own window. Say Yes when Windows asks for admin permission: that lets your friends through the firewall. 2. Double-click `setup.cmd`. Answer the questions or press Enter to keep the defaults. It downloads the game (about 600 MB) and starts the server in its own window, minimized in the taskbar. Say Yes when Windows asks for admin permission: that lets your friends through the firewall.
3. Setup then asks how your friends will join and helps with that (see below). 3. Setup then asks how your friends will join and helps with that (see below).
The server is installed in `Documents\cs16` (or `C:\Users\<you>\cs16` if your Documents folder is synced by OneDrive). From then on, double-click `cs.cmd` in that folder to start or stop the server, change the map or mode, set the bots, or see the kill counter. Closing the server window stops the server. The server is installed in `Documents\cs16` (or `C:\Users\<you>\cs16` if your Documents folder is synced by OneDrive). From then on, double-click `cs.cmd` in that folder to start or stop the server, change the map or mode, set the bots, or see the kill counter. Closing the server window stops the server.
@@ -68,7 +68,7 @@ More for players (Steam and non-Steam): [docs/PLAYERS.md](docs/PLAYERS.md).
- **Setup stopped with an error.** Fix what it says (usually the internet connection) and run it again. It continues where it stopped. - **Setup stopped with an error.** Fix what it says (usually the internet connection) and run it again. It continues where it stopped.
- **Friends can't connect, but you can.** On Windows, run `cs.cmd` → 10 → 1 and accept the admin prompt so the firewall lets them in. If they're not in your house, check the playit tunnel or the port forward. - **Friends can't connect, but you can.** On Windows, run `cs.cmd` → 10 → 1 and accept the admin prompt so the firewall lets them in. If they're not in your house, check the playit tunnel or the port forward.
- **"Unable to initialize Steam" (Windows).** Start the server from `cs.cmd`, not by opening `hlds.exe` directly. - **"Unable to initialize Steam" (Windows).** Close the box and start the server with `cs.cmd` → 9 instead of opening `hlds.exe` directly: `cs.cmd` writes the `steam_appid.txt` file the server needs.
- **The server window closes right away, or setup says files are missing.** Your antivirus probably removed a file. Allow the install folder in it and run `setup.cmd` again. - **The server window closes right away, or setup says files are missing.** Your antivirus probably removed a file. Allow the install folder in it and run `setup.cmd` again.
- **The port is taken.** Setup offers the next free port. Your friends then need that port in the address. - **The port is taken.** Setup offers the next free port. Your friends then need that port in the address.
+1 -1
View File
@@ -90,7 +90,7 @@ The same stack, native instead of Docker: the win32 builds of every part, `hlds.
Things that differ from Linux: Things that differ from Linux:
- **Steam installed on the same PC.** The server's `steam_api.dll` finds the Steam client's `steamclient.dll` through `HKCU\Software\Valve\Steam\ActiveProcess\SteamClientDll` and loads that instead of its own, which ends in "Unable to initialize Steam". `Start-CsServer` renames that value until the server answers queries (a few seconds), then puts it back. Steam rewrites it at every start anyway, and every script repairs it on load if a start was interrupted. - **`steam_appid.txt`.** A fresh SteamCMD install has no `hlds\steam_appid.txt`. `hlds.exe` writes it while starting, but after Steam has already failed, so the very first start ends in a "Fatal error: Unable to initialize Steam" box that blocks the desktop until it's closed. `Start-CsServer` writes the file (`10`) before every start. If the box shows up anyway, it closes the server and starts it again (up to 3 times). The server window starts minimized so it doesn't take the focus.
- **Firewall.** Setup adds an allow rule for `hlds\hlds.exe` on all network types (admin prompt) before the first start, so Windows' own popup doesn't appear, and removes block rules Windows made if that popup was ever cancelled. Normal users often can't read firewall rules, so the result is remembered in `secrets\firewall-rule.txt`. - **Firewall.** Setup adds an allow rule for `hlds\hlds.exe` on all network types (admin prompt) before the first start, so Windows' own popup doesn't appear, and removes block rules Windows made if that popup was ever cancelled. Normal users often can't read firewall rules, so the result is remembered in `secrets\firewall-rule.txt`.
- **Install folder.** `Documents\cs16`, or `%USERPROFILE%\cs16` when Documents is synced by OneDrive, or `C:\cs16` when the user folder has non-ASCII characters (SteamCMD and HLDS can't handle them). The folder is remembered in `%LOCALAPPDATA%\cs16-dm-server\install-folder.txt`, so running a newly downloaded `setup.cmd` updates the existing install. - **Install folder.** `Documents\cs16`, or `%USERPROFILE%\cs16` when Documents is synced by OneDrive, or `C:\cs16` when the user folder has non-ASCII characters (SteamCMD and HLDS can't handle them). The folder is remembered in `%LOCALAPPDATA%\cs16-dm-server\install-folder.txt`, so running a newly downloaded `setup.cmd` updates the existing install.
- **Console log.** `-condebug` writes `hlds\qconsole.log`; setup shows its end when the server doesn't come up. - **Console log.** `-condebug` writes `hlds\qconsole.log`; setup shows its end when the server doesn't come up.
+49 -21
View File
@@ -334,31 +334,59 @@ function Start-CsServer($root) {
$y = $y -replace '(?m)^yb_difficulty ".*"', ('yb_difficulty "' + [int]$s.CS_BOT_DIFFICULTY + '"') $y = $y -replace '(?m)^yb_difficulty ".*"', ('yb_difficulty "' + [int]$s.CS_BOT_DIFFICULTY + '"')
Write-TextFile $ycfg $y Write-TextFile $ycfg $y
$hargs = "-console -condebug -game cstrike -port $([int]$s.CS_PORT) +maxplayers $([int]$s.CS_MAXPLAYERS) +map $($s.CS_MAP) +log on" $hargs = "-console -condebug -game cstrike -port $([int]$s.CS_PORT) +maxplayers $([int]$s.CS_MAXPLAYERS) +map $($s.CS_MAP) +log on"
Restore-SteamClientSetting # A fresh install has no steam_appid.txt. hlds writes it while starting, but too late: Steam
# With Steam installed, the server's steam_api.dll loads the Steam client's steamclient.dll # has already failed and the server sits on a "Fatal error: Unable to initialize Steam" box.
# (found through this registry value) instead of its own, and stops with "Unable to initialize # 10 = Counter-Strike.
# Steam". So the value is hidden until the server answers queries (Steam is set up by then: $appid = Join-Path $h 'steam_appid.txt'
# a few seconds) or gives up. Steam writes it again at every start, and if (-not (Test-Path -LiteralPath $appid) -or [IO.File]::ReadAllText($appid).Trim() -ne '10') { Write-TextFile $appid "10`r`n" }
# Restore-SteamClientSetting (run whenever a script loads this file) repairs an interrupted run. # If that box still shows up, close the server and start it again. The window starts minimized
# (A 64-bit PowerShell can't see the 32-bit server's DLLs, so the query is the signal.) # so it doesn't take the keyboard away from whatever you're doing.
$hidden = $false for ($try = 1; $try -le 3; $try++) {
if ((Get-ItemProperty -Path $Script:SteamKey -ErrorAction SilentlyContinue).SteamClientDll) { $p = Start-Process -FilePath (Join-Path $h 'hlds.exe') -WorkingDirectory $h -ArgumentList $hargs -PassThru -WindowStyle Minimized
Rename-ItemProperty -Path $Script:SteamKey -Name SteamClientDll -NewName $Script:SteamHidden if (-not (Test-SteamFailure $p ([int]$s.CS_PORT))) { break }
$hidden = $true Stop-Process -Id $p.Id -Force -ErrorAction SilentlyContinue
Start-Sleep -Seconds 2
Write-Host " (Steam wasn't ready yet, starting again)"
} }
try {
$p = Start-Process -FilePath (Join-Path $h 'hlds.exe') -WorkingDirectory $h -ArgumentList $hargs -PassThru
if ($hidden) {
$end = (Get-Date).AddSeconds(90)
while ((Get-Date) -lt $end -and -not $p.HasExited) {
if (Get-A2SInfo '127.0.0.1' ([int]$s.CS_PORT) 1000) { break }
Start-Sleep -Milliseconds 500
}
}
} finally { if ($hidden) { Restore-SteamClientSetting } }
return $true return $true
} }
# Waits up to 40 s for the server to answer or to show its "Fatal error" box.
# Returns $true for that box.
function Test-SteamFailure($p, [int]$port) {
$end = (Get-Date).AddSeconds(40)
while ((Get-Date) -lt $end -and -not $p.HasExited) {
if (Get-A2SInfo '127.0.0.1' $port 1000) { return $false }
if (@(Get-ProcessWindowTitles $p.Id | Where-Object { $_ -like 'Fatal error*' }).Count) { return $true }
Start-Sleep -Milliseconds 500
}
return $false
}
# Titles of all top-level windows of a process (the error box is not always its main window)
function Get-ProcessWindowTitles([int]$processId) {
if (-not ('Cs16Win' -as [type])) {
Add-Type @'
using System; using System.Text; using System.Collections.Generic; using System.Runtime.InteropServices;
public static class Cs16Win {
delegate bool EnumProc(IntPtr h, IntPtr l);
[DllImport("user32.dll")] static extern bool EnumWindows(EnumProc f, IntPtr l);
[DllImport("user32.dll")] static extern int GetWindowThreadProcessId(IntPtr h, out int pid);
[DllImport("user32.dll", CharSet = CharSet.Unicode)] static extern int GetWindowText(IntPtr h, StringBuilder s, int n);
public static string[] Titles(int want) {
var r = new List<string>();
EnumWindows((h, l) => { int pid; GetWindowThreadProcessId(h, out pid);
if (pid == want) { var t = new StringBuilder(256); GetWindowText(h, t, 256); r.Add(t.ToString()); } return true; }, IntPtr.Zero);
return r.ToArray();
}
}
'@
}
[Cs16Win]::Titles($processId)
}
# An earlier version (2026-10-15) hid this Steam setting while starting the server; this puts it
# back if a start was interrupted then. Harmless otherwise.
$Script:SteamKey = 'HKCU:\Software\Valve\Steam\ActiveProcess' $Script:SteamKey = 'HKCU:\Software\Valve\Steam\ActiveProcess'
$Script:SteamHidden = 'SteamClientDll_hidden_by_cs16' $Script:SteamHidden = 'SteamClientDll_hidden_by_cs16'
+1 -1
View File
@@ -199,7 +199,7 @@ Write-Host " connect 127.0.0.1:$port (on this PC)" -ForegroundColor Gr
foreach ($ip in Get-LanIPv4) { Write-Host " connect ${ip}:$port (same house)" -ForegroundColor Green } foreach ($ip in Get-LanIPv4) { Write-Host " connect ${ip}:$port (same house)" -ForegroundColor Green }
if ($s.CS_PUBLIC_ADDR) { Write-Host " connect $($s.CS_PUBLIC_ADDR) (friends over the internet)" -ForegroundColor Green } if ($s.CS_PUBLIC_ADDR) { Write-Host " connect $($s.CS_PUBLIC_ADDR) (friends over the internet)" -ForegroundColor Green }
Write-Host '' Write-Host ''
Write-Host " The server runs in its own window. Close that window to stop it." Write-Host " The server runs in its own window (minimized in the taskbar). Close that window to stop it."
Write-Host " Menu (start, stop, map, mode, bots, kill counter, ...): double-click cs.cmd in" Write-Host " Menu (start, stop, map, mode, bots, kill counter, ...): double-click cs.cmd in"
Write-Host " $Root" Write-Host " $Root"
if ($repo -ine $Root -and -not $Yes) { Start-Process explorer.exe -ArgumentList "`"$Root`"" } if ($repo -ine $Root -and -not $Yes) { Start-Process explorer.exe -ArgumentList "`"$Root`"" }