Windows services tab + security CI + wiki + UI tabs - #1
Merged
Conversation
Builds installer + portable EXE on every push to a non-main branch and
on workflow_dispatch. Uploads as workflow artifacts only (no GitHub
Release) so the auto-updater never sees them. Version stamped as
{nextStable}-dev.{sha7} so the parsed semver sits above latest stable,
preventing the dev build from offering itself a downgrade to stable
during testing.
Adds a curated catalog of 10 Windows services that are commonly disabled
for gaming setups (DiagTrack, MapsBroker, WMPNetworkSvc, Fax, RetailDemo,
WerSvc, lfsvc, plus opt-ins for WSearch, SysMain, TabletInputService).
For each service the Settings UI shows display name + service ID, what
it does, the Windows default start type, the current start type+status,
and reboot/recommended/not-installed badges. Per-service the user
chooses Want=Disabled or Default, can toggle Monitor, and can enable
Auto-apply (re-applies via UAC if Windows or another app re-enables a
disabled service).
A 'Gaming optimized' / 'Default' radio at the top of the section is a
one-click preset that flips Want across the recommended subset.
WindowsServiceController wraps sc.exe via Verb=runas; DisableElevated
chains stop + config disabled into a single UAC prompt. Reads use
ServiceController + the registry (no elevation).
WindowsServiceMonitor implements IMonitoredSetting, one instance per
ServiceDefinition, registered in App.xaml.cs from ServiceCatalog.All.
Drift is only reported when the user opted into Want=Disabled (current
!= Disabled) or Want=Default-and-currently-Disabled — Manual->Auto
trigger transitions don't churn the monitor.
ServicePref ('Monitor', 'DesiredDisabled', 'AutoApply') is keyed by
service name in AppConfig.Services so adding services to the catalog
doesn't migrate existing configs.
…Display tabs Single-window scroll was getting unwieldy with the services section added. Each tab now has its own ScrollViewer; the Cancel/Apply/Save row stays docked at the bottom across all tabs. Bumped default width 780 -> 820 so tab headers fit comfortably; reduced default height 760 -> 720 since each tab needs less vertical space than the combined view. All x:Names, bindings, and event handlers preserved unchanged — code-behind didn't need to change.
…rvices
The Want column on each service card is now three radios — Default,
Manual, Disabled — instead of two. This was driven by IP Helper, where
'Manual + stop' is a much safer target than full Disabled (some IPv6
tunneling on home networks still relies on it being available on demand).
Services added:
Recommended (none — added without preset membership):
* Spooler Print Spooler — break printing if disabled
* RemoteRegistry Remote Registry — already Disabled by default on Win11
* DoSvc Delivery Optimization
* iphlpsvc IP Helper — Manual is safer than Disabled
* XboxGipSvc Xbox Accessory Management
* XblAuthManager Xbox Live Auth Manager
* XblGameSave Xbox Live Game Save
* XboxNetApiSvc Xbox Live Networking
None of the new services are in the Gaming-optimized preset; the user
opts into them individually. Existing 7 'recommended' services keep
their preset membership unchanged.
Model changes:
* ServiceDefinition.RecommendedDisable (bool)
-> RecommendedTarget (ServiceTargetState?)
* ServicePref.DesiredDisabled (bool)
-> Desired (ServiceTargetState; serialized as a string via
JsonStringEnumConverter so configs are diffable)
* WindowsServiceController.SetManualElevated wraps 'sc stop' +
'sc config start= demand' in one UAC prompt.
* WindowsServiceMonitor maps Desired -> ServiceStartType, dispatches
to the matching elevated call. The Default-state drift heuristic
is widened: it now also undoes a prior Manual change when the
service's default is Auto/AutoDelayed.
Note: a dev tester who installed the previous build with DesiredDisabled
in their config will see services revert to Want=Default after this
upgrade (the old field is ignored). No existing public release wrote
DesiredDisabled, so stable users are unaffected.
The two callers (MonitorService periodic trim, settings-closed cleanup) are removed. Psapi.TrimSelf and the GC compaction calls still happen on the same cadence — only the changes.log line is gone. LogMemorySnapshot itself is intentionally kept; opt back in at a specific call site if you're tracking a regression.
TabItem defaults HorizontalContentAlignment + VerticalContentAlignment to Center, which made the General tab's single Card float in the vertical middle of the tab area with a wall of empty space above it. Setting both to Stretch on the TabControl propagates to every TabItem so each tab's ScrollViewer fills the available area and content sits naturally at the top.
The display name + 4 badges + service-name pill on a single horizontal line was getting truncated for long entries (Connected User Experiences and Telemetry, Xbox Live Networking Service, etc.). Moves all badges to a WrapPanel directly under the title so the name always has the full card width, and badges flow to a third line if a card collects all four of them.
Wiki content
Lifts Installation, Build-from-source, File-locations, Logging,
Verification, and Source-file-reference out of README into
docs/wiki/ markdown files. Adds Home + _Sidebar nav and a Security
page covering trust signals + spot-check guidance.
tools/sync-wiki.ps1 mirrors docs/wiki/ -> github.com/<repo>.wiki.git
on demand; first run requires the user to initialize the wiki by
creating any first page in the GitHub UI.
Security CI
* .github/workflows/codeql.yml — CodeQL SAST on push, PR, and weekly
schedule. Both csharp and actions languages.
* .github/dependabot.yml — weekly NuGet + GitHub Actions watch with
auto-PRs.
* .github/workflows/scorecard.yml — OpenSSF Scorecard public score
with SARIF upload to code-scanning.
* release.yml gains a 'dotnet list package --vulnerable' gate before
publish, plus a SHA-256 checksum step that emits SHA256SUMS.txt
alongside the installer + portable EXE on every Release.
* SECURITY.md — disclosure policy, supported-version statement,
private-channel reporting (Security Advisories preferred).
README
Trims to overview + screenshot + feature table + verification +
security summary. Detail moves to wiki. Adds CodeQL + Scorecard
badges next to the existing build/release/license set.
Action pinning Every step in build/dev-build/release/codeql/scorecard now references a 40-char commit SHA with the matching version as a trailing comment. Dependabot updates these in place. Improves OpenSSF Scorecard's Pinned-Dependencies score and removes the 'mutable tag' supply-chain exposure where a compromised maintainer could repoint @v4 mid-flight. Deterministic CI builds csproj sets Deterministic=true (always) and ContinuousIntegrationBuild= true under GITHUB_ACTIONS. Combined with portable PDBs, this makes CI-built binaries byte-identical across runs at the same source commit — a prerequisite for any future reproducibility claim. Optional VirusTotal scan on Release release.yml gains an opt-in step that uploads installer + portable EXE to VirusTotal and appends per-engine result URLs to the auto-generated release notes. Gated on the repo variable ENABLE_VIRUSTOTAL=true *and* a VIRUSTOTAL_API_KEY secret — skips silently otherwise. release-notes- extra.md is initialized empty so body_path: append still works when VT is disabled. Architecture rationale wiki page New page covering why GamerGuardian is user-mode P/Invoke and not a kernel driver, why polling instead of event subscriptions, why a single-file ~77 MB self-contained publish, why per-user install, why one IMonitoredSetting per setting, why HKLM writes go through reg.exe / sc.exe rather than Verb=runas of the app itself, and why no telemetry. Linked from the home page and sidebar.
signpath.io is the commercial product; the free OSS program lives at signpath.org. Updates both wiki references to signpath.org and adds the direct apply link in the Security page.
Required by SignPath Foundation for OSS code-signing eligibility, and useful as a public statement of what the app does/doesn't do with user data. Linked from README + the Security wiki page.
…lobal cards Tab anchoring Setting HorizontalContentAlignment=Stretch / VerticalContentAlignment= Stretch on the TabControl wasn't enough — WPF-UI's TabItem style sets these explicitly, overriding the inherited TabControl values. Setting them inline on each TabItem wins via XAML attribute precedence over Style setters. The General tab's single Card no longer floats in the middle of empty space. Global card layout 'Hardware-accelerated GPU Scheduling (HAGS)' was being clipped on narrower window widths because the reboot badge sat on the same line. Moved the badge to its own line directly under the title (matching the service-card layout), with HorizontalAlignment=Left so it doesn't stretch across the card.
A bare <ui:Card> as the immediate child of a ScrollViewer ends up vertically centered (WPF-UI's Card style appears to set VerticalAlignment=Center). The other tabs already work because they have a StackPanel between the ScrollViewer and the cards — StackPanel naturally top-anchors children. Adding the same wrapper to the General tab brings its layout in line.
|
You are seeing this message because GitHub Code Scanning has recently been set up for this repository, or this pull request contains the workflow file for the Code Scanning tool. What Enabling Code Scanning Means:
For more information about GitHub Code Scanning, check out the documentation. |
| _ = sc.Status; | ||
| return true; | ||
| } | ||
| catch { return false; } |
| _ => ServiceStartType.Unknown, | ||
| }; | ||
| } | ||
| catch { return ServiceStartType.Unknown; } |
| using var sc = new ServiceController(serviceName); | ||
| return sc.Status; | ||
| } | ||
| catch { return null; } |
Comment on lines
+147
to
+160
| foreach (var row in ServiceRows) | ||
| { | ||
| if (!row.IsInstalled) continue; | ||
| if (useRecommended) | ||
| { | ||
| // Only flip rows with a RecommendedTarget. Leave others alone. | ||
| if (row.Definition.RecommendedTarget is { } target) | ||
| row.SetDesiredFromPreset(target); | ||
| } | ||
| else | ||
| { | ||
| row.SetDesiredFromPreset(ServiceTargetState.Default); | ||
| } | ||
| } |
| row.SetDesiredFromPreset(ServiceTargetState.Default); | ||
| } | ||
| } | ||
| try { _store.Save(_config); } catch { } |
| row.SetDesiredFromPreset(ServiceTargetState.Default); | ||
| } | ||
| } | ||
| try { _store.Save(_config); } catch { } |
Removes from index and adds to .gitignore. File remains on disk so Claude Code keeps reading it; new edits no longer enter git. History intentionally not rewritten — the previous content is generic developer context (architecture notes, machine paths) with nothing sensitive. Rewriting history would orphan the v0.1.0..v0.1.29 tag chain and force a re-clone for everyone, which isn't worth it for the content this file contains.
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.
Summary
This branch bundles four threads of work into one PR: the Windows services feature you asked for, a Settings UI restructure into tabs, a trust/security CI overhaul, and the new docs/wiki layout.
Features
MonitorServiceloop.Trust & security
# vX.Y.Zcomments so versions are still readable). Dependabot keeps them updated.release.ymlgains: adotnet list package --vulnerablegate before publish, SHA-256 checksums attached to every Release asSHA256SUMS.txt, and an optional VirusTotal scan step gated on theENABLE_VIRUSTOTALrepo variable.Deterministic=true+ContinuousIntegrationBuildin the csproj so CI builds at the same commit are byte-identical run-to-run.Docs
docs/wiki/markdown (8 pages: Home, Installation, Build-from-source, File-locations, Logging, Verification, Source-file-reference, Architecture-rationale, Security) as the wiki source-of-truth.tools/sync-wiki.ps1mirrorsdocs/wiki/into the GitHub Wiki repo on demand.Internal
dev-build.ymlworkflow producing installer + portable EXE as workflow artifacts on every non-mainpush. Stamped{nextStable}-dev.{sha7}so a dev install never tries to "upgrade" itself to stable mid-test.[trim ]memory-snapshot lines no longer written tochanges.log(function preserved for ad-hoc debugging).Test plan
🤖 Generated with Claude Code