# Migrating Powershell Sdk

> Migrates the legacy System.Management.Automation (PowerShell SDK) references from obsolete .NET Framework (Windows PowerShell 5.1) to modern .NET (PowerShell 7+). Replaces Windows PowerShell Reference Assemblies or GAC references with the cross-platform System.Management.Automation NuGet package. Use ONLY when the legacy Windows PowerShell SDK has been flagged as obsolete or deprecated and must be replaced — not for version-bump scenarios where existing PowerShell packages are still supported. Scope is binary cmdlet projects: this skill retargets a compiled project and does NOT edit PowerShell script files. Loose .ps1/.psm1 scripts, and the 5.1-to-7 script breaks they contain, belong to the powershell-5.1-to-7-upgrade scenario instead. Triggers for "migrate PowerShell SDK", "upgrade cmdlet project", "PowerShellStandard.Library", project files (.csproj, .vbproj, .fsproj) with PowerShell references, and .psd1 module manifests that ship alongside such a project.

- Skill: `microsoft/migrating-powershell-sdk` (Agent Skill)
- Install (CLI): `npx skillmds@latest add microsoft/migrating-powershell-sdk`
- Raw SKILL.md: https://api.skillmd.com/api/skills/microsoft/migrating-powershell-sdk/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- Author: Microsoft (https://skillmd.com/u/microsoft)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/microsoft/migrating-powershell-sdk

---


# System.Management.Automation Migration

## Overview

Migrate PowerShell cmdlet projects from .NET Framework (Windows PowerShell 5.1) to modern .NET (.NET 6+). The core change is replacing the Windows PowerShell reference assembly with the cross-platform `System.Management.Automation` NuGet package. Most code remains unchanged because the SDK types (`PSCmdlet`, `Cmdlet`, `PSObject`, attributes) are identical across both packages.

**Scope.** This skill retargets the *project*. It does not read or edit `.ps1`/`.psm1` files, so it will not find the script-level 5.1 → 7 breaks — removed cmdlets, snap-ins, WMI, encoding defaults. If the repository also carries loose PowerShell scripts that must run on PowerShell 7, those are the `powershell-5.1-to-7-upgrade` scenario's work, not this skill's.

## Package Reference Changes

### Old References (Remove)

```xml
<!-- GAC/file reference -->
<Reference Include="System.Management.Automation" />

<!-- Windows PowerShell ref assemblies NuGet -->
<PackageReference Include="Microsoft.PowerShell.5.ReferenceAssemblies" Version="1.1.0" />
```

### New Reference (Add)

```xml
<!-- Cross-platform NuGet package; use version matching target framework -->
<PackageReference Include="System.Management.Automation" Version="{version-for-target-framework}" />

<!-- OR for dual-targeting Windows PowerShell 5.1 + PowerShell 7 -->
<PackageReference Include="PowerShellStandard.Library" Version="{stable-version}" />
```

### Choosing the Right Package

| Package | When to Use |
|---------|-------------|
| `System.Management.Automation` | Targeting a specific PowerShell 7.x version. Provides full API surface. |
| `PowerShellStandard.Library` | Must support both Windows PowerShell 5.1 and PowerShell 7+ from a single binary. Targets `netstandard2.0`. |

Use tools or [PowerShell releases](https://github.com/PowerShell/PowerShell/releases) to find the latest stable package version for the target framework.

## Workflow

```
Migration Progress:
- [ ] Step 1: Detect PowerShell SDK usage
- [ ] Step 2: Determine target framework and package version
- [ ] Step 3: Update project file references
- [ ] Step 4: Handle API differences
- [ ] Step 5: Update module manifest
- [ ] Step 6: Build and verify
```

### Step 1: Detect PowerShell SDK Usage

Scan the project for:
- `using System.Management.Automation;` statements
- Types inheriting from `Cmdlet` or `PSCmdlet`
- `[Cmdlet(...)]` attributes
- Reference type: GAC reference, `Microsoft.PowerShell.5.ReferenceAssemblies` NuGet, or direct file reference

If the project already uses the cross-platform NuGet package, no migration is needed.

### Step 2: Determine Target Framework and Package Version

1. Check if the user specified a target framework (e.g., "migrate to net10.0")
2. Otherwise, read `<TargetFramework>` or `<TargetFrameworks>` from the project file or `Directory.Build.props`
3. Look up the best `System.Management.Automation` package version for that framework
4. If the project must support both Windows PowerShell 5.1 and PowerShell 7+, choose `PowerShellStandard.Library` instead — it targets `netstandard2.0` so a single binary works in both hosts

### Step 3: Update Project File References

Remove old references and add the new package reference (see "Package Reference Changes" above).

### Step 4: Handle API Differences

Most SDK types are identical, but these APIs changed:

| Windows PowerShell | PowerShell 7+ | Action |
|-------------------|---------------|--------|
| `PSSnapIn` classes | Not supported | Convert to module manifests (`.psd1`). Snap-ins were deprecated because modules provide better isolation and discoverability. |
| `PSHost.NotifyBeginApplication` | May not be implemented | Guard with try/catch or remove the call |
| WinRM remoting APIs | Limited on non-Windows | Use SSH remoting for cross-platform scenarios |

### Step 5: Update Module Manifest (If Applicable)

If the project produces a PowerShell module, update the `.psd1`:

```powershell
@{
    PowerShellVersion     = '7.0'
    CompatiblePSEditions  = @('Core')
    ProcessorArchitecture = 'None'
}
```

### Step 6: Build and Verify

1. Build the module:
   ```
   dotnet build
   ```
2. Import and check cmdlet registration:
   ```powershell
   Import-Module ./bin/Debug/{target-framework}/MyModule.dll
   Get-Command -Module MyModule
   ```
3. Run cmdlet smoke tests to verify parameter binding and pipeline operations

## Troubleshooting

### Cmdlets Not Found After Import

Ensure the assembly contains `[Cmdlet]` attributes and the namespace is correctly exported in the module manifest.

### Type Conflicts with Other Modules

Another loaded module may bundle a different `System.Management.Automation` version. Use assembly load contexts or module isolation boundaries to resolve.

### Missing APIs at Runtime

Some Windows PowerShell APIs have no PowerShell 7 equivalent. Check the [PowerShell 7 SDK docs](https://learn.microsoft.com/en-us/powershell/scripting/dev-cross-plat/choosing-the-right-nuget-package) for alternatives.

### Snap-in Code

PowerShell 7 does not support snap-ins. Remove `PSSnapIn`-derived classes and replace with:
- Module manifests (`.psd1`) for metadata
- `RequiredModules` in the manifest for dependency management

