Installation

Build Toolchain

The project uses the .NET 10 SDK with the Microsoft.NET.Sdk.Worker project type. Deterministic builds with locked NuGet restore (packages.lock.json).

Build & Publish

# Restore (locked mode — requires packages.lock.json)
dotnet restore -p:RestoreLockedMode=true

# Run tests
dotnet test -c Release

# Publish optimized self-contained single-file executable
dotnet publish src/JenkinsAsService `
    --nologo --configuration Release `
    -p:RestoreLockedMode=true `
    --runtime win-x64 --self-contained true `
    --output publish/x64/ `
    -p:PublishSingleFile=true `
    -p:IncludeNativeLibrariesForSelfExtract=true `
    -p:EnableCompressionInSingleFile=true `
    -p:PublishReadyToRun=true `
    -p:OptimizationPreference=Speed `
    -p:UseSharedCompilation=true `
    -p:DebuggerSupport=false `
    -p:MetadataUpdaterSupport=false `
    -p:Deterministic=true `
    -p:DebugType=Embedded `
    -p:DebugSymbols=true `
    -p:InformationalVersion="1.0.0" `
    /v:q /clp:ErrorsOnly

# Build MSI installer (requires WiX v5 SDK — auto-restored via NuGet)
dotnet build src/JenkinsAsService.Installer -c Release -p:PublishDir=../../publish/x64/ -p:Version=1.0.0

Publish Flags

Flag Purpose
PublishSingleFile Single .exe output
IncludeNativeLibrariesForSelfExtract Bundles native libs inside the single file
EnableCompressionInSingleFile Compresses the bundle
PublishReadyToRun AOT pre-compilation (R2R) for faster startup
OptimizationPreference=Speed Optimize for speed over size
DebuggerSupport=false Strip debugger attach points (production service)
MetadataUpdaterSupport=false Strip hot-reload metadata
Deterministic=true Same source → identical binary
DebugType=Embedded PDB symbols embedded in .exe (stack traces with file/line info, no separate .pdb)
InformationalVersion Set from git tag in CI

The published output:

NuGet Dependencies

Main Project

Package Version Purpose
Microsoft.Extensions.Hosting.WindowsServices 10.0.9 Windows Service integration
Microsoft.Extensions.Http 10.0.9 IHttpClientFactory for jar download
Microsoft.Extensions.Http.Resilience 10.7.0 Polly retry, circuit breaker, timeout
Serilog.Extensions.Hosting 9.0.0 Serilog integration with .NET hosting
Serilog.Sinks.File 7.0.0 Rolling file log sink
Serilog.Sinks.EventLog 4.0.0 Windows Event Log sink
Serilog.Enrichers.Environment 3.0.1 MachineName and EnvironmentName enrichment
Serilog.Enrichers.Process 3.0.0 ProcessId enrichment
Serilog.Formatting.Compact 3.0.0 CLEF JSON formatter
AdysTech.CredentialManager 3.1.0 Windows Credential Manager access
System.Security.Cryptography.ProtectedData 10.0.9 DPAPI encryption
OpenTelemetry.Extensions.Hosting 1.16.0 OTel hosting integration
OpenTelemetry.Exporter.OpenTelemetryProtocol 1.16.0 OTLP exporter
OpenTelemetry.Instrumentation.Runtime 1.15.1 .NET runtime metrics

Test Project

Package Version Purpose
xunit 2.9.3 Test framework
xunit.runner.visualstudio 3.1.4 VS Test adapter
NSubstitute 5.3.0 Mocking library
FluentAssertions 8.10.0 Fluent assertion syntax
Microsoft.NET.Test.Sdk 18.6.0 Test platform SDK
coverlet.collector 10.0.1 Code coverage collection
Note

All versions are pinned (no floating ranges). Both projects include packages.lock.json for deterministic restores via RestoreLockedMode=true.

MSI Installer

The project includes a WiX v5 MSI installer (src/JenkinsAsService.Installer/) that:

MSI Dialog Flow

LicenseAgreementDlgInstallDirDlgJenkinsConfigDlgSecurityOptionsDlgVerifyReadyDlg

MSI Structure

File Purpose
JenkinsAsService.Installer.wixproj WiX v5 project — references WixToolset.UI.wixext and WixToolset.Util.wixext
Package.wxs Package metadata, UI (WixUI_InstallDir), icon, features
Folders.wxs Install directory definition (ProgramFiles6432Folder\Jenkins)
Service.wxs File components + ServiceInstall / ServiceControl + util:ServiceConfig (recovery)
ConfigDialog.wxs Custom dialogs: JenkinsConfigDlg (URL/secret/name/Java) + SecurityOptionsDlg (secret mode radio group)
License.rtf BSD 3-Clause license in RTF format for the WixUI dialog

The installer project is excluded from the solution build (Build=false). Build it explicitly after publishing.

Installation

  1. Download the .msi for your architecture from Releases
  2. Run the installer — it walks through install path, Jenkins URL, agent secret, and secret protection mode
  3. Done — the service registers and starts automatically

Silent Install

For automated deployments, use msiexec with public properties:

msiexec /i JenkinsAsService_1.0.4_x64.msi /qn `
    INSTALLFOLDER="D:\Jenkins" `
    JENKINS_URL="https://jenkins.example.com:8443" `
    JENKINS_SECRET="your-secret" `
    JENKINS_SECRET_MODE="EnvironmentVariable" `
    JENKINS_AGENT_NAME="" `
    JENKINS_JAVA_PATH=""
Property Required Default Description
INSTALLFOLDER No C:\Program Files\Jenkins Installation directory
JENKINS_URL Yes Jenkins controller URL with explicit port
JENKINS_SECRET Yes JNLP agent secret
JENKINS_SECRET_MODE No EnvironmentVariable EnvironmentVariable, Dpapi, CredentialManager, or Unprotected
JENKINS_AGENT_NAME No Hostname Agent node name in Jenkins
JENKINS_JAVA_PATH No JAVA_HOME Path to JDK bin folder

Portable (Archive)

For environments where MSI installation isn't possible, download the .7z or .rar archive from Releases:

  1. Extract to a folder of your choice (e.g. D:\Jenkins)
  2. Edit appsettings.json — fill in JenkinsURL, AgentSecret, and any other settings
  3. Register and start the service:
sc.exe create Jenkins binPath= "D:\Jenkins\JenkinsAsService.exe" start= auto obj= LocalSystem
sc.exe failure Jenkins reset= 86400 actions= restart/10000/restart/10000/restart/10000
sc.exe start Jenkins

To configure secret protection, run the CLI before starting:

.\JenkinsAsService.exe update-secret --secret "your-secret" --url "https://jenkins:8443" --mode Dpapi --silent

To uninstall:

sc.exe stop Jenkins
sc.exe delete Jenkins

Automated Release

The GitHub Actions release workflow (.github/workflows/release.yml):

  1. Push a tag matching v* (e.g., v1.0.4)
  2. Runs tests, publishes optimized self-contained executables for x64 and x86
  3. Builds MSI installers for both architectures via WiX v5
  4. Creates .7z (LZMA2, max compression) and .rar (RAR5 with 5% recovery record) archives
  5. Generates checksums.json with SHA256 hashes for all artifacts
  6. Creates GitHub Release with auto-generated release notes

Release Artifacts

For a tag v1.0.4:

File Description
JenkinsAsService_1.0.4_x64.msi 64-bit MSI installer
JenkinsAsService_1.0.4_x86.msi 32-bit MSI installer
JenkinsAsService_1.0.4_x64.7z 64-bit archive (7z)
JenkinsAsService_1.0.4_x64.rar 64-bit archive (RAR5 + recovery)
JenkinsAsService_1.0.4_x86.7z 32-bit archive (7z)
JenkinsAsService_1.0.4_x86.rar 32-bit archive (RAR5 + recovery)
JenkinsAsService_1.0.4_checksums.json SHA256 hashes

Service Recovery (Windows-Level)

The MSI installer configures Windows service recovery automatically via util:ServiceConfig:

Note

The built-in watchdog handles Java process crashes. Windows-level recovery covers full service host crashes (the .NET process itself dying) — rare but covered automatically.