Jack the intern was thrilled. He sat at his computer in front of a cmd prompt ready to learn.
“It’s your first day, and we need you to work out all this new dotnet command line stuff”. Jack recalled the words of his new Boss, Joe. “We are far too busy to figure this out, we have code to ship, but this should keep you busy for a few months while we ship the Widgets 2.0 interface.” She looked very serious whenever she talked about the Widgets thing. It must be a big deal. Jack hadn’t really understood the whole widgets thing at induction but was happy to have a job.
Luckily for Jack, he had just spent the last few months at Uni learning java and python on Linux and was a pro at the command line stuff. His personal machine ran Windows too so he felt pretty comfortable now staring at the cold black shell covering most of his windows desktop.
Joe had at least told him where to install dotnet from (www.microsoft.com/net/core) and it practically installed itself. It was no apt-get install
, but hey, it’s for Windows people. He had also been told to start with the command ‘dotnet’ so he was all set.
Jack started typing and looked at the results. First, he typed dotnet
to see what it would tell him.
C:\Users\jackr>dotnet
Usage: dotnet [options]
Usage: dotnet [path-to-application]
Options:
-h|--help Display help.
--version Display version.
path-to-application:
The path to an application .dll file to execute.
“It looks like ‘dotnet –help’ is the right next instruction to find out more”, he thought to himself, “so…”:
C:\Users\jackr>dotnet --help
.NET Command Line Tools (2.0.0)
Usage: dotnet [runtime-options] [path-to-application]
Usage: dotnet [sdk-options] [command] [arguments] [command-options]
path-to-application:
The path to an application .dll file to execute.
SDK commands:
new Initialize .NET projects.
restore Restore dependencies specified in the .NET project.
run Compiles and immediately executes a .NET project.
build Builds a .NET project.
publish Publishes a .NET project for deployment (including the runtime).
test Runs unit tests using the test runner specified in the project.
pack Creates a NuGet package.
migrate Migrates a project.json based project to a msbuild based project.
clean Clean build output(s).
sln Modify solution (SLN) files.
add Add reference to the project.
remove Remove reference from the project.
list List reference in the project.
nuget Provides additional NuGet commands.
msbuild Runs Microsoft Build Engine (MSBuild).
vstest Runs Microsoft Test Execution Command Line Tool.
Common options:
-v|--verbosity Set the verbosity level of the command. Allowed values are q[uiet], m[inimal], n[ormal], d[etailed], and diag[nostic].
-h|--help Show help.
Run 'dotnet COMMAND --help' for more information on a command.
sdk-options:
--version Display .NET Core SDK version.
--info Display .NET Core information.
-d|--diagnostics Enable diagnostic output.
runtime-options:
--additionalprobingpath <path> Path containing probing policy and assemblies to probe for.
--fx-version <version> Version of the installed Shared Framework to use to run the application.
--roll-forward-on-no-candidate-fx Roll forward on no candidate shared framework is enabled.
--additional-deps <path> Path to additonal deps.json file.
“Well, that is a lot of information, where to start?” The first instruction new
seemed to jump out as a reasonable place to start. but first, somewhere to put the files:
C:\Users\jackr>mkdir internTest
C:\Users\jackr>cd internTest
C:\Users\jackr\internTest>dotnet new
Usage: new [options]
Options:
-h, --help Displays help for this command.
-l, --list Lists templates containing the specified name. If no name is specified, lists all templates.
-n, --name The name for the output being created. If no name is specified, the name of the current directory is used.
-o, --output Location to place the generated output.
-i, --install Installs a source or a template pack.
-u, --uninstall Uninstalls a source or a template pack.
--type Filters templates based on available types. Predefined values are "project", "item" or "other".
--force Forces content to be generated even if it would change existing files.
-lang, --language Specifies the language of the template to create.
Templates Short Name Language Tags
--------------------------------------------------------------------------------------------------------
Console Application console [C#], F#, VB Common/Console
Class library classlib [C#], F#, VB Common/Library
Unit Test Project mstest [C#], F#, VB Test/MSTest
xUnit Test Project xunit [C#], F#, VB Test/xUnit
ASP.NET Core Empty web [C#], F# Web/Empty
ASP.NET Core Web App (Model-View-Controller) mvc [C#], F# Web/MVC
ASP.NET Core Web App razor [C#] Web/MVC/Razor Pages
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
ASP.NET Core Web API webapi [C#], F# Web/WebAPI
global.json file globaljson Config
Nuget Config nugetconfig Config
Web Config webconfig Config
Solution File sln Solution
Razor Page page Web/ASP.NET
MVC ViewImports viewimports Web/ASP.NET
MVC ViewStart viewstart Web/ASP.NET
Examples:
dotnet new mvc --auth Individual
dotnet new xunit
dotnet new --help
“Right, I have to tell it what template to use at least, and I can pick C#, F# or even VB. (what is VB?)” Jack had played around a bit with visual studio, so he knew that there were projects and solutions, and websites, console applications and tests. Figuring a website might be too complicated, he decided to give the Console Application option a go:
C:\Users\jackr\internTest>dotnet new console
The template "Console Application" was created successfully.
Processing post-creation actions...
Running 'dotnet restore' on C:\Users\jackr\internTest\internTest.csproj...
Restoring packages for C:\Users\jackr\internTest\internTest.csproj...
Generating MSBuild file C:\Users\jackr\internTest\obj\internTest.csproj.nuget.g.props.
Generating MSBuild file C:\Users\jackr\internTest\obj\internTest.csproj.nuget.g.targets.
Restore completed in 261.64 ms for C:\Users\jackr\internTest\internTest.csproj.
Restore succeeded.
“What’s it done, I wonder?”
C:\Users\jackr\internTest>tree /F /A
Folder PATH listing for volume Windows
Volume serial number is 000000D8 BC96:4BCD
C:.
| internTest.csproj
| Program.cs
|
\---obj
internTest.csproj.nuget.cache
internTest.csproj.nuget.g.props
internTest.csproj.nuget.g.targets
project.assets.json
Jack could see a Program.cs
which must be the console application, an internTest.csproj
(“which must have been named after the parent folder”, he thought) and an obj
folder full of other files ("‘obj’ and ‘bin are build outputs, from memory").
The next instruction in the original list of commands was restore
:
C:\Users\jack\internTest>dotnet restore
Restore completed in 22.69 ms for C:\Users\jackr\internTest\internTest.csproj.
“‘Restore completed’, that’s what is said after I ran ‘dotnet new’, so it must have run that for me automatically.” The next two options were run
and build
. Since Jack was following the order given, he figured he might as well use run
first and see what happens.
C:\Users\jackr\internTest>dotnet run
Hello World!
“Alright, maybe?” He figured it best to look at that Program.cs
file to see what was what. Having not set up his machine with emacs for windows yet, the file was promptly opened in ’notepad’.
using System;
namespace internTest
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
}
}
}
Guessing the program has worked as expected he moved onto the next command, build
.
C:\Users\jackr\internTest>dotnet build
Microsoft (R) Build Engine version 15.3.409.57025 for .NET Core
Copyright (C) Microsoft Corporation. All rights reserved.
internTest -> C:\Users\jackr\internTest\bin\Debug\netcoreapp2.0\internTest.dll
Build succeeded.
0 Warning(s)
0 Error(s)
Time Elapsed 00:00:05.12
“So ‘build’ appears to do what you would think it does. Moving on to ‘publish’:”
C:\Users\jackr\internTest>dotnet publish
Microsoft (R) Build Engine version 15.3.409.57025 for .NET Core
Copyright (C) Microsoft Corporation. All rights reserved.
internTest -> C:\Users\jackr\internTest\bin\Debug\netcoreapp2.0\internTest.dll
internTest -> C:\Users\jackr\internTest\bin\Debug\netcoreapp2.0\publish\
C:\Users\jackr\internTest>tree /F /A
Folder PATH listing for volume Windows
Volume serial number is 00000093 BC96:4BCD
C:.
| internTest.csproj
| Program.cs
|
+---bin
| \---Debug
| \---netcoreapp2.0
| | internTest.deps.json
| | internTest.dll
| | internTest.pdb
| | internTest.runtimeconfig.dev.json
| | internTest.runtimeconfig.json
| |
| \---publish
| internTest.deps.json
| internTest.dll
| internTest.pdb
| internTest.runtimeconfig.json
|
\---obj
| internTest.csproj.nuget.cache
| internTest.csproj.nuget.g.props
| internTest.csproj.nuget.g.targets
| project.assets.json
|
\---Debug
\---netcoreapp2.0
internTest.AssemblyInfo.cs
internTest.AssemblyInfoInputs.cache
internTest.csproj.CoreCompileInputs.cache
internTest.csproj.FileListAbsolute.txt
internTest.dll
internTest.pdb
“That has made a publish folder with a ‘dll’ in it, but I expected an ’exe’. I wonder if I can find out more on publish…”. He tried dotnet help publish
. For a reason totally unknown to Jack, this launched a web browser window to https://docs.microsoft.com/en-gb/dotnet/core/tools/dotnet-publish?tabs=netcore2x displaying help for the publish command, reminiscent of a MAN page. Trying again for something that didn’t take him away from the shell, he tried dotnet publish --help
instead.
C:\Users\jackr\internTest>dotnet publish --help
Usage: dotnet publish [options]
Options:
-h, --help Show help information.
-o, --output <OUTPUT_DIR> Output directory in which to place the published artifacts.
-f, --framework <FRAMEWORK> Target framework to publish for. The target framework has to be specified in the project file.
-r, --runtime <RUNTIME_IDENTIFIER> Publish the project for a given runtime. This is used when creating self-contained deployment. Default is to publish a framework-dependent app.
-c, --configuration <CONFIGURATION> Configuration to use for building the project. Default for most projects is "Debug".
--version-suffix <VERSION_SUFFIX> Defines the value for the $(VersionSuffix) property in the project.
--manifest <manifest.xml> The path to a target manifest file that contains the list of packages to be excluded from the publish step.
--self-contained Publish the .NET Core runtime with your application so the runtime doesn't need to be installed on the target machine. Defaults to 'true' if a runtime identifier is specified.
--no-restore Does not do an implicit restore when executing the command.
-v, --verbosity Set the verbosity level of the command. Allowed values are q[uiet], m[inimal], n[ormal], d[etailed], and diag[nostic].
--no-dependencies Set this flag to ignore project to project references and only restore the root project.
--force Set this flag to force all dependencies to be resolved even if the last restore was successful. This is equivalent to deleting project.assets.json.
There were at least two useful finds in this bunch: --output
or -o
would let him choose a different location to publish to. --self-contained
seemed like it might give him an exe
, perhaps. Jack tried a few combinations, which resulted in some errors. He tried to correct them as he went.
C:\Users\jackr\internTest>dotnet publish -o C:\publish\interntestoutput --self-contained
Microsoft (R) Build Engine version 15.3.409.57025 for .NET Core
Copyright (C) Microsoft Corporation. All rights reserved.
C:\Program Files\dotnet\sdk\2.0.0\Sdks\Microsoft.NET.Sdk\build\Microsoft.NET.RuntimeIdentifierInference.targets(116,5): error : It is not supported to build or publish a self-contained application without specifying a RuntimeIdentifier. Please either specify a RuntimeIdentifier or set SelfContained to false. [C:\Users\jackr\internTest\internTest.csproj]
C:\Users\jackr\internTest>dotnet publish -o C:\publish\interntestoutput --self-contained -r windows
Microsoft (R) Build Engine version 15.3.409.57025 for .NET Core
Copyright (C) Microsoft Corporation. All rights reserved.
C:\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.netcore.app\2.0.0\build\netcoreapp2.0\Microsoft.NETCore.App.targets(19,5): error : Project is targeting runtime 'windows' but did not resolve any runtime-specific packages for the 'Microsoft.NETCore.App' package. This runtime may not be supported by .NET Core. [C:\Users\mclea\internTest\internTest.csproj]
So firstly It is not supported to build or publish a self-contained application without specifying a RuntimeIdentifier
seems to be a thing. and windows
as a value results in Project is targeting runtime 'windows' but did not resolve any runtime-specific packages for the 'Microsoft.NETCore.App' package
. After going back to that web page that launched when he typed in dotnet help publish
he found more info on that option:
-r|–runtime <RUNTIME_IDENTIFIER>
Publishes the application for a given runtime. This is used when creating a self-contained deployment (SCD). For a list of Runtime Identifiers (RIDs), see the RID catalog. Default is to publish a framework-dependent deployment (FDD).
Clicking on the link for RID catalog found that he needed to use one of linux-x64
, ubuntu.14.04-x64
, win7-x64
, or osx.10.12-x64
as the runtime value. Must be win7-x64
, then. Trying again:
C:\Users\jackr\internTest>dotnet publish -o C:\publish\interntestoutput --self-contained -r win7-x64
Microsoft (R) Build Engine version 15.3.409.57025 for .NET Core
Copyright (C) Microsoft Corporation. All rights reserved.
internTest -> C:\Users\jackr\internTest\bin\Debug\netcoreapp2.0\win7-x64\internTest.dll
internTest -> C:\publish\interntestoutput\
C:\Users\jackr\internTest>cd c:\publish\interntestoutput
c:\publish\interntestoutput>tree /F /A
Folder PATH listing for volume Windows
Volume serial number is 00000062 BC96:4BCD
C:.
api-ms-win-*.dll <-- truncated for your reading pleasure
clrcompression.dll
clretwrc.dll
clrjit.dll
coreclr.dll
dbgshim.dll
hostfxr.dll
hostpolicy.dll
internTest.deps.json
internTest.dll
internTest.exe
internTest.pdb
internTest.runtimeconfig.json
Microsoft.CSharp.dll
Microsoft.DiaSymReader.Native.amd64.dll
Microsoft.VisualBasic.dll
Microsoft.Win32.Primitives.dll
Microsoft.Win32.Registry.dll
mscordaccore.dll
mscordaccore_amd64_amd64_4.6.00001.0.dll
mscordbi.dll
mscorlib.dll
mscorrc.debug.dll
mscorrc.dll
netstandard.dll
sos.dll
SOS.NETCore.dll
sos_amd64_amd64_4.6.00001.0.dll
System.*.dll <-- also truncated for readability, phew!
ucrtbase.dll
WindowsBase.dll
Finally! An internTest.exe
as expected. Jack makes a note that this folder is a whopping 61.7 MB
in size, though! Let’s run it for complete satisfaction:
c:\publish\interntestoutput>internTest.exe
Hello World!
Jack remembered seeing Solution File (sln
) back in the dotnet new
help window. He went back to his original project to see how he might add a solution to it. Pretty quickly he has this sussed out, too.
c:\publish\interntestoutput>cd c:\Users\jackr\internTest
c:\Users\jackr\internTest>dotnet new sln
The template "Solution File" was created successfully.
c:\Users\jackr\internTest>dotnet sln
Required command was not provided.
Usage: dotnet sln [options] <SLN_FILE> [command]
Arguments:
<SLN_FILE> Solution file to operate on. If not specified, the command will search the current directory for one.
Options:
-h, --help Show help information.
Commands:
add <args> .NET Add project(s) to a solution file Command
list .NET List project(s) in a solution file Command
remove <args> .NET Remove project(s) from a solution file Command
c:\Users\jackr\internTest>dotnet sln add internTest.csproj
Project `internTest.csproj` added to the solution.
c:\Users\jackr\internTest>ls
'ls' is not recognized as an internal or external command,
operable program or batch file.
c:\Users\jackr\internTest>dir
Volume in drive C is Windows
Volume Serial Number is BC96-4BCD
Directory of c:\Users\jackr\internTest
23/09/2017 18:20 <DIR> .
23/09/2017 18:20 <DIR> ..
23/09/2017 17:38 <DIR> bin
23/09/2017 17:30 178 internTest.csproj
23/09/2017 18:20 1,691 internTest.sln
23/09/2017 18:12 <DIR> obj
23/09/2017 17:30 192 Program.cs
3 File(s) 2,061 bytes
4 Dir(s) 2,718,973,952 bytes free
with two simple commands, dotnet new sln
and dotnet sln add internTest.csproj
Jack was able to create a Visual Studio sln
file and add the project to it. Mint.
In total this had only taken Jack an hour (far less time than this Author took to write this whole farce up) and he took his findings back to Joe.
“What? Done already. Dammit, Intern! You’re not meant to be so productive! I’ll have to get you fetching coffees and making team flight suits. How are you at working a sewing machine? First things first though. Write up your findings and get ready to present to the entire department tomorrow, at the cross-team catchup!”
Jack left feeling a mix of achievement and pressure while wondering if she was serious about those jumpsuits…
The dotnet CLI in a nutshell. If an intern can do it so can you. Plenty was left unexplored, but the Author has left plenty of breadcrumbs for you to continue the journey from where Jack left off.
Stay tuned for more adventures of An Intern Named -Grack- Jack.
*Any resemblance to real people is purely intentional for comedic effect as part of an in-joke. The rest is just an interesting way to look a getting started with dotnet CLI.