dotnet CLI on Windows: build, test, publish in CI
The dotnet CLI builds, tests, and publishes .NET projects; on Windows you often add a runtime identifier like win-x64 and choose self-contained vs framework-dependent output.
dotnet works the same on every OS, but Windows CI has its own concerns: RIDs (win-x64/win-arm64), WPF/WinForms target frameworks that only build on Windows, and SDK pinning via global.json.
What it does
dotnet drives the .NET SDK: build compiles, test runs the test runner, publish produces deployable output. -r win-x64 targets a Windows runtime; --self-contained bundles the runtime so the target host needs no .NET installed.
Common usage
dotnet restore
dotnet build -c Release --no-restore
dotnet test -c Release --no-build --logger "trx;LogFileName=test.trx"
# self-contained single-file Windows publish
dotnet publish -c Release -r win-x64 --self-contained true \
-p:PublishSingleFile=true -o ./outOptions
| Flag | What it does |
|---|---|
| -c, --configuration | Build configuration (Debug/Release) |
| -r, --runtime <RID> | Target runtime, e.g. win-x64, win-arm64 |
| --self-contained <bool> | Bundle the runtime in the output |
| --no-restore / --no-build | Skip steps already done (faster pipelines) |
| -p:Property=Value | Pass an MSBuild property, e.g. PublishSingleFile |
| --logger trx | Emit a TRX test result file for CI to publish |
In CI
Pin the SDK with a global.json so a runner image upgrade cannot change your compiler. WPF and WinForms targets (net8.0-windows) only build on Windows runners, so keep those jobs off Linux agents. Use --no-restore/--no-build to avoid repeating work across build and test steps.
Common errors in CI
"A compatible .NET SDK was not found" with "global.json" means the pinned SDK version is not installed on the runner; install it or relax rollForward. "NETSDK1100: To build a project targeting Windows on this operating system, set the EnableWindowsTargeting property" means a Windows-only TFM is being built on Linux. "RID is not supported" or "win-x64 not found" means a typo in -r or a missing runtime pack; add --self-contained or the matching pack.