dotnet CLI
Microsoft - dotnet CLI should be all the information you need, but it helps me to learn new things if I take notes on them. Often I end up exploring things I might not have otherwise, and having the notes around is a good reference for me if I need to do something similar in the future.
To create a new C# project we can run the following commands from a bash terminal
mkdir dotnet-scrap
cd dotnet-scrap
dotnet new sln
The project structure is now
tree
.
└── dotnet-scrap.sln
The solution file contains the following information
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.30114.105
MinimumVisualStudioVersion = 10.0.40219.1
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
This project doesn't have any .cs
files though, so there isn't anything to build or run at this time. In the next sections I will show how to create different projects and link them together for use.
Custom Library
Then we create a library, called ScrapLibrary
dotnet new classlib -o ScrapLibrary
The template "Class Library" was created successfully.
Processing post-creation actions...
Running 'dotnet restore' on /home/kapper/Code/dotnet-scrap/ScrapLibrary/ScrapLibrary.csproj...
Determining projects to restore...
Restored /home/kapper/Code/dotnet-scrap/ScrapLibrary/ScrapLibrary.csproj (in 63 ms).
Restore succeeded.
The project structure is now
tree -L 2
.
├── dotnet-scrap.sln
└── ScrapLibrary
├── Class1.cs
├── obj
└── ScrapLibrary.csproj
2 directories, 8 files
Now we add the library to our project solution in the root directory of dotnet-scrap
dotnet sln add ScrapLibrary/ScrapLibrary.csproj
The dotnet-scrap.sln
file now contains the following information. The project file structure has not changed.
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.30114.105
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ScrapLibrary", "ScrapLibrary\ScrapLibrary.csproj", "{225F8AD6-761E-436E-9BDE-DC5D3490C38E}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{225F8AD6-761E-436E-9BDE-DC5D3490C38E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{225F8AD6-761E-436E-9BDE-DC5D3490C38E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{225F8AD6-761E-436E-9BDE-DC5D3490C38E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{225F8AD6-761E-436E-9BDE-DC5D3490C38E}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal
And for later testing, we define a public static
function that we can call to verify the library is available within later projects. This is done in the ScrapLibrary/Class1.cs
file.
namespace ScrapLibrary;
public class Class1
{
public static void Hello()
{
Console.Write("Hello!\n");
}
}
XUnit Unit Testing
Now if we want to add the xunit
testing framework to our project, we run the following command
dotnet new xunit -o ScrapLibrary.Test
The file structure of our project is now
tree -L 2
.
├── dotnet-scrap.sln
├── ScrapLibrary
│ ├── Class1.cs
│ ├── obj
│ └── ScrapLibrary.csproj
└── ScrapLibrary.Test
├── obj
├── ScrapLibrary.Test.csproj
└── UnitTest1.cs
4 directories, 5 files
But we still need to add the ScrapLibrary.test
to our dotnet-scrap.sln
, and to do so we run the following command
dotnet sln add ScrapLibrary.Test/ScrapLibrary.Test.csproj
This updates our dotnet-scrap.sln
with the following information
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.30114.105
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ScrapLibrary", "ScrapLibrary\ScrapLibrary.csproj", "{225F8AD6-761E-436E-9BDE-DC5D3490C38E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ScrapLibrary.Test", "ScrapLibrary.Test\ScrapLibrary.Test.csproj", "{85594F96-1E54-4BF6-98B8-3B2C7861B308}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{225F8AD6-761E-436E-9BDE-DC5D3490C38E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{225F8AD6-761E-436E-9BDE-DC5D3490C38E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{225F8AD6-761E-436E-9BDE-DC5D3490C38E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{225F8AD6-761E-436E-9BDE-DC5D3490C38E}.Release|Any CPU.Build.0 = Release|Any CPU
{85594F96-1E54-4BF6-98B8-3B2C7861B308}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{85594F96-1E54-4BF6-98B8-3B2C7861B308}.Debug|Any CPU.Build.0 = Debug|Any CPU
{85594F96-1E54-4BF6-98B8-3B2C7861B308}.Release|Any CPU.ActiveCfg = Release|Any CPU
{85594F96-1E54-4BF6-98B8-3B2C7861B308}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal
Initially, the ScrapProject.Test.csproj
will not contain a reference to our ScrapLibrary
project.
cat ScrapLibrary.Test.csproj
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.11.0" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="coverlet.collector" Version="3.1.0">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>
</Project>
So we need to add a reference from our ScrapLibrary.Test
project to our ScrapLibrary
project, which will allow the use of our custom library.
cd ScrapLibrary.Test
dotnet add reference ../ScrapLibrary/ScrapLibrary.csproj
This updates our ScrapLibrary.Test.csproj
to contain the following information
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.11.0" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="coverlet.collector" Version="3.1.0">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ScrapLibrary\ScrapLibrary.csproj" />
</ItemGroup>
</Project>
And within the xunit ScrapLibrary.Test/UnitTest1.cs
file we can now use the library -
using Xunit;
namespace ScrapLibrary.Test;
public class UnitTest1
{
[Fact]
public void Test1()
{
ScrapLibrary.Class1.Hello();
}
}
Console Application
And finally, as a last step for getting started using C#, we create a simple console application that will build within our solution, and have the ability to use our custom library!
dotnet new console -o ScrapConsole
The template "Console App" was created successfully.
Processing post-creation actions...
Running 'dotnet restore' on /home/kapper/Code/dotnet-scrap/ScrapConsole/ScrapConsole.csproj...
Determining projects to restore...
Restored /home/kapper/Code/dotnet-scrap/ScrapConsole/ScrapConsole.csproj (in 73 ms).
Restore succeeded.
Our project structure is now
tree -L 2
.
├── dotnet-scrap.sln
├── ScrapConsole
│ ├── obj
│ ├── Program.cs
│ └── ScrapConsole.csproj
├── ScrapLibrary
│ ├── Class1.cs
│ ├── obj
│ └── ScrapLibrary.csproj
└── ScrapLibrary.Test
├── obj
├── ScrapLibrary.Test.csproj
└── UnitTest1.cs
6 directories, 7 files
And we again add this ScrapConsole
to our dotnet-scrap.sln
just as we did previously for the library and xunit test projects.
dotnet sln add ScrapConsole/ScrapConsole.csproj
Project `ScrapConsole/ScrapConsole.csproj` added to the solution.
Which updates our dotnet-scrap.sln
to contain the following information
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.30114.105
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ScrapLibrary", "ScrapLibrary\ScrapLibrary.csproj", "{225F8AD6-761E-436E-9BDE-DC5D3490C38E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ScrapLibrary.Test", "ScrapLibrary.Test\ScrapLibrary.Test.csproj", "{85594F96-1E54-4BF6-98B8-3B2C7861B308}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ScrapConsole", "ScrapConsole\ScrapConsole.csproj", "{21EAD6BF-28D7-40E9-BD11-FA8393FCBCF7}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{225F8AD6-761E-436E-9BDE-DC5D3490C38E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{225F8AD6-761E-436E-9BDE-DC5D3490C38E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{225F8AD6-761E-436E-9BDE-DC5D3490C38E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{225F8AD6-761E-436E-9BDE-DC5D3490C38E}.Release|Any CPU.Build.0 = Release|Any CPU
{85594F96-1E54-4BF6-98B8-3B2C7861B308}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{85594F96-1E54-4BF6-98B8-3B2C7861B308}.Debug|Any CPU.Build.0 = Debug|Any CPU
{85594F96-1E54-4BF6-98B8-3B2C7861B308}.Release|Any CPU.ActiveCfg = Release|Any CPU
{85594F96-1E54-4BF6-98B8-3B2C7861B308}.Release|Any CPU.Build.0 = Release|Any CPU
{21EAD6BF-28D7-40E9-BD11-FA8393FCBCF7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{21EAD6BF-28D7-40E9-BD11-FA8393FCBCF7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{21EAD6BF-28D7-40E9-BD11-FA8393FCBCF7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{21EAD6BF-28D7-40E9-BD11-FA8393FCBCF7}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal
Initially, the contents of ScrapConsole/ScrapConsole.csproj
will not contain a reference to our ScrapLibrary
cat ScrapConsole.csproj
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>
So we add a reference from our ScrapConsole
project to allow use of our custom ScrapLibrary
cd ScrapConsole
dotnet add reference ../ScrapLibrary/ScrapLibrary.csproj
And now the ScrapConsole.csproj
contains the following information
cat ScrapConsole.csproj
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<ProjectReference Include="..\ScrapLibrary\ScrapLibrary.csproj" />
</ItemGroup>
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>
And now within the ScrapConsole/Program.cs
file, we can use our library
// See https://aka.ms/new-console-template for more information
using ScrapLibrary;
Console.WriteLine("Hello, World!");
ScrapLibrary.Class1.Hello();
Summary
I think you get the general idea here :) In summary, here are all of the commands we ran to create this project -
mkdir dotnet-scrap
cd dotnet-scrap
dotnet new sln
dotnet new classlib -o ScrapLibrary
dotnet sln add ScrapLibrary/ScrapLibrary.csproj
dotnet new xunit -o ScrapLibrary.Test
dotnet sln add ScrapLibrary.Test/ScrapLibrary.Test.csproj
cd ScrapLibrary.Test/
dotnet add reference ../ScrapLibrary/ScrapLibrary.csproj
cd ..
dotnet new console -o ScrapConsole
dotnet sln add ScrapConsole/ScrapConsole.csproj
cd ScrapConsole/
dotnet add reference ../ScrapLibrary/ScrapLibrary.csproj
cd ..
These commands produce the following project structure
tree -L 2
.
├── dotnet-scrap.sln
├── ScrapConsole
│ ├── bin
│ ├── obj
│ ├── Program.cs
│ └── ScrapConsole.csproj
├── ScrapLibrary
│ ├── bin
│ ├── Class1.cs
│ ├── obj
│ └── ScrapLibrary.csproj
└── ScrapLibrary.Test
├── bin
├── obj
├── ScrapLibrary.Test.csproj
└── UnitTest1.cs
9 directories, 7 files
Help / Documentation
The dotnet command contains very nice output for help and documentation. It is worth taking a few minutes to explore these options, as they will help you navigate the CLI effectively.
If you want basic help for a command to be output to your console
dotnet add --help
Description:
.NET Add Command
Usage:
dotnet [options] add [<PROJECT>] [command]
Arguments:
<PROJECT> The project file to operate on. If a file is not specified, the command will search the
current directory for one. [default: /home/kapper/Code/dotnet-scrap/]
Options:
-?, -h, --help Show command line help.
Commands:
package <PACKAGE_NAME> Add a NuGet package reference to the project.
reference <PROJECT_PATH> Add a project-to-project reference to the project.
If you have internet connection, the following command will open your default web browser and navigate to the documentation for the dotnet add
command. The online documentation is much more verbose and contains several examples. We don't need to bookmark it or search it up each time though, because this command will take us right to the relevant page!
dotnet help add
There are many other help options worth exploring that the CLI provides. For example, the dotnet new --list
command will output all available project templates that you can use
dotnet new --list
These templates matched your input:
Template Name Short Name Language Tags
-------------------------------------------- -------------- ---------- --------------------------
ASP.NET Core Empty web [C#],F# Web/Empty
ASP.NET Core gRPC Service grpc [C#] Web/gRPC
ASP.NET Core Web API webapi [C#],F# Web/WebAPI
ASP.NET Core Web App webapp,razor [C#] Web/MVC/Razor Pages
ASP.NET Core Web App (Model-View-Controller) mvc [C#],F# Web/MVC
ASP.NET Core with Angular angular [C#] Web/MVC/SPA
ASP.NET Core with React.js react [C#] Web/MVC/SPA
ASP.NET Core with React.js and Redux reactredux [C#] Web/MVC/SPA
Blazor Server App blazorserver [C#] Web/Blazor
Blazor WebAssembly App blazorwasm [C#] Web/Blazor/WebAssembly/PWA
Class Library classlib [C#],F#,VB Common/Library
Console App console [C#],F#,VB Common/Console
dotnet gitignore file gitignore Config
Dotnet local tool manifest file tool-manifest Config
EditorConfig file editorconfig Config
global.json file globaljson Config
MSTest Test Project mstest [C#],F#,VB Test/MSTest
MVC ViewImports viewimports [C#] Web/ASP.NET
MVC ViewStart viewstart [C#] Web/ASP.NET
NuGet Config nugetconfig Config
NUnit 3 Test Item nunit-test [C#],F#,VB Test/NUnit
NUnit 3 Test Project nunit [C#],F#,VB Test/NUnit
Protocol Buffer File proto Web/gRPC
Razor Class Library razorclasslib [C#] Web/Razor/Library
Razor Component razorcomponent [C#] Web/ASP.NET
Razor Page page [C#] Web/ASP.NET
Solution File sln Solution
Web Config webconfig Config
Worker Service worker [C#],F# Common/Worker/Web
xUnit Test Project xunit [C#],F#,VB Test/xUnit
This works for all commands available for the dotnet CLI. Without specifying a command, we will get the following output to our console.
dotnet help
.NET SDK (6.0.202)
Usage: dotnet [runtime-options] [path-to-application] [arguments]
Execute a .NET application.
runtime-options:
--additionalprobingpath <path> Path containing probing policy and assemblies to probe for.
--additional-deps <path> Path to additional deps.json file.
--depsfile Path to <application>.deps.json file.
--fx-version <version> Version of the installed Shared Framework to use to run the application.
--roll-forward <setting> Roll forward to framework version (LatestPatch, Minor, LatestMinor, Major, LatestMajor, Disable).
--runtimeconfig Path to <application>.runtimeconfig.json file.
path-to-application:
The path to an application .dll file to execute.
Usage: dotnet [sdk-options] [command] [command-options] [arguments]
Execute a .NET SDK command.
sdk-options:
-d|--diagnostics Enable diagnostic output.
-h|--help Show command line help.
--info Display .NET information.
--list-runtimes Display the installed runtimes.
--list-sdks Display the installed SDKs.
--version Display .NET SDK version in use.
SDK commands:
add Add a package or reference to a .NET project.
build Build a .NET project.
build-server Interact with servers started by a build.
clean Clean build outputs of a .NET project.
format Apply style preferences to a project or solution.
help Show command line help.
list List project references of a .NET project.
msbuild Run Microsoft Build Engine (MSBuild) commands.
new Create a new .NET project or file.
nuget Provides additional NuGet commands.
pack Create a NuGet package.
publish Publish a .NET project for deployment.
remove Remove a package or reference from a .NET project.
restore Restore dependencies specified in a .NET project.
run Build and run a .NET project output.
sdk Manage .NET SDK installation.
sln Modify Visual Studio solution files.
store Store the specified assemblies in the runtime package store.
test Run unit tests using the test runner specified in a .NET project.
tool Install or manage tools that extend the .NET experience.
vstest Run Microsoft Test Engine (VSTest) commands.
workload Manage optional workloads.
Additional commands from bundled tools:
dev-certs Create and manage development certificates.
fsi Start F# Interactive / execute F# scripts.
sql-cache SQL Server cache command-line tools.
user-secrets Manage development user secrets.
watch Start a file watcher that runs a command when files change.
Run 'dotnet [command] --help' for more information on a command