diff --git a/src/Cli/dotnet/Commands/CliCommandStrings.resx b/src/Cli/dotnet/Commands/CliCommandStrings.resx
index 6ca03e2f5fe6..95113e71d016 100644
--- a/src/Cli/dotnet/Commands/CliCommandStrings.resx
+++ b/src/Cli/dotnet/Commands/CliCommandStrings.resx
@@ -2047,6 +2047,33 @@ Your project targets multiple frameworks. Specify which framework to run using '
Install or manage tools that extend the .NET experience.
+
+ Manage tools using Microsoft Desired State Configuration (DSC).
+
+
+ Get the current state of installed tools.
+
+
+ Set the desired state of tools by installing or updating them.
+
+
+ Test if the current state matches the desired state.
+
+
+ Export the current state of all installed tools.
+
+
+ Get the JSON schema for DSC tool state.
+
+
+ Get the Microsoft Desired State Configuration (DSC) resource manifest for dotnet tool.
+
+
+ JSON input representing the desired or requested tool state.
+
+
+ JSON
+
Add an additional NuGet package source to use during installation.
diff --git a/src/Cli/dotnet/Commands/Tool/Dsc/DscModels.cs b/src/Cli/dotnet/Commands/Tool/Dsc/DscModels.cs
new file mode 100644
index 000000000000..22205ddaa99d
--- /dev/null
+++ b/src/Cli/dotnet/Commands/Tool/Dsc/DscModels.cs
@@ -0,0 +1,97 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Text.Json.Serialization;
+using NuGet.Versioning;
+
+namespace Microsoft.DotNet.Cli.Commands.Tool.Dsc;
+
+internal record DscToolsState
+{
+ [JsonPropertyName("tools")]
+ public List Tools { get; set; } = new List();
+}
+
+internal record DscToolState
+{
+ [JsonPropertyName("packageId")]
+ public string? PackageId { get; set; }
+
+ [JsonPropertyName("version")]
+ public string? Version { get; set; }
+
+ [JsonPropertyName("commands")]
+ public List? Commands { get; set; }
+
+ [JsonPropertyName("scope")]
+ [JsonConverter(typeof(JsonStringEnumConverter))]
+ public DscToolScope? Scope { get; set; }
+
+ [JsonPropertyName("toolPath")]
+ public string? ToolPath { get; set; }
+
+ [JsonPropertyName("manifestPath")]
+ public string? ManifestPath { get; set; }
+
+ [JsonPropertyName("_exist")]
+ public bool? Exist { get; set; }
+
+ ///
+ /// Parses packageId and version from the PackageId property.
+ /// Supports format: "packageId" or "packageId@version"
+ ///
+ public (string PackageId, VersionRange? VersionRange) ParsePackageIdentity()
+ {
+ if (string.IsNullOrEmpty(PackageId))
+ {
+ return (string.Empty, null);
+ }
+
+ string[] parts = PackageId.Split('@');
+ string packageId = parts[0];
+
+ if (parts.Length > 1 && !string.IsNullOrEmpty(parts[1]))
+ {
+ // packageId@version format
+ if (VersionRange.TryParse(parts[1], out var versionRange))
+ {
+ return (packageId, versionRange);
+ }
+ }
+ else if (!string.IsNullOrEmpty(Version))
+ {
+ // Use separate Version property if available
+ if (VersionRange.TryParse(Version, out var versionRange))
+ {
+ return (packageId, versionRange);
+ }
+ }
+
+ return (packageId, null);
+ }
+}
+
+internal enum DscToolScope
+{
+ Global,
+ Local,
+ ToolPath
+}
+
+internal record DscErrorMessage
+{
+ [JsonPropertyName("error")]
+ public string Error { get; set; } = string.Empty;
+}
+
+internal record DscDebugMessage
+{
+ [JsonPropertyName("debug")]
+ public string Debug { get; set; } = string.Empty;
+}
+
+internal record DscTraceMessage
+{
+ [JsonPropertyName("trace")]
+ public string Trace { get; set; } = string.Empty;
+}
diff --git a/src/Cli/dotnet/Commands/Tool/Dsc/DscWriter.cs b/src/Cli/dotnet/Commands/Tool/Dsc/DscWriter.cs
new file mode 100644
index 000000000000..d381692988fe
--- /dev/null
+++ b/src/Cli/dotnet/Commands/Tool/Dsc/DscWriter.cs
@@ -0,0 +1,219 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Text.Json;
+using Microsoft.DotNet.Cli.ToolPackage;
+using Microsoft.DotNet.Cli.Utils;
+using Microsoft.Extensions.EnvironmentAbstractions;
+
+namespace Microsoft.DotNet.Cli.Commands.Tool.Dsc;
+
+internal static class DscWriter
+{
+ ///
+ /// Writes an error message to stderr in DSC JSON format.
+ ///
+ public static void WriteError(string message)
+ {
+ var errorMessage = new DscErrorMessage { Error = message };
+ string json = JsonSerializer.Serialize(errorMessage);
+ Reporter.Error.WriteLine(json);
+ }
+
+ ///
+ /// Writes a debug message to stderr in DSC JSON format.
+ ///
+ public static void WriteDebug(string message)
+ {
+ var debugMessage = new DscDebugMessage { Debug = message };
+ string json = JsonSerializer.Serialize(debugMessage);
+ Reporter.Error.WriteLine(json);
+ }
+
+ ///
+ /// Writes a trace message to stderr in DSC JSON format.
+ ///
+ public static void WriteTrace(string message)
+ {
+ var traceMessage = new DscTraceMessage { Trace = message };
+ string json = JsonSerializer.Serialize(traceMessage);
+ Reporter.Error.WriteLine(json);
+ }
+
+ ///
+ /// Writes the result state to stdout in DSC JSON format.
+ ///
+ public static void WriteResult(DscToolsState state)
+ {
+ var options = new JsonSerializerOptions
+ {
+ DefaultIgnoreCondition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull,
+ WriteIndented = false
+ };
+
+ string json = JsonSerializer.Serialize(state, options);
+ Reporter.Output.WriteLine(json);
+ }
+
+ ///
+ /// Writes any object to stdout in JSON format.
+ ///
+ public static void WriteJson(object obj, bool writeIndented = false)
+ {
+ var options = new JsonSerializerOptions
+ {
+ WriteIndented = writeIndented
+ };
+
+ string json = JsonSerializer.Serialize(obj, options);
+ Reporter.Output.WriteLine(json);
+ }
+
+ ///
+ /// Reads input from either stdin (if input is "-") or from a file.
+ ///
+ public static string ReadInput(string input)
+ {
+ if (input == "-")
+ {
+ return Console.In.ReadToEnd();
+ }
+ else
+ {
+ return File.ReadAllText(input);
+ }
+ }
+
+ ///
+ /// Reads and deserializes DSC tool state from input (file or stdin).
+ /// Returns null if input is not provided.
+ /// Exits with code 1 if deserialization fails.
+ ///
+ public static DscToolsState? ReadAndDeserializeInput(string? input)
+ {
+ if (string.IsNullOrEmpty(input))
+ {
+ return null;
+ }
+
+ try
+ {
+ string jsonInput = ReadInput(input);
+ var inputState = JsonSerializer.Deserialize(jsonInput);
+ return inputState;
+ }
+ catch (JsonException ex)
+ {
+ WriteError($"Failed to deserialize JSON: {ex.Message}");
+ Environment.Exit(1);
+ return null; // Unreachable, but satisfies compiler
+ }
+ }
+
+ ///
+ /// Queries the actual state of a tool from the package store.
+ ///
+ public static DscToolState QueryToolState(DscToolState requestedState)
+ {
+ // Parse packageId to handle packageId@version syntax
+ var (packageIdString, _) = requestedState.ParsePackageIdentity();
+
+ if (string.IsNullOrEmpty(packageIdString))
+ {
+ packageIdString = requestedState.PackageId ?? string.Empty;
+ }
+
+ // Determine the scope and tool path based on the requested tool
+ DirectoryPath? toolPath = null;
+ DscToolScope scope = requestedState.Scope ?? DscToolScope.Global;
+
+ if (scope == DscToolScope.ToolPath && !string.IsNullOrWhiteSpace(requestedState.ToolPath))
+ {
+ toolPath = new DirectoryPath(requestedState.ToolPath);
+ }
+ else if (scope == DscToolScope.Global)
+ {
+ // Global tools, use default location (null)
+ toolPath = null;
+ }
+ else if (scope == DscToolScope.Local)
+ {
+ // TODO: Local tools require querying dotnet-tools.json in current directory
+ // For now, return not found for local tools
+ WriteDebug($"Local tool scope not yet implemented for {packageIdString}");
+ return new DscToolState
+ {
+ PackageId = packageIdString,
+ Version = null,
+ Commands = null,
+ Scope = DscToolScope.Local,
+ ToolPath = null,
+ ManifestPath = null,
+ Exist = false
+ };
+ }
+
+ // Query the tool package store
+ var packageStoreQuery = ToolPackageFactory.CreateToolPackageStoreQuery(toolPath);
+ var packageId = new PackageId(packageIdString);
+
+ try
+ {
+ // Find the tool package
+ var installedPackages = packageStoreQuery.EnumeratePackages()
+ .Where(p => p.Id.Equals(packageId))
+ .ToList();
+
+ if (installedPackages.Any())
+ {
+ // Tool exists, get its details from the first (or only) matching package
+ var package = installedPackages.First();
+
+ WriteDebug($"Found tool {package.Id} version {package.Version.ToNormalizedString()}");
+
+ return new DscToolState
+ {
+ PackageId = package.Id.ToString(),
+ Version = package.Version.ToNormalizedString(),
+ Commands = package.Command != null ? new List { package.Command.Name.Value } : null,
+ Scope = scope,
+ ToolPath = scope == DscToolScope.ToolPath ? requestedState.ToolPath : null,
+ ManifestPath = null,
+ Exist = true
+ };
+ }
+ else
+ {
+ // Tool not found
+ WriteDebug($"Tool {packageIdString} not found in {scope} scope");
+
+ return new DscToolState
+ {
+ PackageId = packageIdString,
+ Version = null,
+ Commands = null,
+ Scope = scope,
+ ToolPath = scope == DscToolScope.ToolPath ? requestedState.ToolPath : null,
+ ManifestPath = null,
+ Exist = false
+ };
+ }
+ }
+ catch (Exception ex)
+ {
+ // If there's an error querying the tool, return it as not found
+ WriteError($"Error querying tool {packageIdString}: {ex.Message}");
+
+ return new DscToolState
+ {
+ PackageId = packageIdString,
+ Version = null,
+ Commands = null,
+ Scope = scope,
+ ToolPath = scope == DscToolScope.ToolPath ? requestedState.ToolPath : null,
+ ManifestPath = null,
+ Exist = false
+ };
+ }
+ }
+}
diff --git a/src/Cli/dotnet/Commands/Tool/Dsc/ToolDscCommandParser.cs b/src/Cli/dotnet/Commands/Tool/Dsc/ToolDscCommandParser.cs
new file mode 100644
index 000000000000..8cc5054004ad
--- /dev/null
+++ b/src/Cli/dotnet/Commands/Tool/Dsc/ToolDscCommandParser.cs
@@ -0,0 +1,35 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.CommandLine;
+using Microsoft.DotNet.Cli.Extensions;
+
+namespace Microsoft.DotNet.Cli.Commands.Tool.Dsc;
+
+internal static class ToolDscCommandParser
+{
+ public static readonly string DocsLink = "https://aka.ms/dotnet-tool-dsc";
+
+ private static readonly Command Command = ConstructCommand();
+
+ public static Command GetCommand()
+ {
+ return Command;
+ }
+
+ private static Command ConstructCommand()
+ {
+ DocumentedCommand command = new("dsc", DocsLink, CliCommandStrings.ToolDscCommandDescription);
+
+ command.Subcommands.Add(ToolDscGetCommandParser.GetCommand());
+ command.Subcommands.Add(ToolDscSetCommandParser.GetCommand());
+ command.Subcommands.Add(ToolDscTestCommandParser.GetCommand());
+ command.Subcommands.Add(ToolDscExportCommandParser.GetCommand());
+ command.Subcommands.Add(ToolDscSchemaCommandParser.GetCommand());
+ command.Subcommands.Add(ToolDscManifestCommandParser.GetCommand());
+
+ command.SetAction((parseResult) => parseResult.HandleMissingCommand());
+
+ return command;
+ }
+}
diff --git a/src/Cli/dotnet/Commands/Tool/Dsc/ToolDscExportCommand.cs b/src/Cli/dotnet/Commands/Tool/Dsc/ToolDscExportCommand.cs
new file mode 100644
index 000000000000..577b2bd13f20
--- /dev/null
+++ b/src/Cli/dotnet/Commands/Tool/Dsc/ToolDscExportCommand.cs
@@ -0,0 +1,95 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+#nullable disable
+
+using System.CommandLine;
+using System.Text.Json;
+using Microsoft.DotNet.Cli.ToolPackage;
+using Microsoft.DotNet.Cli.Utils;
+using Microsoft.Extensions.EnvironmentAbstractions;
+
+namespace Microsoft.DotNet.Cli.Commands.Tool.Dsc;
+
+internal class ToolDscExportCommand : CommandBase
+{
+ public ToolDscExportCommand(ParseResult parseResult)
+ : base(parseResult)
+ {
+ }
+
+ public override int Execute()
+ {
+ try
+ {
+ var state = new DscToolsState();
+
+ // Enumerate all global tools
+ DscWriter.WriteTrace("Enumerating global tools");
+ var globalTools = EnumerateGlobalTools();
+ foreach (var tool in globalTools)
+ {
+ state.Tools.Add(tool);
+ }
+
+ DscWriter.WriteTrace($"Found {state.Tools.Count} global tools");
+
+ // TODO: Add support for local tools (requires scanning for dotnet-tools.json files)
+ // TODO: Add support for tool-path tools (requires configuration of tool paths to scan)
+
+ DscWriter.WriteResult(state);
+
+ return 0;
+ }
+ catch (Exception ex)
+ {
+ DscWriter.WriteError($"Unexpected error: {ex.Message}");
+ return 1;
+ }
+ }
+
+ private List EnumerateGlobalTools()
+ {
+ var tools = new List();
+
+ // Query the global tool package store (null = default global location)
+ var packageStoreQuery = ToolPackageFactory.CreateToolPackageStoreQuery(null);
+
+ try
+ {
+ var packages = packageStoreQuery.EnumeratePackages();
+
+ foreach (var package in packages)
+ {
+ try
+ {
+ // Only include packages that have commands
+ if (package.Command != null)
+ {
+ tools.Add(new DscToolState
+ {
+ PackageId = package.Id.ToString(),
+ Version = package.Version.ToNormalizedString(),
+ Commands = new List { package.Command.Name.Value },
+ Scope = DscToolScope.Global,
+ ToolPath = null,
+ ManifestPath = null,
+ Exist = true
+ });
+ }
+ }
+ catch (Exception ex)
+ {
+ // If we can't read a specific package, log a warning and continue
+ DscWriter.WriteError($"Warning: Could not read tool {package.Id}: {ex.Message}");
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ DscWriter.WriteError($"Error enumerating global tools: {ex.Message}");
+ }
+
+ return tools;
+ }
+}
diff --git a/src/Cli/dotnet/Commands/Tool/Dsc/ToolDscExportCommandParser.cs b/src/Cli/dotnet/Commands/Tool/Dsc/ToolDscExportCommandParser.cs
new file mode 100644
index 000000000000..03a3b0d27016
--- /dev/null
+++ b/src/Cli/dotnet/Commands/Tool/Dsc/ToolDscExportCommandParser.cs
@@ -0,0 +1,25 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.CommandLine;
+
+namespace Microsoft.DotNet.Cli.Commands.Tool.Dsc;
+
+internal static class ToolDscExportCommandParser
+{
+ private static readonly Command Command = ConstructCommand();
+
+ public static Command GetCommand()
+ {
+ return Command;
+ }
+
+ private static Command ConstructCommand()
+ {
+ Command command = new("export", CliCommandStrings.ToolDscExportCommandDescription);
+
+ command.SetAction((parseResult) => new ToolDscExportCommand(parseResult).Execute());
+
+ return command;
+ }
+}
diff --git a/src/Cli/dotnet/Commands/Tool/Dsc/ToolDscGetCommand.cs b/src/Cli/dotnet/Commands/Tool/Dsc/ToolDscGetCommand.cs
new file mode 100644
index 000000000000..13cb49986589
--- /dev/null
+++ b/src/Cli/dotnet/Commands/Tool/Dsc/ToolDscGetCommand.cs
@@ -0,0 +1,48 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+#nullable disable
+
+using System.CommandLine;
+using System.Text.Json;
+using Microsoft.DotNet.Cli.Utils;
+
+namespace Microsoft.DotNet.Cli.Commands.Tool.Dsc;
+
+internal class ToolDscGetCommand : CommandBase
+{
+ private readonly string _input;
+
+ public ToolDscGetCommand(ParseResult parseResult)
+ : base(parseResult)
+ {
+ _input = parseResult.GetValue(ToolDscGetCommandParser.InputOption);
+ }
+
+ public override int Execute()
+ {
+ try
+ {
+ var inputState = DscWriter.ReadAndDeserializeInput(_input);
+ var resultState = new DscToolsState();
+
+ foreach (var tool in inputState?.Tools ?? Enumerable.Empty())
+ {
+ var actualState = DscWriter.QueryToolState(tool);
+ if (actualState != null)
+ {
+ resultState.Tools.Add(actualState);
+ }
+ }
+
+ DscWriter.WriteResult(resultState);
+
+ return 0;
+ }
+ catch (Exception ex)
+ {
+ DscWriter.WriteError($"Unexpected error: {ex.Message}");
+ return 1;
+ }
+ }
+}
diff --git a/src/Cli/dotnet/Commands/Tool/Dsc/ToolDscGetCommandParser.cs b/src/Cli/dotnet/Commands/Tool/Dsc/ToolDscGetCommandParser.cs
new file mode 100644
index 000000000000..88dd47a3e7fe
--- /dev/null
+++ b/src/Cli/dotnet/Commands/Tool/Dsc/ToolDscGetCommandParser.cs
@@ -0,0 +1,33 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.CommandLine;
+using Microsoft.DotNet.Cli.Extensions;
+
+namespace Microsoft.DotNet.Cli.Commands.Tool.Dsc;
+
+internal static class ToolDscGetCommandParser
+{
+ public static readonly Option InputOption = new("--input", "-i")
+ {
+ Description = CliCommandStrings.ToolDscInputOptionDescription,
+ HelpName = CliCommandStrings.ToolDscInputOptionName
+ };
+
+ private static readonly Command Command = ConstructCommand();
+
+ public static Command GetCommand()
+ {
+ return Command;
+ }
+
+ private static Command ConstructCommand()
+ {
+ Command command = new("get", CliCommandStrings.ToolDscGetCommandDescription);
+ command.Options.Add(InputOption);
+
+ command.SetAction((parseResult) => new ToolDscGetCommand(parseResult).Execute());
+
+ return command;
+ }
+}
diff --git a/src/Cli/dotnet/Commands/Tool/Dsc/ToolDscManifestCommand.cs b/src/Cli/dotnet/Commands/Tool/Dsc/ToolDscManifestCommand.cs
new file mode 100644
index 000000000000..5df59cbfd0ab
--- /dev/null
+++ b/src/Cli/dotnet/Commands/Tool/Dsc/ToolDscManifestCommand.cs
@@ -0,0 +1,103 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.CommandLine;
+using System.Text.Json;
+using Microsoft.DotNet.Cli.Utils;
+
+namespace Microsoft.DotNet.Cli.Commands.Tool.Dsc;
+
+internal class ToolDscManifestCommand : CommandBase
+{
+ public ToolDscManifestCommand(ParseResult parseResult)
+ : base(parseResult)
+ {
+ }
+
+ public override int Execute()
+ {
+ try
+ {
+ var manifest = new Dictionary
+ {
+ ["$schema"] = "https://aka.ms/dsc/schemas/v3/bundled/resource/manifest.json",
+ ["type"] = "Microsoft.DotNet.Sdk/Tool",
+ ["description"] = "Manage .NET tools using Microsoft Desired State Configuration (DSC).",
+ ["version"] = "1.0.0",
+ ["tags"] = new[] { "dotnet", "tool", "sdk" },
+ ["exitCodes"] = new Dictionary
+ {
+ ["0"] = "Success",
+ ["1"] = "Error"
+ },
+ ["schema"] = new Dictionary
+ {
+ ["command"] = new Dictionary
+ {
+ ["executable"] = "dotnet",
+ ["args"] = new object[] { "tool", "dsc", "schema" }
+ }
+ },
+ ["get"] = new Dictionary
+ {
+ ["executable"] = "dotnet",
+ ["args"] = new object[]
+ {
+ "tool",
+ "dsc",
+ "get",
+ new Dictionary
+ {
+ ["jsonInputArg"] = "--input",
+ ["mandatory"] = true
+ }
+ }
+ },
+ ["set"] = new Dictionary
+ {
+ ["executable"] = "dotnet",
+ ["args"] = new object[]
+ {
+ "tool",
+ "dsc",
+ "set",
+ new Dictionary
+ {
+ ["jsonInputArg"] = "--input",
+ ["mandatory"] = true
+ }
+ }
+ },
+ ["test"] = new Dictionary
+ {
+ ["executable"] = "dotnet",
+ ["args"] = new object[]
+ {
+ "tool",
+ "dsc",
+ "test",
+ new Dictionary
+ {
+ ["jsonInputArg"] = "--input",
+ ["mandatory"] = true
+ }
+ }
+ },
+ ["export"] = new Dictionary
+ {
+ ["executable"] = "dotnet",
+ ["args"] = new object[] { "tool", "dsc", "export" }
+ }
+ };
+
+ DscWriter.WriteJson(manifest);
+
+ return 0;
+ }
+ catch (Exception ex)
+ {
+ DscWriter.WriteError($"Error generating manifest: {ex.Message}");
+ return 1;
+ }
+ }
+}
diff --git a/src/Cli/dotnet/Commands/Tool/Dsc/ToolDscManifestCommandParser.cs b/src/Cli/dotnet/Commands/Tool/Dsc/ToolDscManifestCommandParser.cs
new file mode 100644
index 000000000000..f597dfe9a3f3
--- /dev/null
+++ b/src/Cli/dotnet/Commands/Tool/Dsc/ToolDscManifestCommandParser.cs
@@ -0,0 +1,25 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.CommandLine;
+
+namespace Microsoft.DotNet.Cli.Commands.Tool.Dsc;
+
+internal static class ToolDscManifestCommandParser
+{
+ private static readonly Command Command = ConstructCommand();
+
+ public static Command GetCommand()
+ {
+ return Command;
+ }
+
+ private static Command ConstructCommand()
+ {
+ Command command = new("manifest", CliCommandStrings.ToolDscManifestCommandDescription);
+
+ command.SetAction((parseResult) => new ToolDscManifestCommand(parseResult).Execute());
+
+ return command;
+ }
+}
diff --git a/src/Cli/dotnet/Commands/Tool/Dsc/ToolDscSchemaCommand.cs b/src/Cli/dotnet/Commands/Tool/Dsc/ToolDscSchemaCommand.cs
new file mode 100644
index 000000000000..6de2f631e07d
--- /dev/null
+++ b/src/Cli/dotnet/Commands/Tool/Dsc/ToolDscSchemaCommand.cs
@@ -0,0 +1,108 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+#nullable disable
+
+using System.CommandLine;
+using System.Reflection;
+using System.Text.Json;
+using System.Text.Json.Serialization;
+using Microsoft.DotNet.Cli.Utils;
+
+namespace Microsoft.DotNet.Cli.Commands.Tool.Dsc;
+
+internal class ToolDscSchemaCommand : CommandBase
+{
+ public ToolDscSchemaCommand(ParseResult parseResult)
+ : base(parseResult)
+ {
+ }
+
+ public override int Execute()
+ {
+ try
+ {
+ // Generate schema dynamically from DscToolState model
+ var toolProperties = new Dictionary();
+ var requiredProperties = new List();
+
+ foreach (var prop in typeof(DscToolState).GetProperties())
+ {
+ var jsonPropertyAttr = prop.GetCustomAttribute();
+ if (jsonPropertyAttr == null) continue;
+
+ string propertyName = jsonPropertyAttr.Name;
+ var propertySchema = GetPropertySchema(prop);
+
+ toolProperties[propertyName] = propertySchema;
+
+ // packageId is required
+ if (propertyName == "packageId")
+ {
+ requiredProperties.Add(propertyName);
+ }
+ }
+
+ var schema = new
+ {
+ type = "object",
+ properties = new
+ {
+ tools = new
+ {
+ type = "array",
+ items = new
+ {
+ type = "object",
+ properties = toolProperties,
+ required = requiredProperties.ToArray()
+ }
+ }
+ }
+ };
+
+ DscWriter.WriteJson(schema, writeIndented: true);
+
+ return 0;
+ }
+ catch (Exception ex)
+ {
+ DscWriter.WriteError($"Unexpected error: {ex.Message}");
+ return 1;
+ }
+ }
+
+ private static object GetPropertySchema(PropertyInfo prop)
+ {
+ var underlyingType = Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType;
+
+ // Check for enum
+ if (underlyingType.IsEnum)
+ {
+ var enumValues = Enum.GetNames(underlyingType);
+ return new { type = "string", @enum = enumValues };
+ }
+
+ // Check for List
+ if (underlyingType.IsGenericType && underlyingType.GetGenericTypeDefinition() == typeof(List<>))
+ {
+ var itemType = underlyingType.GetGenericArguments()[0];
+ if (itemType == typeof(string))
+ {
+ return new { type = "array", items = new { type = "string" } };
+ }
+ }
+
+ // Map CLR types to JSON schema types
+ if (underlyingType == typeof(string))
+ return new { type = "string" };
+ if (underlyingType == typeof(bool))
+ return new { type = "boolean" };
+ if (underlyingType == typeof(int) || underlyingType == typeof(long))
+ return new { type = "integer" };
+ if (underlyingType == typeof(double) || underlyingType == typeof(float))
+ return new { type = "number" };
+
+ return new { type = "string" };
+ }
+}
diff --git a/src/Cli/dotnet/Commands/Tool/Dsc/ToolDscSchemaCommandParser.cs b/src/Cli/dotnet/Commands/Tool/Dsc/ToolDscSchemaCommandParser.cs
new file mode 100644
index 000000000000..3743cb502f23
--- /dev/null
+++ b/src/Cli/dotnet/Commands/Tool/Dsc/ToolDscSchemaCommandParser.cs
@@ -0,0 +1,25 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.CommandLine;
+
+namespace Microsoft.DotNet.Cli.Commands.Tool.Dsc;
+
+internal static class ToolDscSchemaCommandParser
+{
+ private static readonly Command Command = ConstructCommand();
+
+ public static Command GetCommand()
+ {
+ return Command;
+ }
+
+ private static Command ConstructCommand()
+ {
+ Command command = new("schema", CliCommandStrings.ToolDscSchemaCommandDescription);
+
+ command.SetAction((parseResult) => new ToolDscSchemaCommand(parseResult).Execute());
+
+ return command;
+ }
+}
diff --git a/src/Cli/dotnet/Commands/Tool/Dsc/ToolDscSetCommand.cs b/src/Cli/dotnet/Commands/Tool/Dsc/ToolDscSetCommand.cs
new file mode 100644
index 000000000000..31848e5b3fb1
--- /dev/null
+++ b/src/Cli/dotnet/Commands/Tool/Dsc/ToolDscSetCommand.cs
@@ -0,0 +1,118 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+#nullable disable
+
+using System.CommandLine;
+using System.Text.Json;
+using Microsoft.DotNet.Cli.Commands.Tool.Install;
+using Microsoft.DotNet.Cli.ToolPackage;
+using Microsoft.DotNet.Cli.Utils;
+using Microsoft.Extensions.EnvironmentAbstractions;
+using NuGet.Versioning;
+
+namespace Microsoft.DotNet.Cli.Commands.Tool.Dsc;
+
+internal class ToolDscSetCommand : CommandBase
+{
+ private readonly string _input;
+
+ public ToolDscSetCommand(ParseResult parseResult)
+ : base(parseResult)
+ {
+ _input = parseResult.GetValue(ToolDscSetCommandParser.InputOption);
+ }
+
+ public override int Execute()
+ {
+ try
+ {
+ var inputState = DscWriter.ReadAndDeserializeInput(_input);
+ var resultState = new DscToolsState();
+ bool hasFailures = false;
+
+ foreach (var tool in inputState?.Tools ?? Enumerable.Empty())
+ {
+ // Skip tools that should not exist (Exist == false)
+ if (tool.Exist == false)
+ {
+ DscWriter.WriteDebug($"Skipping tool {tool.PackageId}: _exist is false (tool removal not supported)");
+ continue;
+ }
+
+ // Only support Global scope for now
+ var scope = tool.Scope ?? DscToolScope.Global;
+ if (scope != DscToolScope.Global)
+ {
+ DscWriter.WriteDebug($"Skipping tool {tool.PackageId}: only Global scope is currently supported");
+ continue;
+ }
+
+ DscWriter.WriteDebug($"Setting desired state for tool: {tool.PackageId}");
+
+ // Parse packageId and version
+ var (packageId, versionRange) = tool.ParsePackageIdentity();
+
+ if (string.IsNullOrEmpty(packageId))
+ {
+ DscWriter.WriteError($"Invalid packageId: {tool.PackageId}");
+ continue;
+ }
+
+ // Install or update the tool
+ try
+ {
+ string installArgs = $"tool install -g {packageId}";
+ if (versionRange != null)
+ {
+ installArgs += $" --version \"{versionRange.OriginalString}\"";
+ }
+
+ var installParseResult = Parser.Parse($"dotnet {installArgs}");
+
+ var installCommand = new ToolInstallGlobalOrToolPathCommand(
+ installParseResult,
+ packageId: new PackageId(packageId),
+ createToolPackageStoreDownloaderUninstaller: null,
+ createShellShimRepository: null,
+ environmentPathInstruction: null,
+ reporter: null);
+
+ int exitCode = installCommand.Execute();
+
+ if (exitCode != 0)
+ {
+ DscWriter.WriteError($"Failed to install/update tool {packageId}");
+ hasFailures = true;
+ continue;
+ }
+
+ DscWriter.WriteDebug($"Tool {packageId} is at desired state");
+ }
+ catch (Exception ex)
+ {
+ DscWriter.WriteError($"Error installing/updating tool {packageId}: {ex.Message}");
+ hasFailures = true;
+ continue;
+ }
+
+ // Query final state after installation
+ var finalState = DscWriter.QueryToolState(new DscToolState
+ {
+ PackageId = packageId,
+ Scope = scope
+ });
+
+ resultState.Tools.Add(finalState);
+ }
+
+ DscWriter.WriteResult(resultState);
+ return hasFailures ? 1 : 0;
+ }
+ catch (Exception ex)
+ {
+ DscWriter.WriteError($"Unexpected error: {ex.Message}");
+ return 1;
+ }
+ }
+}
diff --git a/src/Cli/dotnet/Commands/Tool/Dsc/ToolDscSetCommandParser.cs b/src/Cli/dotnet/Commands/Tool/Dsc/ToolDscSetCommandParser.cs
new file mode 100644
index 000000000000..6ae4331d9444
--- /dev/null
+++ b/src/Cli/dotnet/Commands/Tool/Dsc/ToolDscSetCommandParser.cs
@@ -0,0 +1,33 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.CommandLine;
+using Microsoft.DotNet.Cli.Extensions;
+
+namespace Microsoft.DotNet.Cli.Commands.Tool.Dsc;
+
+internal static class ToolDscSetCommandParser
+{
+ public static readonly Option InputOption = new("--input", "-i")
+ {
+ Description = CliCommandStrings.ToolDscInputOptionDescription,
+ HelpName = CliCommandStrings.ToolDscInputOptionName
+ };
+
+ private static readonly Command Command = ConstructCommand();
+
+ public static Command GetCommand()
+ {
+ return Command;
+ }
+
+ private static Command ConstructCommand()
+ {
+ Command command = new("set", CliCommandStrings.ToolDscSetCommandDescription);
+ command.Options.Add(InputOption);
+
+ command.SetAction((parseResult) => new ToolDscSetCommand(parseResult).Execute());
+
+ return command;
+ }
+}
diff --git a/src/Cli/dotnet/Commands/Tool/Dsc/ToolDscTestCommand.cs b/src/Cli/dotnet/Commands/Tool/Dsc/ToolDscTestCommand.cs
new file mode 100644
index 000000000000..741fa5378dee
--- /dev/null
+++ b/src/Cli/dotnet/Commands/Tool/Dsc/ToolDscTestCommand.cs
@@ -0,0 +1,172 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+#nullable disable
+
+using System.CommandLine;
+using System.Text.Json;
+using Microsoft.DotNet.Cli.Utils;
+using NuGet.Versioning;
+
+namespace Microsoft.DotNet.Cli.Commands.Tool.Dsc;
+
+internal class ToolDscTestCommand : CommandBase
+{
+ private readonly string _input;
+
+ public ToolDscTestCommand(ParseResult parseResult)
+ : base(parseResult)
+ {
+ _input = parseResult.GetValue(ToolDscTestCommandParser.InputOption);
+ }
+
+ public override int Execute()
+ {
+ try
+ {
+ var inputState = DscWriter.ReadAndDeserializeInput(_input);
+ var resultState = new DscToolsState();
+ bool allMatch = true;
+
+ foreach (var tool in inputState?.Tools ?? Enumerable.Empty())
+ {
+ var actualState = DscWriter.QueryToolState(tool);
+ bool matches = CompareToolStates(tool, actualState);
+
+ actualState.Exist = matches;
+
+ if (!matches)
+ {
+ allMatch = false;
+ }
+
+ resultState.Tools.Add(actualState);
+ }
+
+ DscWriter.WriteResult(resultState);
+
+ // Return exit code 0 if all tools match desired state, 1 if any don't match
+ return allMatch ? 0 : 1;
+ }
+ catch (Exception ex)
+ {
+ DscWriter.WriteError($"Unexpected error: {ex.Message}");
+ return 1;
+ }
+ }
+
+ ///
+ /// Compares desired state with actual state to determine if they match.
+ ///
+ private bool CompareToolStates(DscToolState desired, DscToolState actual)
+ {
+ // Parse packageId to handle packageId@version syntax
+ var (packageId, versionRange) = desired.ParsePackageIdentity();
+
+ // Check _exist property first
+ bool desiredExist = desired.Exist ?? true; // Default to true if not specified
+ bool actualExist = actual.Exist ?? false;
+
+ if (desiredExist != actualExist)
+ {
+ DscWriter.WriteDebug($"Tool {packageId}: Exist mismatch (desired: {desiredExist}, actual: {actualExist})");
+ return false;
+ }
+
+ // If tool should not exist and doesn't exist, that's a match
+ if (!desiredExist && !actualExist)
+ {
+ DscWriter.WriteDebug($"Tool {packageId}: Correctly does not exist");
+ return true;
+ }
+
+ // If tool should exist but doesn't, already caught above
+ // Now check version if specified
+ if (versionRange != null)
+ {
+ // packageId@version syntax or Version property specified
+ if (string.IsNullOrEmpty(actual.Version))
+ {
+ DscWriter.WriteDebug($"Tool {packageId}: Version mismatch (desired: {versionRange.OriginalString}, actual: none)");
+ return false;
+ }
+
+ // Check if actual version satisfies the version range
+ if (NuGetVersion.TryParse(actual.Version, out var actualVersion))
+ {
+ if (!versionRange.Satisfies(actualVersion))
+ {
+ DscWriter.WriteDebug($"Tool {packageId}: Version mismatch (desired: {versionRange.OriginalString}, actual: {actual.Version})");
+ return false;
+ }
+ }
+ else
+ {
+ DscWriter.WriteDebug($"Tool {packageId}: Failed to parse actual version {actual.Version}");
+ return false;
+ }
+ }
+ else if (!string.IsNullOrEmpty(desired.Version))
+ {
+ // Fallback to string comparison for Version property (shouldn't happen if ParsePackageIdentity works)
+ if (string.IsNullOrEmpty(actual.Version))
+ {
+ DscWriter.WriteDebug($"Tool {packageId}: Version mismatch (desired: {desired.Version}, actual: none)");
+ return false;
+ }
+
+ if (NuGetVersion.TryParse(desired.Version, out var desiredVersion) &&
+ NuGetVersion.TryParse(actual.Version, out var actualVersion))
+ {
+ if (!desiredVersion.Equals(actualVersion))
+ {
+ DscWriter.WriteDebug($"Tool {packageId}: Version mismatch (desired: {desired.Version}, actual: {actual.Version})");
+ return false;
+ }
+ }
+ else if (!string.Equals(desired.Version, actual.Version, StringComparison.OrdinalIgnoreCase))
+ {
+ DscWriter.WriteDebug($"Tool {packageId}: Version mismatch (desired: {desired.Version}, actual: {actual.Version})");
+ return false;
+ }
+ }
+
+ // Check commands if specified
+ if (desired.Commands != null && desired.Commands.Any())
+ {
+ if (actual.Commands == null || !actual.Commands.Any())
+ {
+ DscWriter.WriteDebug($"Tool {desired.PackageId}: Commands mismatch (desired commands specified, actual: none)");
+ return false;
+ }
+
+ // Check if all desired commands are present in actual
+ var missingCommands = desired.Commands.Except(actual.Commands, StringComparer.OrdinalIgnoreCase).ToList();
+ if (missingCommands.Any())
+ {
+ DscWriter.WriteDebug($"Tool {desired.PackageId}: Missing commands: {string.Join(", ", missingCommands)}");
+ return false;
+ }
+ }
+
+ // Check scope if specified
+ if (desired.Scope.HasValue && actual.Scope.HasValue)
+ {
+ if (desired.Scope.Value != actual.Scope.Value)
+ {
+ DscWriter.WriteDebug($"Tool {desired.PackageId}: Scope mismatch (desired: {desired.Scope.Value}, actual: {actual.Scope.Value})");
+ return false;
+ }
+ }
+
+ if (!string.IsNullOrEmpty(desired.ToolPath) && !string.IsNullOrEmpty(actual.ToolPath))
+ {
+ if (!string.Equals(desired.ToolPath, actual.ToolPath, StringComparison.OrdinalIgnoreCase))
+ {
+ DscWriter.WriteDebug($"Tool {desired.PackageId}: ToolPath mismatch (desired: {desired.ToolPath}, actual: {actual.ToolPath})");
+ return false;
+ }
+ }
+ return true;
+ }
+}
diff --git a/src/Cli/dotnet/Commands/Tool/Dsc/ToolDscTestCommandParser.cs b/src/Cli/dotnet/Commands/Tool/Dsc/ToolDscTestCommandParser.cs
new file mode 100644
index 000000000000..572e73b4abc2
--- /dev/null
+++ b/src/Cli/dotnet/Commands/Tool/Dsc/ToolDscTestCommandParser.cs
@@ -0,0 +1,33 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.CommandLine;
+using Microsoft.DotNet.Cli.Extensions;
+
+namespace Microsoft.DotNet.Cli.Commands.Tool.Dsc;
+
+internal static class ToolDscTestCommandParser
+{
+ public static readonly Option InputOption = new("--input", "-i")
+ {
+ Description = CliCommandStrings.ToolDscInputOptionDescription,
+ HelpName = CliCommandStrings.ToolDscInputOptionName
+ };
+
+ private static readonly Command Command = ConstructCommand();
+
+ public static Command GetCommand()
+ {
+ return Command;
+ }
+
+ private static Command ConstructCommand()
+ {
+ Command command = new("test", CliCommandStrings.ToolDscTestCommandDescription);
+ command.Options.Add(InputOption);
+
+ command.SetAction((parseResult) => new ToolDscTestCommand(parseResult).Execute());
+
+ return command;
+ }
+}
diff --git a/src/Cli/dotnet/Commands/Tool/ToolCommandParser.cs b/src/Cli/dotnet/Commands/Tool/ToolCommandParser.cs
index 0392bde15d3f..b0e93ef1a58d 100644
--- a/src/Cli/dotnet/Commands/Tool/ToolCommandParser.cs
+++ b/src/Cli/dotnet/Commands/Tool/ToolCommandParser.cs
@@ -4,6 +4,7 @@
#nullable disable
using System.CommandLine;
+using Microsoft.DotNet.Cli.Commands.Tool.Dsc;
using Microsoft.DotNet.Cli.Commands.Tool.Execute;
using Microsoft.DotNet.Cli.Commands.Tool.Install;
using Microsoft.DotNet.Cli.Commands.Tool.List;
@@ -39,6 +40,7 @@ private static Command ConstructCommand()
command.Subcommands.Add(ToolSearchCommandParser.GetCommand());
command.Subcommands.Add(ToolRestoreCommandParser.GetCommand());
command.Subcommands.Add(ToolExecuteCommandParser.GetCommand());
+ command.Subcommands.Add(ToolDscCommandParser.GetCommand());
command.SetAction((parseResult) => parseResult.HandleMissingCommand());
diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.cs.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.cs.xlf
index d1d8709624e6..ef306e017851 100644
--- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.cs.xlf
+++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.cs.xlf
@@ -3218,6 +3218,51 @@ Chcete pokračovat?
Stažení balíčku nástroje vyžaduje potvrzení. Spusťte v interaktivním režimu nebo potvrďte akci pomocí možnosti příkazového řádku --yes.{Locked="--yes"}
+
+ Manage tools using Microsoft Desired State Configuration (DSC).
+ Manage tools using Microsoft Desired State Configuration (DSC).
+
+
+
+ Export the current state of all installed tools.
+ Export the current state of all installed tools.
+
+
+
+ Get the current state of installed tools.
+ Get the current state of installed tools.
+
+
+
+ JSON input representing the desired or requested tool state.
+ JSON input representing the desired or requested tool state.
+
+
+
+ JSON
+ JSON
+
+
+
+ Get the Microsoft Desired State Configuration (DSC) resource manifest for dotnet tool.
+ Get the Microsoft Desired State Configuration (DSC) resource manifest for dotnet tool.
+
+
+
+ Get the JSON schema for DSC tool state.
+ Get the JSON schema for DSC tool state.
+
+
+
+ Set the desired state of tools by installing or updating them.
+ Set the desired state of tools by installing or updating them.
+
+
+
+ Test if the current state matches the desired state.
+ Test if the current state matches the desired state.
+
+ Executes a tool from source without permanently installing it.Spustí nástroj ze zdroje bez trvalé instalace.
diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.de.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.de.xlf
index 2a39befb9d3c..c24bfaf3c3f9 100644
--- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.de.xlf
+++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.de.xlf
@@ -3218,6 +3218,51 @@ Vorgang fortsetzen?
Der Download des Toolpakets muss bestätigt werden. Führen Sie den Vorgang im interaktiven Modus aus oder verwenden Sie zur Bestätigung die Befehlszeilenoption "--yes".{Locked="--yes"}
+
+ Manage tools using Microsoft Desired State Configuration (DSC).
+ Manage tools using Microsoft Desired State Configuration (DSC).
+
+
+
+ Export the current state of all installed tools.
+ Export the current state of all installed tools.
+
+
+
+ Get the current state of installed tools.
+ Get the current state of installed tools.
+
+
+
+ JSON input representing the desired or requested tool state.
+ JSON input representing the desired or requested tool state.
+
+
+
+ JSON
+ JSON
+
+
+
+ Get the Microsoft Desired State Configuration (DSC) resource manifest for dotnet tool.
+ Get the Microsoft Desired State Configuration (DSC) resource manifest for dotnet tool.
+
+
+
+ Get the JSON schema for DSC tool state.
+ Get the JSON schema for DSC tool state.
+
+
+
+ Set the desired state of tools by installing or updating them.
+ Set the desired state of tools by installing or updating them.
+
+
+
+ Test if the current state matches the desired state.
+ Test if the current state matches the desired state.
+
+ Executes a tool from source without permanently installing it.Führt ein Tool aus der Quelle aus, ohne es dauerhaft zu installieren.
diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.es.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.es.xlf
index 84f4aabb9069..353f5071c26c 100644
--- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.es.xlf
+++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.es.xlf
@@ -3218,6 +3218,51 @@ Proceed?
La descarga del paquete de herramientas necesita confirmación. Ejecute en modo interactivo o use la opción de línea de comandos "--yes" para confirmar.{Locked="--yes"}
+
+ Manage tools using Microsoft Desired State Configuration (DSC).
+ Manage tools using Microsoft Desired State Configuration (DSC).
+
+
+
+ Export the current state of all installed tools.
+ Export the current state of all installed tools.
+
+
+
+ Get the current state of installed tools.
+ Get the current state of installed tools.
+
+
+
+ JSON input representing the desired or requested tool state.
+ JSON input representing the desired or requested tool state.
+
+
+
+ JSON
+ JSON
+
+
+
+ Get the Microsoft Desired State Configuration (DSC) resource manifest for dotnet tool.
+ Get the Microsoft Desired State Configuration (DSC) resource manifest for dotnet tool.
+
+
+
+ Get the JSON schema for DSC tool state.
+ Get the JSON schema for DSC tool state.
+
+
+
+ Set the desired state of tools by installing or updating them.
+ Set the desired state of tools by installing or updating them.
+
+
+
+ Test if the current state matches the desired state.
+ Test if the current state matches the desired state.
+
+ Executes a tool from source without permanently installing it.Ejecuta una herramienta desde el origen sin instalarla permanentemente.
diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.fr.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.fr.xlf
index 6a637323a60e..3935070ab2a8 100644
--- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.fr.xlf
+++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.fr.xlf
@@ -3218,6 +3218,51 @@ Voulez-vous continuer ?
Le téléchargement du package d’outils doit être confirmé. Exécutez en mode interactif ou utilisez l’option de ligne de commande « --yes » pour confirmer.{Locked="--yes"}
+
+ Manage tools using Microsoft Desired State Configuration (DSC).
+ Manage tools using Microsoft Desired State Configuration (DSC).
+
+
+
+ Export the current state of all installed tools.
+ Export the current state of all installed tools.
+
+
+
+ Get the current state of installed tools.
+ Get the current state of installed tools.
+
+
+
+ JSON input representing the desired or requested tool state.
+ JSON input representing the desired or requested tool state.
+
+
+
+ JSON
+ JSON
+
+
+
+ Get the Microsoft Desired State Configuration (DSC) resource manifest for dotnet tool.
+ Get the Microsoft Desired State Configuration (DSC) resource manifest for dotnet tool.
+
+
+
+ Get the JSON schema for DSC tool state.
+ Get the JSON schema for DSC tool state.
+
+
+
+ Set the desired state of tools by installing or updating them.
+ Set the desired state of tools by installing or updating them.
+
+
+
+ Test if the current state matches the desired state.
+ Test if the current state matches the desired state.
+
+ Executes a tool from source without permanently installing it.Exécute un outil à partir de la source sans l’installer définitivement.
diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.it.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.it.xlf
index 1f255f43c794..050cc5eb7117 100644
--- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.it.xlf
+++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.it.xlf
@@ -3218,6 +3218,51 @@ Procedere?
Il download del pacchetto dello strumento richiede conferma. Esegui in modalità interattiva o usa l'opzione della riga di comando "--yes" per confermare.{Locked="--yes"}
+
+ Manage tools using Microsoft Desired State Configuration (DSC).
+ Manage tools using Microsoft Desired State Configuration (DSC).
+
+
+
+ Export the current state of all installed tools.
+ Export the current state of all installed tools.
+
+
+
+ Get the current state of installed tools.
+ Get the current state of installed tools.
+
+
+
+ JSON input representing the desired or requested tool state.
+ JSON input representing the desired or requested tool state.
+
+
+
+ JSON
+ JSON
+
+
+
+ Get the Microsoft Desired State Configuration (DSC) resource manifest for dotnet tool.
+ Get the Microsoft Desired State Configuration (DSC) resource manifest for dotnet tool.
+
+
+
+ Get the JSON schema for DSC tool state.
+ Get the JSON schema for DSC tool state.
+
+
+
+ Set the desired state of tools by installing or updating them.
+ Set the desired state of tools by installing or updating them.
+
+
+
+ Test if the current state matches the desired state.
+ Test if the current state matches the desired state.
+
+ Executes a tool from source without permanently installing it.Esegue uno strumento dall'origine senza installarlo permanentemente.
diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ja.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ja.xlf
index 7aa8108b6954..1a4b8d6972e8 100644
--- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ja.xlf
+++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ja.xlf
@@ -3218,6 +3218,51 @@ Proceed?
ツール パッケージのダウンロードには確認が必要です。対話モードで実行するか、"--yes" コマンド ライン オプションを使用して確認してください。{Locked="--yes"}
+
+ Manage tools using Microsoft Desired State Configuration (DSC).
+ Manage tools using Microsoft Desired State Configuration (DSC).
+
+
+
+ Export the current state of all installed tools.
+ Export the current state of all installed tools.
+
+
+
+ Get the current state of installed tools.
+ Get the current state of installed tools.
+
+
+
+ JSON input representing the desired or requested tool state.
+ JSON input representing the desired or requested tool state.
+
+
+
+ JSON
+ JSON
+
+
+
+ Get the Microsoft Desired State Configuration (DSC) resource manifest for dotnet tool.
+ Get the Microsoft Desired State Configuration (DSC) resource manifest for dotnet tool.
+
+
+
+ Get the JSON schema for DSC tool state.
+ Get the JSON schema for DSC tool state.
+
+
+
+ Set the desired state of tools by installing or updating them.
+ Set the desired state of tools by installing or updating them.
+
+
+
+ Test if the current state matches the desired state.
+ Test if the current state matches the desired state.
+
+ Executes a tool from source without permanently installing it.ツールを永続的にインストールすることなく、ソースから実行します。
diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ko.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ko.xlf
index 6544ed0d7051..98c3a6edc685 100644
--- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ko.xlf
+++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ko.xlf
@@ -3218,6 +3218,51 @@ Proceed?
도구 패키지 다운로드를 확인해야 합니다. 대화형 모드에서 실행하거나 "--yes" 명령줄 옵션을 사용하여 확인하세요.{Locked="--yes"}
+
+ Manage tools using Microsoft Desired State Configuration (DSC).
+ Manage tools using Microsoft Desired State Configuration (DSC).
+
+
+
+ Export the current state of all installed tools.
+ Export the current state of all installed tools.
+
+
+
+ Get the current state of installed tools.
+ Get the current state of installed tools.
+
+
+
+ JSON input representing the desired or requested tool state.
+ JSON input representing the desired or requested tool state.
+
+
+
+ JSON
+ JSON
+
+
+
+ Get the Microsoft Desired State Configuration (DSC) resource manifest for dotnet tool.
+ Get the Microsoft Desired State Configuration (DSC) resource manifest for dotnet tool.
+
+
+
+ Get the JSON schema for DSC tool state.
+ Get the JSON schema for DSC tool state.
+
+
+
+ Set the desired state of tools by installing or updating them.
+ Set the desired state of tools by installing or updating them.
+
+
+
+ Test if the current state matches the desired state.
+ Test if the current state matches the desired state.
+
+ Executes a tool from source without permanently installing it.영구적으로 설치하지 않고 원본에서 도구를 실행합니다.
diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.pl.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.pl.xlf
index 6e7de9021244..8aace083331a 100644
--- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.pl.xlf
+++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.pl.xlf
@@ -3218,6 +3218,51 @@ Kontynuować?
Pobieranie pakietu narzędzi wymaga potwierdzenia. Uruchom w trybie interakcyjnym lub użyj opcji wiersza polecenia „--yes”, aby potwierdzić.{Locked="--yes"}
+
+ Manage tools using Microsoft Desired State Configuration (DSC).
+ Manage tools using Microsoft Desired State Configuration (DSC).
+
+
+
+ Export the current state of all installed tools.
+ Export the current state of all installed tools.
+
+
+
+ Get the current state of installed tools.
+ Get the current state of installed tools.
+
+
+
+ JSON input representing the desired or requested tool state.
+ JSON input representing the desired or requested tool state.
+
+
+
+ JSON
+ JSON
+
+
+
+ Get the Microsoft Desired State Configuration (DSC) resource manifest for dotnet tool.
+ Get the Microsoft Desired State Configuration (DSC) resource manifest for dotnet tool.
+
+
+
+ Get the JSON schema for DSC tool state.
+ Get the JSON schema for DSC tool state.
+
+
+
+ Set the desired state of tools by installing or updating them.
+ Set the desired state of tools by installing or updating them.
+
+
+
+ Test if the current state matches the desired state.
+ Test if the current state matches the desired state.
+
+ Executes a tool from source without permanently installing it.Wykonuje narzędzie ze źródła bez trwałego instalowania go.
diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.pt-BR.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.pt-BR.xlf
index 032d2caf149f..8813374a1da0 100644
--- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.pt-BR.xlf
+++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.pt-BR.xlf
@@ -3218,6 +3218,51 @@ Continuar?
O download do pacote de ferramentas precisa de confirmação. Execute no modo interativo ou use a opção de linha de comando "--yes" para confirmar.{Locked="--yes"}
+
+ Manage tools using Microsoft Desired State Configuration (DSC).
+ Manage tools using Microsoft Desired State Configuration (DSC).
+
+
+
+ Export the current state of all installed tools.
+ Export the current state of all installed tools.
+
+
+
+ Get the current state of installed tools.
+ Get the current state of installed tools.
+
+
+
+ JSON input representing the desired or requested tool state.
+ JSON input representing the desired or requested tool state.
+
+
+
+ JSON
+ JSON
+
+
+
+ Get the Microsoft Desired State Configuration (DSC) resource manifest for dotnet tool.
+ Get the Microsoft Desired State Configuration (DSC) resource manifest for dotnet tool.
+
+
+
+ Get the JSON schema for DSC tool state.
+ Get the JSON schema for DSC tool state.
+
+
+
+ Set the desired state of tools by installing or updating them.
+ Set the desired state of tools by installing or updating them.
+
+
+
+ Test if the current state matches the desired state.
+ Test if the current state matches the desired state.
+
+ Executes a tool from source without permanently installing it.Executa uma ferramenta da origem sem instalá-la permanentemente.
diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ru.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ru.xlf
index 05edfdd693ef..1d0d54365e3e 100644
--- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ru.xlf
+++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ru.xlf
@@ -3218,6 +3218,51 @@ Proceed?
Для скачивания пакета инструмента требуется подтверждение. Запустите в интерактивном режиме или используйте параметр командной строки "--yes" для подтверждения.{Locked="--yes"}
+
+ Manage tools using Microsoft Desired State Configuration (DSC).
+ Manage tools using Microsoft Desired State Configuration (DSC).
+
+
+
+ Export the current state of all installed tools.
+ Export the current state of all installed tools.
+
+
+
+ Get the current state of installed tools.
+ Get the current state of installed tools.
+
+
+
+ JSON input representing the desired or requested tool state.
+ JSON input representing the desired or requested tool state.
+
+
+
+ JSON
+ JSON
+
+
+
+ Get the Microsoft Desired State Configuration (DSC) resource manifest for dotnet tool.
+ Get the Microsoft Desired State Configuration (DSC) resource manifest for dotnet tool.
+
+
+
+ Get the JSON schema for DSC tool state.
+ Get the JSON schema for DSC tool state.
+
+
+
+ Set the desired state of tools by installing or updating them.
+ Set the desired state of tools by installing or updating them.
+
+
+
+ Test if the current state matches the desired state.
+ Test if the current state matches the desired state.
+
+ Executes a tool from source without permanently installing it.Выполняет инструмент из источника без его постоянной установки.
diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.tr.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.tr.xlf
index 228d3a11bd02..a0c8dac403a0 100644
--- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.tr.xlf
+++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.tr.xlf
@@ -3218,6 +3218,51 @@ Devam edilsin mi?
Araç paketinin indirilmesi için onay gerekiyor. Etkileşimli modda çalıştırın veya onaylamak için "--yes" komut satırı seçeneğini kullanın.{Locked="--yes"}
+
+ Manage tools using Microsoft Desired State Configuration (DSC).
+ Manage tools using Microsoft Desired State Configuration (DSC).
+
+
+
+ Export the current state of all installed tools.
+ Export the current state of all installed tools.
+
+
+
+ Get the current state of installed tools.
+ Get the current state of installed tools.
+
+
+
+ JSON input representing the desired or requested tool state.
+ JSON input representing the desired or requested tool state.
+
+
+
+ JSON
+ JSON
+
+
+
+ Get the Microsoft Desired State Configuration (DSC) resource manifest for dotnet tool.
+ Get the Microsoft Desired State Configuration (DSC) resource manifest for dotnet tool.
+
+
+
+ Get the JSON schema for DSC tool state.
+ Get the JSON schema for DSC tool state.
+
+
+
+ Set the desired state of tools by installing or updating them.
+ Set the desired state of tools by installing or updating them.
+
+
+
+ Test if the current state matches the desired state.
+ Test if the current state matches the desired state.
+
+ Executes a tool from source without permanently installing it.Aracı kalıcı olarak yüklemeden kaynaktan yürütür.
diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.zh-Hans.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.zh-Hans.xlf
index 8dce87da752d..5215b467d3ea 100644
--- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.zh-Hans.xlf
+++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.zh-Hans.xlf
@@ -3218,6 +3218,51 @@ Proceed?
工具包下载需要确认。在交互模式下运行,或使用 “--yes” 命令行选项进行确认。{Locked="--yes"}
+
+ Manage tools using Microsoft Desired State Configuration (DSC).
+ Manage tools using Microsoft Desired State Configuration (DSC).
+
+
+
+ Export the current state of all installed tools.
+ Export the current state of all installed tools.
+
+
+
+ Get the current state of installed tools.
+ Get the current state of installed tools.
+
+
+
+ JSON input representing the desired or requested tool state.
+ JSON input representing the desired or requested tool state.
+
+
+
+ JSON
+ JSON
+
+
+
+ Get the Microsoft Desired State Configuration (DSC) resource manifest for dotnet tool.
+ Get the Microsoft Desired State Configuration (DSC) resource manifest for dotnet tool.
+
+
+
+ Get the JSON schema for DSC tool state.
+ Get the JSON schema for DSC tool state.
+
+
+
+ Set the desired state of tools by installing or updating them.
+ Set the desired state of tools by installing or updating them.
+
+
+
+ Test if the current state matches the desired state.
+ Test if the current state matches the desired state.
+
+ Executes a tool from source without permanently installing it.从源执行工具,而无需永久安装它。
diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.zh-Hant.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.zh-Hant.xlf
index 4402fa7bc229..d0cb397abbb9 100644
--- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.zh-Hant.xlf
+++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.zh-Hant.xlf
@@ -3218,6 +3218,51 @@ Proceed?
工具套件下載需要確認。請以互動模式執行,或使用 "--yes" 命令列選項來確認。{Locked="--yes"}
+
+ Manage tools using Microsoft Desired State Configuration (DSC).
+ Manage tools using Microsoft Desired State Configuration (DSC).
+
+
+
+ Export the current state of all installed tools.
+ Export the current state of all installed tools.
+
+
+
+ Get the current state of installed tools.
+ Get the current state of installed tools.
+
+
+
+ JSON input representing the desired or requested tool state.
+ JSON input representing the desired or requested tool state.
+
+
+
+ JSON
+ JSON
+
+
+
+ Get the Microsoft Desired State Configuration (DSC) resource manifest for dotnet tool.
+ Get the Microsoft Desired State Configuration (DSC) resource manifest for dotnet tool.
+
+
+
+ Get the JSON schema for DSC tool state.
+ Get the JSON schema for DSC tool state.
+
+
+
+ Set the desired state of tools by installing or updating them.
+ Set the desired state of tools by installing or updating them.
+
+
+
+ Test if the current state matches the desired state.
+ Test if the current state matches the desired state.
+
+ Executes a tool from source without permanently installing it.從來源執行工具,但不永久性地安裝。
diff --git a/src/Cli/dotnet/dotnet.csproj b/src/Cli/dotnet/dotnet.csproj
index 2e63f9a3c5a8..9a45aeb11d75 100644
--- a/src/Cli/dotnet/dotnet.csproj
+++ b/src/Cli/dotnet/dotnet.csproj
@@ -107,4 +107,17 @@
OverwriteReadOnlyFiles="true" />
+
+
+
+ $(TargetName).dsc.resource.json
+ $(RepoRoot).dotnet\dotnet$([System.IO.Path]::GetExtension('$(DotnetToolCommand)'))
+
+
+
+
+
+
+