fix(watcher): find Steam EFT installs and recover from a missing logs path - #213
Open
JacobWoodson wants to merge 1 commit into
Open
JacobWoodson wants to merge 1 commit into
JacobWoodson wants to merge 1 commit into
Conversation
… path Steam writes its uninstall entry for EFT with an empty InstallLocation, so GetDefaultLogsFolder fell through every candidate and threw. The null-only guard also let the empty value through, producing relative "Logs" and "build\Logs" probes against the process working directory. Discovery now falls back to walking the Steam libraries from libraryfolders.vdf and reading appmanifest_3932890.acf, which resolves installs in non-default libraries. All registry lookups check both the 32- and 64-bit views, since Valve's own keys are 32-bit. A missing logs folder is no longer fatal: GetDefaultLogsFolder returns an empty string, and Start() keeps the process and screenshot watchers running while reporting one actionable message. Previously the empty path reached FileSystemWatcher, which threw "Error reading the directory." from EnableRaisingEvents and skipped the rest of Start(). Because that throw left EnableRaisingEvents false, the LogsPath setter's recovery branch never ran and choosing a folder in Settings silently did nothing until restart. Startup state is now tracked explicitly so setting a path completes the deferred startup. Fixes the-hideout#210 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Contributor
|
Fix was inncluded in PR211. Please verify resolution before closing. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #210.
Root cause is not what the issue describes
The issue attributes the failure to the discovery code relying on "a single machine-wide Steam uninstall registry key". The key and the registry view are actually fine — the value inside it is not.
On a machine that reproduces the bug (EFT installed through Steam, no Battlestate launcher):
GetDefaultLogsFolderguards withif (installPath == null), which an empty string passes. Discovery then builds relative paths —Path.Combine("", "Logs")isLogs, andPath.Combine("", "build", "Logs")isbuild\Logs— which get probed against TarkovMonitor's working directory rather than against the install. Both miss, the loop exhausts, and it throwsNo Tarkov install path found.This is not an edge case. On that same machine, 57 of 98
Steam App *uninstall entries have no usableInstallLocation: some are written with the value blank (Destiny 2 shows the identical pattern), others are empty keys with no values at all. The uninstall entry alone is not a reliable source for a Steam install, which is why this PR adds the Steam library walk the issue asks for.Worth recording for anyone who reads the issue first: the registry view is not the problem. Steam writes these entries to the 64-bit view (98 entries under
Registry64, 0 underRegistry32), so the existing non-WOW6432Nodepath was correct. This PR still checks both views, becauseHKLM\SOFTWARE\Valve\Steamgenuinely is a 32-bit key.The cascade after the throw
The reported second error is reproducible, and the ordering matters:
LogsPathgetter catches the throw, reportsgetting logs path, and returns"".logFileCreateWatcher.Path = ""is a silent no-op — the setter short-circuits when the value equals the already-empty backing field, so nothing throws here.EnableRaisingEvents = truethen throwsFileNotFoundException: Error reading the directory., which is the second message users see.Because the throw lands on step 3 rather than step 1, the remainder of
Start()never runs, soprocessTimerandSetupScreenshotWatcher()are silently skipped too — the process and screenshot watchers die alongside log monitoring.It also leaves
EnableRaisingEventsfalse, and theLogsPathsetter only re-points the watcherif (logFileCreateWatcher.EnableRaisingEvents). So after a failed startup, choosing a folder under Settings > Logs Folder writes the setting and does nothing else. Monitoring stays dead until the app is restarted, with no feedback that anything is still wrong.Changes
All in
GameWatcher.cs.Discovery
IsNullOrEmptyguard onInstallLocation, so a blank value no longer produces relative path probes.Valve\Steam, enumerate libraries fromlibraryfolders.vdf, and readinstalldirfromappmanifest_3932890.acfin each. Falls back to the conventionalEscape from Tarkovfolder name when the manifest is missing. This is what makes non-default libraries work.GetDefaultLogsFolderreturns""instead of throwing. Both callers already handle an empty result;Settings.razorkeeps itstry/catchfor genuine registry failures.Recoverable startup
Start()starts the process timer and screenshot watcher first, then callsStartLogWatcher(). A missing folder reports one actionable message (Could not find the Escape from Tarkov logs folder. Choose it under Settings > Logs Folder to start monitoring.) and leaves the rest of the app running. No empty path reachesFileSystemWatcher.Deferred startup completion
watcherStarted/logWatcherStartedflags replace theEnableRaisingEventscheck. SettingLogsPathafter a deferred start now completes startup, so the existingcustomLogsPathhandler inMainBlazorUIrecovers without a restart.MainBlazorUIitself is unchanged.GetLatestLogFoldercalledlogFolders.Last()on a possibly-empty array; it now returns""for a logs folder with no session subfolders, and the caller lets the create-watcher pick up the next one EFT writes.Verification
Built against the pinned SDK (10.0.302): 0 errors, 230 warnings — identical to the master baseline.
Before/after on the reproducing machine, invoking the compiled
GetDefaultLogsFolderand then replaying whatStart()does with the result:That install is in a non-default Steam library with the
build\Logslayout and no Battlestate registry key. Also exercised directly: library enumeration returns all four libraries fromlibraryfolders.vdf; manifest parsing returns the expectedinstalldir; a missing manifest and a nonexistent install path both return empty without throwing; and both theLogsandbuild\Logslayouts resolve.Existing Battlestate installs are unaffected — that registry branch is unchanged apart from the stricter empty-value guard, and it is still tried before any Steam lookup.
Not addressed
user.config/ missingcustomLogsPathnode item from the issue. That concerns hand-editing and external scripts, not app behavior; the app reads the setting through the generated wrapper, which returns the default when the node is absent.GetDefaultLogsFolderreaches the registry and filesystem through static calls, so making it testable needs seams that felt out of scope for a bugfix. Happy to do it as a follow-up if you want it.MessageLogbuffers into a list so constructor-time messages still render once the WebView loads. That symptom looks like Handle PvpSeason session mode without flooding or freezing the Dashboard #187 (an oversized message breaking the layout) rather than this bug, so I lefteft.Start()where it is.🤖 Generated with Claude Code