Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
188 changes: 52 additions & 136 deletions docs/core/tools/global-tools-how-to-create.md
Original file line number Diff line number Diff line change
@@ -1,25 +1,25 @@
---
title: "Tutorial: Create a .NET tool"
description: Learn how to create a .NET tool. A tool is a console application that is installed by using the .NET CLI.
description: Learn how to create a .NET tool. A tool is a console application that is installed by using the .NET CLI. In this tutorial, you build a tool that reports .NET runtime information, OS details, and key environment variable settings.
ms.topic: tutorial
ms.date: 10/27/2021
ms.date: 04/08/2026
---

# Tutorial: Create a .NET tool using the .NET CLI

**This article applies to:** ✔️ .NET Core 2.1 SDK and later versions
**This article applies to:** ✔️ .NET 8 SDK and later versions

This tutorial teaches you how to create and package a .NET tool. The .NET CLI lets you create a console application as a tool, which others can install and run. .NET tools are NuGet packages that are installed from the .NET CLI. For more information about tools, see [.NET tools overview](global-tools.md).

The tool that you'll create is a console application that takes a message as input and displays the message along with lines of text that create the image of a robot.
The tool that you'll create is a console application that takes information about the current .NET environment and displays it, including the .NET version, operating system details, and key environment variable settings.

This is the first in a series of three tutorials. In this tutorial, you create and package a tool. In the next two tutorials you [use the tool as a global tool](global-tools-how-to-use.md) and [use the tool as a local tool](local-tools-how-to-use.md). The procedures for creating a tool are the same whether you use it as a global tool or as a local tool.

## Prerequisites

- [.NET SDK 6.0.100](https://dotnet.microsoft.com/download/dotnet/6.0) or a later version.
- [.NET SDK 10.0](https://dotnet.microsoft.com/download/dotnet/10.0) or a later version.

This tutorial uses .NET SDK 6.0, but global tools are available starting in .NET Core SDK 2.1. Local tools are available starting in .NET Core SDK 3.0.
This tutorial uses .NET SDK 10.0. Global tools are available starting in .NET Core SDK 2.1, and local tools are available starting in .NET Core SDK 3.0.
Comment on lines +10 to +22
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The article says it applies to .NET 8 SDK and later, but the tutorial requires .NET SDK 10.0 and the included project targets net10.0. Align the applies to line with the actual minimum SDK/runtime (or retarget the tutorial to net8.0 if you want it to apply to .NET 8).

Copilot uses AI. Check for mistakes.

- A text editor or code editor of your choice.

Expand All @@ -30,150 +30,81 @@ This is the first in a series of three tutorials. In this tutorial, you create a
1. Navigate to the *repository* folder and enter the following command:

```dotnetcli
dotnet new console -n microsoft.botsay -f net6.0
dotnet new console -n dotnet-env
```

The command creates a new folder named *microsoft.botsay* under the *repository* folder.
The command creates a new folder named *dotnet-env* under the *repository* folder.

> [!NOTE]
> For this tutorial you create a tool that targets .NET 6.0. To target a different framework, change the `-f|--framework` option. To target multiple frameworks, change the `TargetFramework` element to a `TargetFrameworks` element in the project file, as shown in the following example:
>
> ```xml
> <Project Sdk="Microsoft.NET.Sdk">
> <PropertyGroup>
> <OutputType>Exe</OutputType>
> <TargetFrameworks>net8.0;net6.0</TargetFrameworks>
> </PropertyGroup>
> </Project>
> ```

1. Navigate to the *microsoft.botsay* folder.
1. Navigate to the *dotnet-env* folder.

```console
cd microsoft.botsay
cd dotnet-env
```

## Add the code

1. Open the *Program.cs* file with your code editor.

1. Replace the code in *Program.cs* with the following code:
1. Replace the contents with the following code:

```csharp
using System.Reflection;
:::code language="csharp" source="./snippets/global-tools-how-to-create/csharp/Program.cs" id="fullprogram":::

namespace microsoft.botsay;
The program has two methods:

internal class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
}
}
```
- `Main` checks whether any arguments were passed. With no arguments, it calls `ShowInfo()`. With any argument, it prints the tool version.
- `ShowInfo` displays three sections of information:
Comment on lines +52 to +55
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This section describes a Main method, but the sample uses top-level statements (no explicit Main method in the source). Update the wording to refer to the program's entry point/top-level statements, or change the sample to an explicit Main method so the description matches the code.

Copilot uses AI. Check for mistakes.
- **Runtime** — the .NET version, framework description, and runtime identifier, using `Environment.Version` and `RuntimeInformation`.
- **System** — OS description, architecture, machine name, and processor count.
- **Environment Variables** — six key .NET-related variables (`DOTNET_ROOT`, `DOTNET_HOST_PATH`, `DOTNET_CLI_HOME`, `DOTNET_NOLOGO`, `NUGET_PACKAGES`, and `DOTNET_ENVIRONMENT`), showing `(not set)` for any that aren't configured.

The `using System.Reflection;` directive is needed by code that you add in the next step.

1. Replace the `Main` method with the following code to process the command-line arguments for the application.

```csharp
static void Main(string[] args)
{
if (args.Length == 0)
{
var versionString = Assembly.GetEntryAssembly()?
.GetCustomAttribute<AssemblyInformationalVersionAttribute>()?
.InformationalVersion
.ToString();

Console.WriteLine($"botsay v{versionString}");
Console.WriteLine("-------------");
Console.WriteLine("\nUsage:");
Console.WriteLine(" botsay <message>");
return;
}

ShowBot(string.Join(' ', args));
}
```

If no arguments are passed, a short help message is displayed. Otherwise, all of the arguments are concatenated into a single string and printed by calling the `ShowBot` method that you create in the next step.

1. Add a new method named `ShowBot` that takes a string parameter. The method prints out the message and an image of a robot using lines of text.

```csharp
static void ShowBot(string message)
{
string bot = $"\n {message}";
bot += @"
__________________
\
\
....
....'
....
..........
.............'..'..
................'..'.....
.......'..........'..'..'....
........'..........'..'..'.....
.'....'..'..........'..'.......'.
.'..................'... ......
. ......'......... .....
. _ __ ......
.. # ## ......
.... . .......
...... ....... ............
................ ......................
........................'................
......................'..'...... .......
.........................'..'..... .......
........ ..'.............'..'.... ..........
..'..'... ...............'....... ..........
...'...... ...... .......... ...... .......
........... ....... ........ ......
....... '...'.'. '.'.'.' ....
....... .....'.. ..'.....
.. .......... ..'........
............ ..............
............. '..............
...........'.. .'.'............
............... .'.'.............
.............'.. ..'..'...........
............... .'..............
......... ..............
.....
";
Console.WriteLine(bot);
}
```
The `using System.Reflection` directive is required for `Assembly.GetEntryAssembly()` and `AssemblyInformationalVersionAttribute`. The `using System.Runtime.InteropServices` directive is required for `RuntimeInformation`.

1. Save your changes.

## Test the application

Run the project and see the output. Try these variations at the command line to see different results:
Run the project and see the output:

```dotnetcli
dotnet run
dotnet run -- "Hello from the bot"
dotnet run -- Hello from the bot
```

All arguments after the `--` delimiter are passed to your application.
The output looks similar to the following example:

```console
dotnet-env v1.0.0
----------------------------------------

Runtime
.NET Version 10.0.4
Framework .NET 10.0.4
Runtime Identifier win-x64

System
OS Microsoft Windows 10.0.22631
Architecture X64
Machine Name MY-MACHINE
Processor Count 16

Environment Variables
DOTNET_ROOT (not set)
DOTNET_HOST_PATH (not set)
DOTNET_CLI_HOME (not set)
DOTNET_NOLOGO (not set)
NUGET_PACKAGES (not set)
DOTNET_ENVIRONMENT (not set)
```

> [!NOTE]
> The values shown depend on your machine and .NET installation. The output varies by platform.

## Package the tool

Before you can pack and distribute the application as a tool, you need to modify the project file.

1. Open the *microsoft.botsay.csproj* file and add three new XML nodes to the end of the `<PropertyGroup>` node:
1. Open the *dotnet-env.csproj* file and add three new XML nodes to the end of the `<PropertyGroup>` node:

```xml
<PackAsTool>true</PackAsTool>
<ToolCommandName>botsay</ToolCommandName>
<PackageOutputPath>./nupkg</PackageOutputPath>
```
:::code language="xml" source="./snippets/global-tools-how-to-create/csharp/dotnet-env.csproj" id="toolsettings":::

`<ToolCommandName>` is an optional element that specifies the command that will invoke the tool after it's installed. If this element isn't provided, the command name for the tool is the assembly name, which is typically the project file name without the *.csproj* extension.

Expand All @@ -184,30 +115,15 @@ Before you can pack and distribute the application as a tool, you need to modify

The project file now looks like the following example:

```xml
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>

<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>

<PackAsTool>true</PackAsTool>
<ToolCommandName>botsay</ToolCommandName>
<PackageOutputPath>./nupkg</PackageOutputPath>

</PropertyGroup>

</Project>
```
:::code language="xml" source="./snippets/global-tools-how-to-create/csharp/dotnet-env.csproj" id="full":::

1. Create a NuGet package by running the [dotnet pack](dotnet-pack.md) command:

```dotnetcli
dotnet pack
```

The *microsoft.botsay.1.0.0.nupkg* file is created in the folder identified by the `<PackageOutputPath>` value from the *microsoft.botsay.csproj* file, which in this example is the *./nupkg* folder.
The *dotnet-env.1.0.0.nupkg* file is created in the folder identified by the `<PackageOutputPath>` value from the *dotnet-env.csproj* file, which in this example is the *./nupkg* folder.

When you want to release a tool publicly, you can upload it to `https://www.nuget.org`. Once the tool is available on NuGet, developers can install the tool by using the [dotnet tool install](dotnet-tool-install.md) command. For this tutorial you install the package directly from the local *nupkg* folder, so there's no need to upload the package to NuGet.

Expand Down
38 changes: 19 additions & 19 deletions docs/core/tools/global-tools-how-to-use.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@
title: "Tutorial: Install and use a .NET global tool"
description: Learn how to install and use a .NET tool as a global tool.
ms.topic: tutorial
ms.date: 09/06/2025
ms.date: 04/08/2026
---

# Tutorial: Install and use a .NET global tool using the .NET CLI

**This article applies to:** ✔️ .NET Core 2.1 SDK and later versions
**This article applies to:** ✔️ .NET 8 SDK and later versions

This tutorial teaches you how to install and use a global tool. You use a tool that you create in the [first tutorial of this series](global-tools-how-to-create.md).

Expand All @@ -23,7 +23,7 @@ Starting with .NET 10.0.100, you can run .NET tools without permanent installati
1. Run the tool directly using dnx (simplified syntax):

```dotnetcli
dnx microsoft.botsay --add-source ./nupkg microsoft.botsay hello from the bot
dnx dotnet-env --add-source ./nupkg
```

The `--add-source` parameter tells the .NET CLI to use the *./nupkg* directory as an additional source feed for NuGet packages when the tool is not available on NuGet.org.
Expand All @@ -32,38 +32,38 @@ Starting with .NET 10.0.100, you can run .NET tools without permanent installati

If you prefer permanent installation for frequent use:

1. Install the tool from the package by running the [dotnet tool install](dotnet-tool-install.md) command in the *microsoft.botsay* project folder:
1. Install the tool from the package by running the [dotnet tool install](dotnet-tool-install.md) command in the *dotnet-env* project folder:

```dotnetcli
dotnet tool install --global --add-source ./nupkg microsoft.botsay
dotnet tool install --global --add-source ./nupkg dotnet-env
```

The `--global` parameter tells the .NET CLI to install the tool binaries in a default location that is automatically added to the PATH environment variable.

The `--add-source` parameter tells the .NET CLI to temporarily use the *./nupkg* directory as an additional source feed for NuGet packages. You gave your package a unique name to make sure that it will only be found in the *./nupkg* directory, not on the Nuget.org site.
The `--add-source` parameter tells the .NET CLI to temporarily use the *./nupkg* directory as an additional source feed for NuGet packages. You gave your package a unique name to make sure that it will only be found in the *./nupkg* directory, not on the NuGet.org site.

The output shows the command used to call the tool and the version installed:

```console
You can invoke the tool using the following command: botsay
Tool 'microsoft.botsay' (version '1.0.0') was successfully installed.
You can invoke the tool using the following command: dotnet-env
Tool 'dotnet-env' (version '1.0.0') was successfully installed.
```

[!INCLUDE[](includes/dotnet-tool-install-arch-options.md)]

1. Invoke the tool:

```console
botsay hello from the bot
dotnet-env
```

> [!NOTE]
> If this command fails, you may need to open a new terminal to refresh the PATH.
> If this command fails, you might need to open a new terminal to refresh the PATH.

1. Remove the tool by running the [dotnet tool uninstall](dotnet-tool-uninstall.md) command:

```dotnetcli
dotnet tool uninstall -g microsoft.botsay
dotnet tool uninstall -g dotnet-env
```

## Use the tool as a global tool installed in a custom location
Expand All @@ -73,50 +73,50 @@ If you prefer permanent installation for frequent use:
On Windows:

```dotnetcli
dotnet tool install --tool-path c:\dotnet-tools --add-source ./nupkg microsoft.botsay
dotnet tool install --tool-path c:\dotnet-tools --add-source ./nupkg dotnet-env
```

On Linux or macOS:

```dotnetcli
dotnet tool install --tool-path ~/bin --add-source ./nupkg microsoft.botsay
dotnet tool install --tool-path ~/bin --add-source ./nupkg dotnet-env
```

The `--tool-path` parameter tells the .NET CLI to install the tool binaries in the specified location. If the directory doesn't exist, it is created. This directory is not automatically added to the PATH environment variable.

The output shows the command used to call the tool and the version installed:

```console
You can invoke the tool using the following command: botsay
Tool 'microsoft.botsay' (version '1.0.0') was successfully installed.
You can invoke the tool using the following command: dotnet-env
Tool 'dotnet-env' (version '1.0.0') was successfully installed.
```

1. Invoke the tool:

On Windows:

```console
c:\dotnet-tools\botsay hello from the bot
c:\dotnet-tools\dotnet-env
```

On Linux or macOS:

```console
~/bin/botsay hello from the bot
~/bin/dotnet-env
```

1. Remove the tool by running the [dotnet tool uninstall](dotnet-tool-uninstall.md) command:

On Windows:

```dotnetcli
dotnet tool uninstall --tool-path c:\dotnet-tools microsoft.botsay
dotnet tool uninstall --tool-path c:\dotnet-tools dotnet-env
```

On Linux or macOS:

```dotnetcli
dotnet tool uninstall --tool-path ~/bin microsoft.botsay
dotnet tool uninstall --tool-path ~/bin dotnet-env
```

## Troubleshoot
Expand Down
Loading
Loading