One of PowerShell’s most powerful and defining features is that it is built directly on the .NET runtime. This isn’t just a superficial connection; PowerShell’s engine, its cmdlets, and the data that flows through its pipeline are all .NET objects. This deep integration gives PowerShell a “superpower”: the ability to directly and seamlessly access the vast ecosystem of .NET classes and methods.

This guide will walk you through how this relationship works and how you can leverage .NET to write incredibly powerful and flexible scripts, turning PowerShell into a full-fledged .NET scripting language.


The Core Relationship: PowerShell is a .NET Scripting Language

Unlike traditional shells that work with text, PowerShell works with objects. When you run a command like Get-Process, you are not getting a block of text; you are getting a collection of .NET objects. This is why you can do things like $process.Kill()—you are calling the Kill() method on a System.Diagnostics.Process object.

Because of this, you can access almost any part of the .NET Framework (or modern .NET on pwsh) directly from your script.


1. Accessing Static .NET Classes and Methods

The easiest way to start using .NET in PowerShell is by calling static methods on built-in .NET classes. You can do this using the [TypeName]::MethodName() syntax.

Example: Using [System.Math]

# Get the square root of 144
[math]::Sqrt(144)

# Get the larger of two numbers
[math]::Max(10, 20)

Example: Using [System.DateTime]

# Get the current date and time
[DateTime]::Now

# Check if a year is a leap year
[DateTime]::IsLeapYear(2024)


2. Creating and Working with .NET Objects

You can create an instance of any .NET class using the New-Object cmdlet.

Example: Working with Files

# Create a FileInfo object for a specific file
$file = New-Object System.IO.FileInfo "C:\Windows\notepad.exe"

# Now you can access its properties and methods
Write-Host "File Name: $($file.Name)"
Write-Host "File Size: $($file.Length) bytes"
Write-Host "Creation Date: $($file.CreationTime)"

Example: Using a Stopwatch to time a command

$stopwatch = [System.Diagnostics.Stopwatch]::StartNew()

# Run a command that takes some time
Start-Sleep -Seconds 2

$stopwatch.Stop()
Write-Host "The command took $($stopwatch.Elapsed.TotalMilliseconds) ms to run."


3. Loading Your Own .NET Code with Add-Type

PowerShell’s .NET integration isn’t limited to the built-in classes. You can load your own custom C# code on the fly using the Add-Type cmdlet. This is incredibly powerful for creating helper functions or accessing complex logic that is easier to write in C#.

From a C# Source String

You can embed C# code directly in your PowerShell script.

# Define some C# code as a string
$csharpSource = @"
public static class MyCustomTools {
    public static string SayHello(string name) {
        return $"Hello, {name}, from C#!"";
    }
}
"@

# Compile the C# code in memory
Add-Type -TypeDefinition $csharpSource -Language CSharp

# Now you can call your new static method
[MyCustomTools]::SayHello("PowerShell User")

From a Pre-compiled DLL

If you have a pre-compiled .NET library (.dll file), you can load it directly into your PowerShell session.

# Load a .NET assembly from a DLL file
Add-Type -Path "C:\MyProjects\MyLibrary.dll"

# Now you can create instances of the classes from that library
$myObject = New-Object MyLibrary.MyClass

Staying Current: PowerShell and Modern .NET

The cross-platform version of PowerShell (pwsh) is built on the latest versions of .NET (e.g., .NET 8, .NET 9, etc.). This means that as .NET evolves and gets new features and performance improvements, PowerShell automatically benefits.

You can check which version of .NET your PowerShell session is running on with this command:

[System.Runtime.InteropServices.RuntimeInformation]::FrameworkDescription

This close relationship ensures that PowerShell remains a modern, high-performance scripting language that can take advantage of the latest innovations in the .NET ecosystem.


Conclusion

PowerShell’s seamless integration with .NET is its most defining and powerful feature. It elevates PowerShell from a simple shell to a full-fledged scripting language capable of complex, enterprise-grade automation.

By learning to leverage the .NET framework from within your scripts, you can:

  • Perform complex tasks that would be difficult or impossible with traditional shell commands.
  • Write more efficient and performant code by using compiled .NET methods.
  • Extend PowerShell’s capabilities with your own custom C# code.

The next time you’re faced with a complex scripting challenge, remember that the entire .NET library is at your fingertips.