C# interactive build automation system makes it easy to build .NET projects. It can be part of your solution as a regular .NET console project or run C# scripts without compiling them, or even run in REPL mode - allowing you to run C# interactively.
✔️ Three Integrated Execution Modes
- Flexible interoperability between modes (#operating-modes) to adapt to diverse workflow requirements.
✔️ Native Cross-Platform Support
- Seamlessly operates on Windows, Linux, and macOS without compatibility compromises.
✔️ Integrated Debugging Capabilities
- Debug ".NET build projects" directly to identify and resolve issues during compilation and builds.
✔️ Zero Abstraction Overhead
- Eliminates restrictive constructs (e.g., Tasks/Targets):
- Pure .NET codebase – no proprietary syntax or hidden layers
- Industry-standard practices ensure long-term maintainability
✔️ Granular Build Control API
- Precise management of builds, tests, and deployments with streamlined project configuration.
✔️ Consolidated Build Analytics
- Actionable insights through summarized statistics.
.NET build project
Seamless integration into existing solutions as a standard .NET console project.
- Create the Project
Initialize a new console application using .NET CLI:
dotnet new console -n MyBuildApp
cd MyConsoleApp- Add a reference to the Build automation library for .NET
Add the CSharpInteractive NuGet package for scripting capabilities:
dotnet add package CSharpInteractive
- Install the Template
First, install theCSharpInteractive.TemplatesNuGet package as a dotnet template:
dotnet new install CSharpInteractive.Templates
- Generate the Project
Create a new project named Build using the template:
dotnet new build -o ./Build
The generated project supports two run methods:
- Compiled Application (via
Program.cs):dotnet run --project ./Build
- Script Execution (via
Program.csx):dotnet csi ./Build
Running C# script
Direct execution of C# scripts without prior compilation:
- Zero-Compilation Workflow - execute .csx files directly using Roslyn scripting engines, bypassing traditional dotnet build steps for rapid iteration.
- Cross-Platform Scripting
- Windows - integrate with PowerShell/PowerShell Core automation pipelines
- Linux/macOS - combine with bash/zsh scripts via shebang directives (#!/usr/bin/env dotnet-script)
- Dependency Management - resolve NuGet packages in scripts via #r "nuget: PackageName/Version" syntax, with local cache optimization.
Run a specified script with a given argument:
dotnet csi ./MyDirectory/hello.csx World
Run a single script located in the MyDirectory directory:
dotnet csi ./MyDirectory World
Usage details
dotnet csi [options] [--] [script] [script arguments]
Executes a script if specified, otherwise launches an interactive REPL (Read Eval Print Loop).
-- - Indicates that the remaining arguments should not be treated as options.
script - The path to the script file to run. If no such file is found, the command will treat it as a directory and look for a single script file inside that directory.
script arguments - Script arguments are accessible in a script via the global list Args[index] by an argument index.
@file - Read the response file for more options.
Supported options:
| Option | Description | Alternative form |
|---|---|---|
| --help | Show how to use the command. | /?, -h, /h, /help |
| --version | Display the tool version. | /version |
| --source | Specify the NuGet package source to use. Supported formats: URL, or a UNC directory path. | -s, /s, /source |
| --property <key=value> | Define a key-value pair(s) for the script properties called Props, which is accessible in scripts. | -p, /property, /p |
| --property:<key=value> | Define a key-value pair(s) in MSBuild style for the script properties called Props, which is accessible in scripts. | -p:<key=value>, /property:<key=value>, /p:<key=value>, --property:key1=val1;key2=val2 |
Interactive
REPL (Read-Eval-Print-Loop) interface for interactive code evaluation. Please see this page for installation details.
Launch the tool in the interactive mode:
dotnet csi
Simply enter C# commands sequentially one line after another and get the result in console output.
- Build project example
- CSharp Interactive build project
- Pure.DI build project
- Immutype build project
- Comparison with Cake and Nuke
- Output, logging and tracing
- Writing a line to a build log
- Writing a line highlighted with "Header" color to a build log
- Writing an empty line to a build log
- Registering errors in the build log
- Registering warnings in the build log
- Registering a summary in the build log
- Registering information in the build log
- Registering trace information in the build log
- Arguments and parameters
- Microsoft DI
- NuGet
- Command Line
- Docker CLI
- .NET CLI
- Adding a NuGet package
- Adding a NuGet source
- Adding a project reference
- Adding projects to the solution file
- Adding project-to-project (P2P) references
- Building a project
- Building a project using MSBuild
- Cleaning a project
- Clearing the specified NuGet cache type
- Creating a new project, configuration file, or solution based on the specified template
- Deleting a NuGet package to the server
- Disabling a NuGet source
- Displaing template package metadata
- Enabling a NuGet source
- Enabling or disabling workload-set update mode
- Executing a dotnet application
- Fixing (non code style) analyzer issues
- Fixing code style issues
- Formatting a code
- Getting a value of a specified NuGet configuration setting
- Installing a template package
- Installing optional workloads
- Installing the .NET local tools that are in scope for the current directory
- Installing the specified .NET tool
- Installing workloads needed for a project or a solution
- Invoking a local tool
- Packing a code into a NuGet package
- Printing a dependency graph for NuGet package
- Printing all .NET tools of the specified type currently installed
- Printing all configured NuGet sources
- Printing all projects in a solution file
- Printing available templates to be run using dotnet new
- Printing installed workloads
- Printing nuget configuration files currently being applied to a directory
- Printing NuGet packages for a project
- Printing project references for a project
- Printing the latest available version of the .NET SDK and .NET Runtime, for each feature band
- Printing the location of the specified NuGet cache type
- Publishing an application and its dependencies to a folder for deployment to a hosting system
- Pushing a NuGet package to the server
- Removing a NuGet package
- Removing a project or multiple projects from the solution file
- Removing an existing source from your NuGet configuration files
- Repairing workloads installations
- Restoring the dependencies and tools of a project
- Running a .NET application
- Running a custom .NET command
- Running source code without any explicit compile or launch commands
- Running tests from the specified assemblies
- Searching all .NET tools that are published to NuGet
- Searching for a NuGet package
- Searching for optional workloads
- Searching for the templates
- Setting the value of a specified NuGet configuration setting
- Signing with certificate
- Storing the specified assemblies in the runtime package store.
- Testing a project using the MSBuild VSTest target
- Testing from the specified project
- Uninstalling a specified workload
- Uninstalling a template package
- Uninstalling the specified .NET tool
- Unsetting the value of a specified NuGet configuration setting
- Updating a NuGet source
- Updating installed template packages
- Updating installed workloads
- Updating the specified .NET tool
- Working with development certificates
- Running C# script
- Shutting down build servers
- TeamCity API
WriteLine("Hello");
WriteLine("Hello", Header); WriteLine("Hello ".WithColor(Header), "world!");
WriteLine();
Error("Error info"); Error("Error info", "Error identifier"); Error("Error: ".WithColor(), "datails".WithColor(Color.Details));
Warning("Warning info"); Warning("Warning ", "info".WithColor(Color.Details));
Summary("Summary message"); Summary("Summary ", "message".WithColor(Color.Details));
Info("Some info"); Info("Some ", "info".WithColor(Color.Details));
Trace("Some trace info"); Trace("Some trace ", "info".WithColor(Color.Details));
Args have got from the script arguments.
if (Args.Count > 0) { WriteLine(Args[0]); } if (Args.Count > 1) { WriteLine(Args[1]); }
WriteLine(Props["version"]); WriteLine(Props.Get("configuration", "Release")); // Some CI/CDs have integration of these properties. // For example in TeamCity this property with all changes will be available in the next TeamCity steps. Props["version"] = "1.1.6";
Host is actually the provider of all global properties and methods.
var packages = Host.GetService<INuGet>(); Host.WriteLine("Hello");
This method might be used to get access to different APIs like INuGet or ICommandLine.
GetService<INuGet>(); var serviceProvider = GetService<IServiceProvider>(); serviceProvider.GetService(typeof(INuGet));
Besides that, it is possible to get an instance of System.IServiceProvider to access APIs.
public void Run() { var serviceProvider = GetService<IServiceCollection>() .AddTransient<MyTask>() .BuildServiceProvider(); var myTask = serviceProvider.GetRequiredService<MyTask>(); var exitCode = myTask.Run(); exitCode.ShouldBe(0); } private class MyTask(ICommandLineRunner runner) { public int? Run() => runner .Run(new CommandLine("whoami")) .EnsureSuccess() .ExitCode; }
using HostApi; IEnumerable<NuGetPackage> packages = GetService<INuGet>() .Restore(new NuGetRestoreSettings("IoC.Container").WithVersionRange(VersionRange.All));
using HostApi; var packagesPath = Path.Combine( Path.GetTempPath(), Guid.NewGuid().ToString()[..4]); var settings = new NuGetRestoreSettings("IoC.Container") .WithVersionRange(VersionRange.Parse("[1.3, 1.3.8)")) .WithTargetFrameworkMoniker("net5.0") .WithPackagesPath(packagesPath); IEnumerable<NuGetPackage> packages = GetService<INuGet>().Restore(settings);
using HostApi; // Creates and run a simple command line "whoami".AsCommandLine().Run().EnsureSuccess(); // Creates and run a simple command line new CommandLine("whoami").Run().EnsureSuccess(); // Creates and run a command line with arguments new CommandLine("cmd", "/c", "echo", "Hello").Run(); // Same as previous statement new CommandLine("cmd", "/c") .AddArgs("echo", "Hello") .Run().EnsureSuccess(); (new CommandLine("cmd") + "/c" + "echo" + "Hello") .Run().EnsureSuccess(); "cmd".AsCommandLine("/c", "echo", "Hello") .Run().EnsureSuccess(); ("cmd".AsCommandLine() + "/c" + "echo" + "Hello") .Run().EnsureSuccess(); // Just builds a command line with multiple environment variables var cmd = new CommandLine("cmd", "/c", "echo", "Hello") .AddVars(("Var1", "val1"), ("var2", "Val2")); // Same as previous statement cmd = new CommandLine("cmd") + "/c" + "echo" + "Hello" + ("Var1", "val1") + ("var2", "Val2"); // Builds a command line to run from a specific working directory cmd = new CommandLine("cmd", "/c", "echo", "Hello") .WithWorkingDirectory("MyDyrectory"); // Builds a command line and replaces all command line arguments cmd = new CommandLine("cmd", "/c", "echo", "Hello") .WithArgs("/c", "echo", "Hello !!!");
using HostApi; GetService<ICommandLineRunner>() .Run(new CommandLine("cmd", "/c", "DIR")).EnsureSuccess(); // or the same thing using the extension method new CommandLine("cmd", "/c", "DIR") .Run().EnsureSuccess(); // using operator '+' var cmd = new CommandLine("cmd") + "/c" + "DIR"; cmd.Run().EnsureSuccess(); // with environment variables cmd = new CommandLine("cmd") + "/c" + "DIR" + ("MyEnvVar", "Some Value"); cmd.Run().EnsureSuccess();
using HostApi; await GetService<ICommandLineRunner>() .RunAsync(new CommandLine("cmd", "/C", "DIR")).EnsureSuccess(); // or the same thing using the extension method var result = await new CommandLine("cmd", "/c", "DIR") .RunAsync().EnsureSuccess();
using HostApi; var lines = new List<string>(); var result = new CommandLine("cmd", "/c", "SET") .AddVars(("MyEnv", "MyVal")) .Run(output => lines.Add(output.Line)).EnsureSuccess(); lines.ShouldContain("MyEnv=MyVal");
using HostApi; var task = new CommandLine("cmd", "/c", "DIR") .RunAsync().EnsureSuccess(); var result = new CommandLine("cmd", "/c", "SET") .Run().EnsureSuccess(); await task;
Cancellation will destroy the process and its child processes.
using HostApi; var cancellationTokenSource = new CancellationTokenSource(); var task = new CommandLine("cmd", "/c", "TIMEOUT", "/T", "120") .RunAsync(null, cancellationTokenSource.Token); cancellationTokenSource.CancelAfter(TimeSpan.FromMilliseconds(100)); task.IsCompleted.ShouldBeFalse();
If timeout expired a process will be killed.
using HostApi; var exitCode = new CommandLine("cmd", "/c", "TIMEOUT", "/T", "120") .Run(null, TimeSpan.FromMilliseconds(1)) .ExitCode;
using HostApi; // Creates a base docker command line var dockerRun = new DockerRun() .WithAutoRemove(true) .WithInteractive(true) .WithImage("mcr.microsoft.com/dotnet/sdk") .WithPlatform("linux") .WithContainerWorkingDirectory("/MyProjects") .AddVolumes((ToAbsoluteLinuxPath(Environment.CurrentDirectory), "/MyProjects")); // Creates a new library project in a docker container dockerRun .WithCommandLine(new DotNetCustom("new", "classlib", "-n", "MyLib", "--force")) .Run().EnsureSuccess(); // Builds the library project in a docker container var result = dockerRun .WithCommandLine(new DotNetBuild().WithProject("MyLib/MyLib.csproj")) .Build().EnsureSuccess(); string ToAbsoluteLinuxPath(string path) => "/" + path.Replace(":", "").Replace('\\', '/');
using HostApi; // Creates some command line to run in a docker container var cmd = new CommandLine("whoami"); // Runs the command line in a docker container var result = new DockerRun(cmd, "mcr.microsoft.com/dotnet/sdk") .WithAutoRemove(true) .Run().EnsureSuccess();
using HostApi; var result = new DotNetAddPackage() .WithWorkingDirectory("MyLib") .WithPackage("Pure.DI") .Run().EnsureSuccess();
using HostApi; new DotNetNuGetAddSource() .WithName("TestSource") .WithSource(source) .Run().EnsureSuccess();
using HostApi; new DotNetAddReference() .WithProject(Path.Combine("MyTests", "MyTests.csproj")) .WithReferences(Path.Combine("MyLib", "MyLib.csproj")) .Run().EnsureSuccess(); new DotNetRemoveReference() .WithProject(Path.Combine("MyTests", "MyTests.csproj")) .WithReferences(Path.Combine("MyLib", "MyLib.csproj")) .Run().EnsureSuccess(); var lines = new List<string>(); new DotNetListReference() .WithProject(Path.Combine("MyTests", "MyTests.csproj")) .Run(output => lines.Add(output.Line)); lines.Any(i => i.Contains("MyLib.csproj")).ShouldBeFalse();
using HostApi; new DotNetNew() .WithTemplateName("sln") .WithName("MySolution") .WithForce(true) .AddArgs("--format", "sln") .Run().EnsureSuccess(); new DotNetSlnAdd() .WithSolution("MySolution.sln") .AddProjects( Path.Combine("MyLib", "MyLib.csproj"), Path.Combine("MyTests", "MyTests.csproj")) .Run().EnsureSuccess();
using HostApi; var result = new DotNetAddReference() .WithProject(Path.Combine("MyTests", "MyTests.csproj")) .WithReferences(Path.Combine("MyLib", "MyLib.csproj")) .Run().EnsureSuccess();
using HostApi; var messages = new List<BuildMessage>(); var result = new DotNetBuild() .WithWorkingDirectory("MyTests") .Build(message => messages.Add(message)).EnsureSuccess(); result.Errors.Any(message => message.State == BuildMessageState.StdError).ShouldBeFalse(result.ToString()); result.ExitCode.ShouldBe(0, result.ToString());
using HostApi; // Creates a new library project, running a command like: "dotnet new classlib -n MyLib --force" new DotNetNew() .WithTemplateName("classlib") .WithName("MyLib") .WithForce(true) .Build().EnsureSuccess(); // Builds the library project, running a command like: "dotnet msbuild /t:Build -restore /p:configuration=Release -verbosity=detailed" from the directory "MyLib" var result = new MSBuild() .WithWorkingDirectory("MyLib") .WithTarget("Build") .WithRestore(true) .AddProps(("configuration", "Release")) .WithVerbosity(DotNetVerbosity.Detailed) .Build().EnsureSuccess(); // The "result" variable provides details about a build result.Errors.Any(message => message.State == BuildMessageState.StdError).ShouldBeFalse(result.ToString()); result.ExitCode.ShouldBe(0, result.ToString());
using HostApi; // Clean the project, running a command like: "dotnet clean" from the directory "MyLib" new DotNetClean() .WithWorkingDirectory("MyLib") .Build().EnsureSuccess();
using HostApi; new DotNetNuGetLocalsClear() .WithCacheLocation(NuGetCacheLocation.Temp) .Run().EnsureSuccess();
using HostApi; new DotNetNew() .WithTemplateName("classlib") .WithName("MyLib") .WithForce(true) .Run().EnsureSuccess();
using HostApi; new DotNetNuGetDelete() .WithPackage("MyLib") .WithPackageVersion("1.0.0") .WithSource(repoUrl) .Run().EnsureSuccess();
using HostApi; new DotNetNuGetDisableSource() .WithName("TestSource") .Run().EnsureSuccess();
using HostApi; new DotNetNewDetails() .WithTemplateName("CSharpInteractive.Templates") .Run().EnsureSuccess();
using HostApi; new DotNetNuGetEnableSource() .WithName("TestSource") .Run().EnsureSuccess();
using HostApi; new DotNetWorkloadConfig() .WithUpdateMode(DotNetWorkloadUpdateMode.WorkloadSet) .Run().EnsureSuccess();
using HostApi; new DotNetExec() .WithPathToApplication(Path.Combine(path, "MyApp.dll")) .Run().EnsureSuccess();
using HostApi; new DotNetFormatAnalyzers() .WithWorkingDirectory("MyLib") .WithProject("MyLib.csproj") .AddDiagnostics("CA1831", "CA1832") .WithSeverity(DotNetFormatSeverity.Warning) .Run().EnsureSuccess();
using HostApi; new DotNetFormatStyle() .WithWorkingDirectory("MyLib") .WithProject("MyLib.csproj") .AddDiagnostics("IDE0005", "IDE0006") .WithSeverity(DotNetFormatSeverity.Information) .Run().EnsureSuccess();
using HostApi; new DotNetFormat() .WithWorkingDirectory("MyLib") .WithProject("MyLib.csproj") .AddDiagnostics("IDE0005", "IDE0006") .AddIncludes(".", "./tests") .AddExcludes("./obj") .WithSeverity(DotNetFormatSeverity.Information) .Run().EnsureSuccess();
using HostApi; string? repositoryPath = null; new DotNetNuGetConfigGet() .WithConfigKey("repositoryPath") .Run(output => repositoryPath = output.Line).EnsureSuccess();
using HostApi; new DotNetNewInstall() .WithPackage("Pure.DI.Templates") .Run().EnsureSuccess();
using HostApi; new DotNetWorkloadInstall() .AddWorkloads("aspire") .Run().EnsureSuccess();
using HostApi; // Creates a local tool manifest new DotNetNew() .WithTemplateName("tool-manifest") .Run().EnsureSuccess(); new DotNetToolRestore() .Run().EnsureSuccess();
using HostApi; new DotNetToolInstall() .WithLocal(true) .WithPackage("dotnet-csi") .WithVersion("1.1.2") .Run().EnsureSuccess();
using HostApi; new DotNetWorkloadRestore() .WithProject(Path.Combine("MyLib", "MyLib.csproj")) .Run().EnsureSuccess();
using HostApi; var script = Path.GetTempFileName(); File.WriteAllText(script, "Console.WriteLine($\"Hello, {Args[0]}!\");"); var stdOut = new List<string>(); new DotNetToolRun() .WithCommandName("dotnet-csi") .AddArgs(script) .AddArgs("World") .Run(output => stdOut.Add(output.Line)) .EnsureSuccess(); // Checks stdOut stdOut.Contains("Hello, World!").ShouldBeTrue();
using HostApi; // Creates a NuGet package of version 1.2.3 for the project new DotNetPack() .WithWorkingDirectory("MyLib") .WithOutput(path) .AddProps(("version", "1.2.3")) .Build().EnsureSuccess();
using HostApi; new DotNetNuGetWhy() .WithProject(Path.Combine("MyLib", "MyLib.csproj")) .WithPackage("MyLib.1.2.3.nupkg") .Run().EnsureSuccess();
using HostApi; new DotNetToolList() .WithLocal(true) .Run().EnsureSuccess(); new DotNetToolList() .WithGlobal(true) .Run().EnsureSuccess();
using HostApi; new DotNetNuGetListSource() .WithFormat(NuGetListFormat.Short) .Run().EnsureSuccess();
using HostApi; var lines = new List<string>(); new DotNetSlnList() .WithSolution("MySolution.sln") .Run(output => lines.Add(output.Line)) .EnsureSuccess();
using HostApi; new DotNetNewList() .Run().EnsureSuccess();
using HostApi; new DotNetWorkloadList() .Run().EnsureSuccess();
using HostApi; var configPaths = new List<string>(); new DotNetNuGetConfigPaths() .Run(output => configPaths.Add(output.Line)).EnsureSuccess();
using HostApi; new DotNetAddPackage() .WithWorkingDirectory("MyLib") .WithPackage("Pure.DI") .Run().EnsureSuccess(); var lines = new List<string>(); new DotNetListPackage() .WithProject(Path.Combine("MyLib", "MyLib.csproj")) .WithVerbosity(DotNetVerbosity.Minimal) .Run(output => lines.Add(output.Line)); lines.Any(i => i.Contains("Pure.DI")).ShouldBeTrue();
using HostApi; new DotNetAddReference() .WithProject(Path.Combine("MyTests", "MyTests.csproj")) .WithReferences(Path.Combine("MyLib", "MyLib.csproj")) .Run().EnsureSuccess(); var lines = new List<string>(); new DotNetListReference() .WithProject(Path.Combine("MyTests", "MyTests.csproj")) .Run(output => lines.Add(output.Line)); lines.Any(i => i.Contains("MyLib.csproj")).ShouldBeTrue();
using HostApi; var sdks = new List<Sdk>(); new DotNetSdkCheck() .Run(output => { if (output.Line.StartsWith("Microsoft.")) { var data = output.Line.Split(' ', StringSplitOptions.RemoveEmptyEntries); if (data.Length >= 2) { sdks.Add(new Sdk(data[0], NuGetVersion.Parse(data[1]))); } } }) .EnsureSuccess(); sdks.Count.ShouldBeGreaterThan(0); record Sdk(string Name, NuGetVersion Version);
using HostApi; new DotNetNuGetLocalsList() .WithCacheLocation(NuGetCacheLocation.GlobalPackages) .Run().EnsureSuccess();
using HostApi; new DotNetPublish() .WithWorkingDirectory("MyLib") .WithFramework(framework) .WithOutput("bin") .Build().EnsureSuccess();
using HostApi; new DotNetNuGetPush() .WithWorkingDirectory("MyLib") .WithPackage(Path.Combine("packages", "MyLib.1.0.0.nupkg")) .WithSource(repoUrl) .Run().EnsureSuccess();
using HostApi; new DotNetAddPackage() .WithWorkingDirectory("MyLib") .WithPackage("Pure.DI") .Run().EnsureSuccess(); new DotNetRemovePackage() .WithWorkingDirectory("MyLib") .WithPackage("Pure.DI") .Run().EnsureSuccess();
using HostApi; new DotNetSlnRemove() .WithSolution("MySolution.sln") .AddProjects( Path.Combine("MyLib", "MyLib.csproj")) .Run().EnsureSuccess();
using HostApi; new DotNetNuGetRemoveSource() .WithName("TestSource") .Run().EnsureSuccess();
using HostApi; new DotNetWorkloadRepair() .Run().EnsureSuccess();
using HostApi; new DotNetRestore() .WithProject(Path.Combine("MyLib", "MyLib.csproj")) .Build().EnsureSuccess();
// Adds the namespace "HostApi" to use .NET build API using HostApi; new DotNet() .WithPathToApplication(Path.Combine(path, "MyApp.dll")) .Run().EnsureSuccess();
using HostApi; // Gets the dotnet version, running a command like: "dotnet --version" NuGetVersion? version = null; new DotNetCustom("--version") .Run(message => NuGetVersion.TryParse(message.Line, out version)) .EnsureSuccess(); version.ShouldNotBeNull();
using HostApi; var stdOut = new List<string>(); new DotNetRun() .WithProject(Path.Combine("MyApp", "MyApp.csproj")) .Build(message => stdOut.Add(message.Text)) .EnsureSuccess();
using HostApi; // Runs tests var result = new VSTest() .AddTestFileNames(Path.Combine("bin", "MyTests.dll")) .WithWorkingDirectory(path) .Build().EnsureSuccess(); // The "result" variable provides details about build and tests result.ExitCode.ShouldBe(0, result.ToString()); result.Summary.Tests.ShouldBe(1, result.ToString()); result.Tests.Count(test => test.State == TestState.Finished).ShouldBe(1, result.ToString());
using HostApi; new DotNetToolSearch() .WithPackage("dotnet-csi") .WithDetail(true) .Run().EnsureSuccess();
using System.Text; using System.Text.Json; using HostApi; var packagesJson = new StringBuilder(); new DotNetPackageSearch() .WithSearchTerm("Pure.DI") .WithFormat(DotNetPackageSearchResultFormat.Json) .Run(output => packagesJson.AppendLine(output.Line)).EnsureSuccess(); var result = JsonSerializer.Deserialize<Result>( packagesJson.ToString(), new JsonSerializerOptions { PropertyNameCaseInsensitive = true }); result.ShouldNotBeNull(); result.SearchResult.SelectMany(i => i.Packages).Count(i => i.Id == "Pure.DI").ShouldBe(1); record Result(int Version, IReadOnlyCollection<Source> SearchResult); record Source(string SourceName, IReadOnlyCollection<Package> Packages); record Package( string Id, string LatestVersion, int TotalDownloads, string Owners);
using HostApi; new DotNetWorkloadSearch() .WithSearchString("maui") .Run().EnsureSuccess();
using HostApi; new DotNetNewSearch() .WithTemplateName("build") .Run().EnsureSuccess();
using HostApi; new DotNetNuGetConfigSet() .WithConfigFile(configFile) .WithConfigKey("repositoryPath") .WithConfigValue("MyValue") .Run().EnsureSuccess();
using HostApi; new DotNetNuGetSign() .AddPackages("MyLib.1.2.3.nupkg") .WithCertificatePath("certificate.pfx") .WithCertificatePassword("Abc") .WithTimestampingServer("http://timestamp.digicert.com/") .Run().EnsureSuccess();
using HostApi; new DotNetStore() .AddManifests(Path.Combine("MyLib", "MyLib.csproj")) .WithFramework("net8.0") .WithRuntime("win-x64") .Build();
using HostApi; // Runs tests via a command var result = new MSBuild() .WithTarget("VSTest") .WithWorkingDirectory("MyTests") .Build().EnsureSuccess(); // The "result" variable provides details about a build result.ExitCode.ShouldBe(0, result.ToString()); result.Summary.Tests.ShouldBe(1, result.ToString()); result.Tests.Count(test => test.State == TestState.Finished).ShouldBe(1, result.ToString());
using HostApi; // Runs tests var result = new DotNetTest() .WithProject("MyTests") .Build().EnsureSuccess();
using HostApi; new DotNetWorkloadUninstall() .AddWorkloads("aspire") .Run().EnsureSuccess();
using HostApi; new DotNetNewUninstall() .WithPackage("Pure.DI.Templates") .Run();
using HostApi; new DotNetToolUninstall() .WithPackage("dotnet-csi") .Run().EnsureSuccess();
using HostApi; new DotNetNuGetConfigUnset() .WithConfigKey("repositoryPath") .Run().EnsureSuccess();
using HostApi; new DotNetNuGetUpdateSource() .WithName("TestSource") .WithSource(newSource) .Run().EnsureSuccess();
using HostApi; new DotNetNewUpdate() .Run().EnsureSuccess();
using HostApi; new DotNetWorkloadUpdate() .Run().EnsureSuccess();
using HostApi; new DotNetToolUpdate() .WithLocal(true) .WithPackage("dotnet-csi") .WithVersion("1.1.2") .Run().EnsureSuccess();
using HostApi; // Create a certificate, trust it, and export it to a PEM file. new DotNetDevCertsHttps() .WithExportPath("certificate.pem") .WithTrust(true) .WithFormat(DotNetCertificateFormat.Pem) .WithPassword("Abc") .Run().EnsureSuccess();
using HostApi; var script = Path.GetTempFileName(); File.WriteAllText(script, "Console.WriteLine($\"Hello, {Args[0]}!\");"); var stdOut = new List<string>(); new DotNetCsi() .WithScript(script) .AddArgs("World") .Run(output => stdOut.Add(output.Line)) .EnsureSuccess(); // Checks stdOut stdOut.Contains("Hello, World!").ShouldBeTrue();
using HostApi; // Shuts down all build servers that are started from dotnet. new DotNetBuildServerShutdown() .Run().EnsureSuccess();
For more details how to use TeamCity service message API please see this page. Instead of creating a root message writer like in the following example:
using JetBrains.TeamCity.ServiceMessages.Write.Special; using var writer = new TeamCityServiceMessages().CreateWriter(Console.WriteLine);
use this statement:
using JetBrains.TeamCity.ServiceMessages.Write.Special; using var writer = GetService<ITeamCityWriter>();
This sample opens a block My Tests and reports about two tests:
// Adds a namespace to use ITeamCityWriter using JetBrains.TeamCity.ServiceMessages.Write.Special; using var writer = GetService<ITeamCityWriter>(); using (var tests = writer.OpenBlock("My Tests")) { using (var test = tests.OpenTest("Test1")) { test.WriteStdOutput("Hello"); test.WriteImage("TestsResults/Test1Screenshot.jpg", "Screenshot"); test.WriteDuration(TimeSpan.FromMilliseconds(10)); } using (var test = tests.OpenTest("Test2")) { test.WriteIgnored("Some reason"); } }
For more information on TeamCity Service Messages, see this page.
