Skip to content

Installation

Rod Christiansen edited this page Sep 3, 2026 · 1 revision

Installation

Supported platforms

Item Value
Operating system Windows 10 / Windows 11 (supportedOS GUID {8e0f7a12-…} in both app manifests)
Architectures x64 and ARM64 (win-x64, win-arm64 runtime identifiers)
.NET runtime None required at run time — both executables are published self-contained, single-file, ReadyToRun
Privileges Installation and service registration require elevation; the service runs as LocalSystem

Nothing in the repo declares a minimum Windows build beyond the Windows 10/11 compatibility GUID. The service reads the Security event log, which is only readable by LocalSystem and administrators — see Windows Session Model.

What gets installed

File Role
C:\Program Files\StartSet\managedstatekeeper.exe CLI and execution engine
C:\Program Files\StartSet\StartSetService.exe Windows service host (StartSet)

The install directory is added to the machine PATH by the packaged install scripts and by the MSI's Environment element, so managedstatekeeper is callable by name in new shells.

C:\ProgramData\ManagedState and all payload directories are created by the installer scripts, by the MSI's CreateFolder components, and again by the service and CLI at run time (ExecutionEngine.EnsureDirectories). A missing directory is not an error.

Install methods

GitHub release zip

Every tagged release publishes startset-x64.zip and startset-arm64.zip containing the two executables, unsigned. This is the only artifact the public release workflow uploads.

Extract to the install directory:

Expand-Archive .\startset-x64.zip -DestinationPath 'C:\Program Files\StartSet' -Force

Register and start the service:

sc.exe create StartSet binPath="C:\Program Files\StartSet\StartSetService.exe" start=auto
sc.exe description StartSet "StartSet - Script automation at boot, login, and on-demand"
sc.exe start StartSet

Register the event log source so warnings and errors land in the Application log under a recognised source:

New-EventLog -LogName Application -Source StartSet

MSI

build\msi\Package.wxs is a WiX v6 package definition (WixToolset.Sdk/6.0.0). It installs per-machine into ProgramFiles64Folder\StartSet, creates every payload directory, adds the install directory to the system PATH, installs the StartSet service as LocalSystem with Start="auto", and starts it on install / stops and removes it on uninstall. MajorUpgrade is configured with Schedule="afterInstallValidate", so upgrades replace in place.

The upgrade code is stable across versions:

7E4F8A2D-3B5C-4D6E-9F1A-2C8D4E5F6A7B

Install silently:

msiexec.exe /i StartSet-<version>-x64.msi /qn /l*v "$env:TEMP\startset_install.log"

Note that build.ps1's MSI path does not invoke the .wixproj — it stages a payload/scripts/ build-info.yaml tree and hands it to cimipkg.exe. See Development.

NuGet package

build\nupkg\StartSet.nuspec.template produces StartSet-x64 / StartSet-arm64 packages carrying the executables under tools\. These are consumed by package managers that install from a NuGet feed; the nuspec itself performs no service registration, so pair it with the post-install steps above.

Managed package (.pkg / .intunewin)

build.ps1 can also emit a cimipkg .pkg (payload + preinstall.ps1 / postinstall.ps1 + build-info.yaml) and, when IntuneWinAppUtil.exe is on PATH, a .intunewin wrapper for Intune deployment. The packaged postinstall.ps1 is what creates the directories, sets PATH, deletes any existing StartSet service, recreates it as automatic-start, and starts it; preinstall.ps1 stops a running service first.

Build from source

See Development.

Signing

GitHub Actions builds and publishes unsigned binaries (build.ps1 -NoSign -Binaries). Sign them with your organisation's certificate before distributing to a fleet.

$cert = "Your Certificate Name"
$timestampUrl = "http://timestamp.digicert.com"
Get-ChildItem -Recurse -Include *.exe,*.dll | ForEach-Object {
    signtool sign /fd SHA256 /tr $timestampUrl /td SHA256 /n $cert $_.FullName
}

Sign MSIs separately, after the binaries inside them have been signed and the package rebuilt:

Get-ChildItem -Filter "StartSet-*.msi" | ForEach-Object {
    signtool sign /fd SHA256 /tr $timestampUrl /td SHA256 /n $cert $_.FullName
}

build.ps1 will also sign during the build when a certificate is available — see Development for -Sign, -Thumbprint, -SignMSI and the STARTSET_CERT_CN / STARTSET_CERT_SUBJECT environment variables.

Verification

Check the version. The CLI prints Major.MM.DD.HHMM, derived from the assembly version that build.ps1 stamps as yyyy.MM.dd.HHmm:

managedstatekeeper --version

Confirm the service is registered as LocalSystem and running:

Get-CimInstance Win32_Service -Filter "Name='StartSet'" | Select-Object State, StartMode, StartName

Confirm the payload tree exists:

Get-ChildItem C:\ProgramData\ManagedState

Exercise the engine end to end without a reboot or logon:

managedstatekeeper process boot-every

A session directory should appear under C:\ProgramData\ManagedState\logs\<today>\<HHmm>\.

Uninstall

MSI-installed:

msiexec.exe /x StartSet-<version>-x64.msi /qn

Manually installed:

sc.exe stop StartSet
sc.exe delete StartSet
Remove-Item 'C:\Program Files\StartSet' -Recurse -Force

Neither route removes C:\ProgramData\ManagedState. Payloads, Config.yaml, the run-once ledgers, logs and reports survive uninstall — deliberately, so a reinstall does not re-run every *-once payload. Remove it explicitly if you want a clean slate:

Remove-Item 'C:\ProgramData\ManagedState' -Recurse -Force

Clone this wiki locally