# All of .NET at Your Fingertips

Under every cmdlet is .NET, a library of thousands of ready-made tools, and PowerShell reaches any of them directly: a type in square brackets and :: call its static members, such as \[Math\]::Round, \[IO.Path\]::GetExtension and \[Guid\]::NewGuid(), and Add-Type compiles a few lines of C# into tools of your own.

Freelancer · PowerShell · Updated November 10, 2026

## After this lesson you can

- Call .NET's static methods from PowerShell, such as \[Math\]::Round, \[IO.Path\]::GetExtension and \[Guid\]::NewGuid()
- Compile a few lines of C# into the session with Add-Type and call them from PowerShell

## Key takeaways

- A type's name in square brackets, then `::` (read "colon colon"), reaches a tool that belongs to the type itself: `[Math]::Round(19.987, 2)` gives 19.99.
- `[Math]::Round(2.5)` gives 2: .NET rounds a half to the even number. Add `[MidpointRounding]::AwayFromZero` for the 3 a shop would charge.
- Type a method's name without parentheses, such as `[Math]::Round`, to see every way to call it.
- `[IO.Path]` takes file names apart as text, and `[Guid]::NewGuid()` makes an ID that no one else will ever make.
- `Add-Type -TypeDefinition` compiles C# into this window. A type can be added once a window, so a changed version needs a new window.

You need the extension of 300 photo names, a name for a test folder that can't clash with any other, or a price rounded the way a shop rounds it. No cmdlet does exactly that, and installing a module for one line feels like buying a toolbox for one screw. You already own the toolbox. Since *Columns You Make Yourself: Calculated Properties* you've been rounding with `[math]::Round`, a tool from **.NET**, the library PowerShell is built on. It holds thousands more, and every one of them works at the prompt. .NET developers try out a line of their app this way before they write it, and administrators reach for it when no cmdlet fits.

## A toolbox under every cmdlet: \`\[Math\]\`

A **type** is a kind of thing .NET knows about: a number, a date, a file. Its name goes in square brackets, as `[int]` and `[datetime]` did in *Numbers, Dates and Types*. Some types are toolboxes: `[Math]` holds math, and `::` (read "colon colon") takes a tool out of it. Those tools are **static members**: they belong to the type itself, so you don't need an object first. A method takes values in parentheses; a property, such as `PI`, takes none:

```powershell
[Math]::Round(19.987, 2)
[Math]::Max(42, 17)
[Math]::Pow(2, 10)
[Math]::PI
```

```text
19.99
42
1024
3.14159265358979
```

`[Math]` is short for `[System.Math]`: PowerShell adds `System.` for you, and capital letters don't matter, so `[math]` is the same toolbox.

![PowerShell drawn as a house standing on a much larger foundation labeled .NET: the house's rooms hold the cmdlets Get-ChildItem, Sort-Object and Import-Csv, and a staircase marked :: leads down into the foundation, where three open drawers labeled with the .NET classes Math, IO.Path and Guid hold the tools Round, GetExtension and NewGuid](https://fsdtrainingmedia.blob.core.windows.net/public/images/2026/11/55a4e4e2d39d4270a36ad2c7a4e82a64.webp)

One surprise is worth knowing before you round money:

```powershell
[Math]::Round(2.5)
[Math]::Round(3.5)
[Math]::Round(2.5, [MidpointRounding]::AwayFromZero)
```

```text
2
4
3
```

A number exactly halfway goes to the even neighbor, so 2.5 becomes 2. Banks use this so halves don't always push totals up. A shop's till rounds a half up, and `[MidpointRounding]::AwayFromZero` does that.

## Ask a type what it can do

Type a method's name without the parentheses, and PowerShell lists every way to call it:

```powershell
[Math]::Round
```

```text
OverloadDefinitions
-------------------
static decimal Round(decimal d)
static decimal Round(decimal d, int decimals)
static decimal Round(decimal d, System.MidpointRounding mode)
static decimal Round(decimal d, int decimals, System.MidpointRounding mode)
static double Round(double a)
static double Round(double value, int digits)
static double Round(double value, System.MidpointRounding mode)
static double Round(double value, int digits, System.MidpointRounding mode)
```

Each line is one way: a number alone, a number and how many digits, or either one with a rounding mode. `[Math] | Get-Member -Static` lists everything in the toolbox, the same way `Get-Member` showed an object's properties in *What an Object Is: `Get-Member`*. Microsoft's .NET documentation has a page for every type, with examples in C# that read almost like PowerShell.

## File names and IDs: \`\[IO.Path\]\` and \`\[Guid\]\`

`[IO.Path]` takes file names apart. It works on the text alone, so the file doesn't have to exist:

```powershell
[IO.Path]::GetExtension('beach-day.JPG')
[IO.Path]::GetFileNameWithoutExtension('beach-day.JPG')
[IO.Path]::ChangeExtension('notes.txt', '.md')
```

```text
.JPG
beach-day
notes.md
```

A **GUID** (globally unique identifier, said "goo-id") is a random number so large that no two computers will ever make the same one. Windows labels drives and apps with them, and this course's exercise checks name their throwaway folders with them, so two runs never collide:

```powershell
"report-$([Guid]::NewGuid()).txt"
```

```text
report-87fdc681-1519-4bb4-b34f-ff9d2afa08b1.txt
```

Yours will be different, and different again each time. The cmdlet `New-Guid` makes the same kind of ID.

## A few lines of C#: \`Add-Type\`

Sometimes the tool you need isn't in .NET either, or a colleague hands you a few lines of **C#**, the language most of .NET is written in. `Add-Type -TypeDefinition` turns C# into a new type in this window. The C# goes in a here-string, from *Text: Quotes and `$( )`*:

```powershell
Add-Type -TypeDefinition @'
public static class Kitchen
{
    public static double ToCelsius(double fahrenheit)
    {
        return (fahrenheit - 32) * 5 / 9;
    }
}
'@
[Kitchen]::ToCelsius(350)
[Math]::Round([Kitchen]::ToCelsius(350))
```

```text
176.666666666667
177
```

`Kitchen` is now a type like `[Math]`, and a recipe's 350 °F oven is 177 °C. Two things behave differently from PowerShell. C# is **compiled**, checked as a whole before anything runs, so a missing `;` stops it with the line and column of the mistake: `(5,41): error CS1002: ; expected`. And a type can be added only once a window: change `Kitchen` and run it again, and PowerShell says `Cannot add type. The type name 'Kitchen' already exists.` Open a new window to try the new version.

Windows PowerShell 5.1 compiles only older C#, so a snippet written for today's C# may not work there. On a Mac or Linux, all of this works the same, and `[IO.Path]` follows the system's `/`.

## Check yourself

2 questions to try on the lesson page.

## So what

When no cmdlet does the job, the answer is usually one line of .NET away, and when even .NET falls short, a few lines of C# make the tool you need.

## Key terms

- [.NET](https://www.ask-codey.com/glossary/dotnet)
- [.NET Types in PowerShell](https://www.ask-codey.com/glossary/dotnet-types-in-powershell)
- [Static Member](https://www.ask-codey.com/glossary/static-member)
- [GUID](https://www.ask-codey.com/glossary/guid)
- [Add-Type](https://www.ask-codey.com/glossary/add-type)

## Cheat sheets

- [All of .NET at Your Fingertips](https://www.ask-codey.com/cheat-sheets/powershell-dotnet-cheat-sheet)

## Related

- [Numbers, Dates and Types](https://www.ask-codey.com/lessons/powershell-types)
- [Columns You Make Yourself: Calculated Properties](https://www.ask-codey.com/lessons/powershell-calculated-properties)
- [Your Script Can Have a Window Too](https://www.ask-codey.com/lessons/powershell-windows-forms)
- [When to Reach for Another Language](https://www.ask-codey.com/lessons/powershell-when-to-use-another-language)

Source: https://www.ask-codey.com/lessons/powershell-dotnet
