← All posts

Install .NET SDK on Windows and run your first program

The installer asks you nothing and takes a few minutes. The time goes into checking that the version answering your terminal is the one you think it is.

Artur Kot 8 min read

Two commands need to work at the end. dotnet --info should answer with a version number, and dotnet run should print a line of text to the console. To install .NET SDK you download one file and click through it. The interesting part starts after that.

Step 0: check whether you already have it

Open PowerShell and type this before downloading anything:

dotnet --list-sdks

A line with a number and a path means the SDK is already there:

10.0.400 [C:\Program Files\dotnet\sdk]

If it’s there, stop. Skip ahead to the first program. Visual Studio, Rider and a handful of other tools pull an SDK in as part of their own setup, so that line shows up more often than anyone’s memory of what they installed last year would suggest. Empty output, or a complaint about an unrecognised command, means you carry on.

The check is worth the ten seconds because a second install alongside the first one doesn’t fail. It succeeds, leaves you with two copies, one of which happens to come first in PATH, and a week of wondering why your editor disagrees with your terminal.

Run the installer, then read what it gives you

The Windows x64 installer comes from the .NET download page. It’s around 200 MB and asks nothing beyond permission to install. There’s no component picker and no install location to choose. Nothing to get wrong. You install .NET SDK once per machine and then mostly stop thinking about it.

Close your terminal afterwards and open a new one. Then:

dotnet --info

The reply is long, and that’s the point of it. It carries everything you’d otherwise have to ask for one question at a time, and it’s the first thing anyone willing to help will want pasted into the thread.

Three different version numbers, none of them wrong

That single reply reports several versions, and they aren’t one number written out in a few places:

.NET SDK:
 Version:           10.0.400
 Commit:            14fbf8d527
 MSBuild version:   18.9.6+14fbf8d52

Runtime Environment:
 RID:         win-x64
 Base Path:   C:\Program Files\dotnet\sdk\10.0.400\

Host:
  Version:      10.0.11
  Architecture: x64

The number under SDK and the one under Host differ, and they’re supposed to. The first describes the tools you compile with. The second describes the runtime that executes whatever those tools produced. The SDK moves faster, because changes to the compiler and the project templates don’t require touching the thing that runs compiled code.

A separate command shows how many runtimes are sitting side by side:

dotnet --list-runtimes

On this machine it prints these two among others:

Microsoft.NETCore.App 9.0.19 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 10.0.11 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]

Two entries from the same family, one from .NET 9 and one from .NET 10. The older one is left over from a previous SDK, and it earns its place, because a program built against .NET 9 still looks for it at startup. You come back to this list when a program runs for you and not for someone else. Deleting old runtimes speeds up nothing. They cost disk space and nothing else.

Further down, dotnet --info prints this on some machines:

Other architectures found:
  x86   [C:\Program Files (x86)\dotnet]

That’s a second install in a different architecture, usually left behind by some other installer. It’s harmless on its own. What matters is that where dotnet points at the folder without (x86) in its name. If it points at the (x86) one, your PATH order is backwards and this is the moment to fix it.

Your first program takes two commands

One command scaffolds a console project:

dotnet new console -o hello
cd hello
dotnet run

The first prints what it did:

The template "Console App" was created successfully.

Processing post-creation actions...
Restoring C:\...\hello\hello.csproj:
  Determining projects to restore...
  Restored C:\...\hello\hello.csproj (in 118 ms).
Restore succeeded.

Those last lines mean the package restore already happened. A separate dotnet restore isn’t needed, though plenty of tutorials tell you to run one immediately after creating a project.

Two files appear. hello.csproj describes the project and Program.cs holds the code, which starts life as a single line:

Console.WriteLine("Hello, World!");

There’s no class, no Main method and no declaration wrapped around it. The compiler supplies those at build time and the file stays at one statement. Older tutorials show a dozen lines here, which isn’t an error on their part, just the previous template convention.

The obj folder that turns up beside them comes from the restore and isn’t part of your code. Inside hello.csproj, one line matters:

<TargetFramework>net10.0</TargetFramework>

It decides which version of the platform your program gets built against, and it’s what you edit when moving a project to a different one. That number doesn’t have to match your SDK version. It has to match one of the runtimes from dotnet --list-runtimes.

The first dotnet run on a clean machine took 6.5 seconds here. The second, with no code changes, took 2.5. The gap is compilation, which runs in full the first time and then drops out until you touch a file again. So the first run can look frozen. It isn’t.

The very first dotnet command on a fresh system adds one more thing. It prints a greeting, a note about telemetry collection, and a line about a certificate:

Installed an ASP.NET Core HTTPS development certificate.
To trust the certificate, run 'dotnet dev-certs https --trust'

That certificate matters later, the first time you open an https address from a web project. You’ll see this once.

The two failures you’ll actually hit

The common one arrives after a perfectly good install:

'dotnet' is not recognized as an internal or external command,
operable program or batch file.

PowerShell words the same absence differently:

The term 'dotnet' is not recognized as the name of a cmdlet, function, script
file, or operable program.

This comes from the shell rather than from .NET, so it arrives in your Windows display language. The cause is nearly always the same one. The installer appended C:\Program Files\dotnet\ to PATH, but a terminal you opened earlier read the old copy of that variable at startup and nothing will make it read again. Close the window, open a new one, and confirm with where dotnet. The right answer is C:\Program Files\dotnet\dotnet.exe. Rebooting gets recommended a lot in forum answers and is almost never what fixes this.

The second failure is more interesting, because it only shows up in one directory. The same command works a level above and stops working once you step into the project:

  * You intended to execute a .NET SDK command:
      A compatible .NET SDK was not found.

Requested SDK version: 9.0.100
global.json file: C:\...\global.json

Installed SDKs:
10.0.400 [C:\Program Files\dotnet\sdk]

Install the [9.0.100] .NET SDK or update global.json to match an installed SDK.

A global.json file is pinning the project to one SDK version. Course repositories and company templates carry them often, and since the file sits in the project root and runs to a few lines, it’s easy to miss when you clone someone else’s code. You can install the version it asks for, or raise the number in the file to whatever dotnet --list-sdks reports. SDK versions coexist without conflict, so installing another one breaks nothing that already works.

Installing the SDK is done when dotnet --info and dotnet run both answer with what you expect. The next message you see will come from the compiler, and the most common of those is CS0029 on an assignment.

DevJourney runs these same commands inside the app, against real dotnet, with nothing to configure separately.

Topics: dotnetnarzedziapodstawy

The download has started

DevJourney_1.0.0_x64-setup.exe · 1.0.0

If Windows warns you

"Windows protected your PC" is not a virus detection. SmartScreen trusts the certificate an installer is signed with, and this one is still earning its reputation through a download count.

In the warning: More info → Run anyway.

Confirm it yourself

Check this download on VirusTotal

Or in PowerShell, where you downloaded it:

Get-FileHash .\DevJourney_1.0.0_x64-setup.exe

Should print:

7cd001be4463317f601b8bb2eed78537982a3559c92f06e96288434c79931fd6