Stride Versions
Managing Stride versions is the launcher's core responsibility. This file describes how versions are discovered, how install/update/uninstall flows are wired, and where to hook new behavior.
Version kinds
flowchart TD
SVM["StrideVersionViewModel<br/>(abstract)"]
SSV["StrideStoreVersionViewModel<br/>Major.Minor from NuGet feed"]
SSA["StrideStoreAlternateVersionViewModel<br/>Alternate patch version under the same Major.Minor"]
SDV["StrideDevVersionViewModel<br/>Local build or DevRedirect package"]
SVM --> SSV
SVM --> SDV
SSV --> SSA
Each entry in MainViewModel.StrideVersions corresponds to one Major.Minor pair. A StrideStoreVersionViewModel holds both the latest NugetLocalPackage installed and the latest NugetServerPackage from the feed — that's how the UI knows whether a version is installed, outdated, or download-only.
Version discovery
MainViewModel.FetchOnlineData orchestrates three phases:
- Local.
RetrieveLocalStrideVersionscallsNugetStore.GetPackagesInstalled(MainPackageIds)and filters withFilterStrideMainPackages()(PackageFilterExtensions.cs). Packages are grouped by{Major}.{Minor}. - Server.
RetrieveServerStrideVersionscallsNugetStore.FindSourcePackages(MainPackageIds, …). If the call returns nothing,IsOfflineflips on and the UI shows an error with the accumulated log. - Dev. Dev-redirect packages (detected via
NugetStore.IsDevRedirectPackage) are added asStrideDevVersionViewModelwith their real on-disk path fromNugetStore.GetRealPath. Additionally, every entry inLauncherSettings.DeveloperVersionsis added up front.
The same Major.Minor key is looked up with SortedObservableCollection.BinarySearch(Tuple.Create(major, minor)) to merge local and server state into a single view model.
NuGet store
Stride.Core.Packages.NugetStore is a thin facade over NuGet's v3 APIs. The launcher does not call NuGet directly — every operation goes through NugetStore:
| Method | Used by |
|---|---|
GetPackagesInstalled(ids) |
RetrieveLocalStrideVersions |
FindSourcePackages(ids, ct) |
RetrieveServerStrideVersions, VsixVersionViewModel.UpdateFromStore |
InstallPackage(id, version, frameworks, progress) |
PackageVersionViewModel download flow, SelfUpdater |
UninstallPackage(package, progress) |
PackageVersionViewModel delete flow, MainViewModel.RemoveUnusedPackages, Launcher.UninstallAsync |
GetUpdates(identity, …) |
SelfUpdater |
PurgeCache() |
SelfUpdater after a file swap |
Every call is serialized through MainViewModel.RunLockTask, which takes objectLock and runs on a background thread.
Progress is reported via IPackagesLogger — MainViewModel implements it and stores every log line in-memory so the crash report and the "offline" dialog can attach it.
Install / update flow
- User clicks Install or Update on a
StrideVersionViewModel. PackageVersionViewModel.Download(true)runs: it setsIsProcessing, callsNugetStore.InstallPackage, and updates progress viaOnDownloadProgress.- On completion,
UpdateStatusrecomputesCanBeDownloaded/CanDeleteand the UI re-binds. MainViewModel.RetrieveLocalStrideVersionsis re-run to refresh the version list and to clean up any newly-unused transitive packages viaRemoveUnusedPackages(walksDependenciesstarting from the Stride main packages and uninstalls anything no longer referenced).UpdateAvailableEditors()re-scanstools/andlib/for TFM subfolders containing a Game Studio executable (Stride.GameStudio.Avalonia.Desktop.exeon Windows,.dllon Linux).SelectedEditoris restored fromLauncherSettings.PreferredEditorif present, otherwise the first editor found is used, and the runtime combo is refreshed for the active version.
Uninstall flow
Two entry points:
- Per-version, from the UI:
PackageVersionViewModel.Delete(removeFromUi: true, confirmPrompt: true)prompts the user, callsNugetStore.UninstallPackage, and updates status. - Full uninstall, from
Stride.Launcher.exe /Uninstall: Launcher.cs'sUninstallAsync:- Calls
UninstallHelper.CloseProcessesInPathAsyncto kill any running Stride/Game Studio process started from the launcher directory. The user is prompted to confirm viaMessageBox. - Iterates
store.MainPackageIdsand uninstalls every matching local package. - Cleans
.lockand.oldfiles left over from previous self-updates. - Cancels the app's
CancellationTokenSourceso the main loop exits.
- Calls
UninstallHelper also subscribes to NugetStore.NugetPackageUninstalling to close lingering processes before each package is removed — this is why it lives as a disposable member on MainViewModel (uninstallHelper).
Editor discovery
StrideVersionViewModel.AvailableEditors is an ObservableList<string> populated by scanning every framework folder of the package install paths (PackageLayout.FrameworkDirectories; a dev-redirect version scans bin/<Configuration>/ of the in-tree project instead). The launcher looks for:
{InstallPath}/tools/{framework}/Stride.GameStudio.Avalonia.Desktop.{exe|dll}
{InstallPath}/lib/{framework}/Stride.GameStudio.Avalonia.Desktop.{exe|dll}
On Windows, Stride.GameStudio.exe is also considered. The first folder holding an editor wins; each editor's folder is remembered for LocateMainExecutable. Stride 4.0 shipped both a net472 and a net5.0-windows editor, which is why the legacy lib/net472/Stride.GameStudio.exe fallback still exists; since 4.1 every version ships one framework folder per editor.
Runtime choice
MainViewModel.AvailableRuntimes lists ".NET N or newer (default)" for the active version's editor's own runtimeconfig major, then ".NET M or newer" for each .NET major above it, restricted to majors with both a runtime and an SDK installed (DotNetInstall.Detect). A choice is a minimum: a project that needs a newer major still gets it, and a global.json SDK pin wins over the choice. The list is only shown when the editor takes the choice (DotNetHostSelector.SupportsHostSelection, a type-reference scan of the editor assembly), so older editors never receive --framework. An explicit choice starts the editor through dotnet exec --runtimeconfig <generated>; the default entry passes no choice, starts the apphost and lets the editor re-execute itself when the project needs a newer major.
VSIX
VsixVersionViewModel treats the VSIX as just another NuGet package but overrides the install step to invoke VSIXInstaller.exe against the detected VisualStudioVersions.AvailableInstances matching the supported range (VS2019 for major 16, VS2022AndNext for major ≥ 17). Two instances exist on MainViewModel: VsixPackage2019 and VsixPackage2022.
Adding a new version kind
- Create a subclass of
StrideVersionViewModel(orStrideStoreVersionViewModelfor "looks like a store version but from a different source"). - Override
UpdateStatusto describe when the entry is downloadable vs installed. - Populate it from
MainViewModel— either from a settings source (likeLauncherSettings.DeveloperVersions) or from a new NuGet query. - If the UI needs to distinguish it, add a DataTemplate in
MainView.axamlkeyed on the concrete type.