PowerShell Standard Library: Build single module that works across Windows PowerShell and PowerShell Core

Steve

August 6th, 2018

This is the first of a series of blog posts that will help you take advantage of a new NuGet package PowerShellStandard Library 5.1.0. This package allows developers to create modules that are portable between Windows PowerShell 5.1 and PowerShell Core 6.0. This means that you can create PowerShell modules that run on Windows, Linux, and macOS with a single binary!

The version of PowerShell Standard Library indicates the lowest version of PowerShell that it is compatible with. The community promise is that it is always forward compatible. So a module built against PowerShell Standard Library v3 is compatible with Windows PowerShell v3, v4, v5.1, PowerShell Core 6, and the upcoming PowerShell Core 6.1. Compatibility is achieved by providing a subset of the APIs common across all those versions of PowerShell. This reference assembly is the equivalent to a header file for C/C++ where it has the APIs defined, but no implementation. During runtime, the module would use the version of System.Management.Automation.dll that is used by the PowerShell host.

Creating a PowerShell Module

In this post, I’ll walk through the steps for creating a simple C# module with a single cmdlet. I will also be using the DotNet CLI tools for creating everything I need.

Installing the PowerShell Standard Module Template

First, we can leverage a new template that we published for DotNet CLI, but we need to install it first:

PS> dotnet new -i Microsoft.PowerShell.Standard.Module.Template Restoring packages for C:\Users\James\.templateengine\dotnetcli\v2.1.302\scratch\restore.csproj... Installing Microsoft.PowerShell.Standard.Module.Template 0.1.3. Generating MSBuild file C:\Users\James\.templateengine\dotnetcli\v2.1.302\scratch\obj\restore.csproj.nuget.g.props. Generating MSBuild file C:\Users\James\.templateengine\dotnetcli\v2.1.302\scratch\obj\restore.csproj.nuget.g.targets. Restore completed in 1.66 sec for C:\Users\James\.templateengine\dotnetcli\v2.1.302\scratch\restore.csproj. Usage: new [options] Options: -h, --help Displays help for this command. -l, --list Lists templates containing the specified name. If no name is specified, lists all templates. -n, --name The name for the output being created. If no name is specified, the name of the current directory is used. -o, --output Location to place the generated output. -i, --install Installs a source or a template pack. -u, --uninstall Uninstalls a source or a template pack. --nuget-source Specifies a NuGet source to use during install. --type Filters templates based on available types. Predefined values are "project", "item" or "other". --force Forces content to be generated even if it would change existing files. -lang, --language Filters templates based on language and specifies the language of the template to create. Templates Short Name Language Tags ---------------------------------------------------------------------------------------------------------------------------- Console Application console [C#], F#, VB Common/Console Class library classlib [C#], F#, VB Common/Library PowerShell Standard Module psmodule [C#] Library/PowerShell/Module ...

A new template called psmodule is now available making it easy to start a new C# based PowerShell module. Any issues, feedback, or suggestions for this template should be opened in the PowerShell Standard repo.

Creating a new project

We need to create a location for our new project and then use the template to create the project:

PS> mkdir myModule Directory: C:\Users\James Mode LastWriteTime Length Name ---- ------------- ------ ---- d----- 8/3/2018 2:41 PM myModule PS> cd myModule PS C:\Users\James\myModule> dotnet new psmodule The template "PowerShell Standard Module" was created successfully. Processing post-creation actions... Running 'dotnet restore' on C:\Users\James\myModule\myModule.csproj... Restoring packages for C:\Users\James\myModule\myModule.csproj... Installing PowerShellStandard.Library 5.1.0-preview-06. Generating MSBuild file C:\Users\James\myModule\obj\myModule.csproj.nuget.g.props. Generating MSBuild file C:\Users\James\myModule\obj\myModule.csproj.nuget.g.targets. Restore completed in 1.76 sec for C:\Users\James\myModule\myModule.csproj. Restore succeeded.

You can see that the dotnet cli has created a source file and .csproj file for my project:

PS C:\Users\James\myModule> dir Directory: C:\Users\James\myModule Mode LastWriteTime Length Name ---- ------------- ------ ---- d----- 8/3/2018 1:48 PM obj -a---- 8/3/2018 1:48 PM 376 myModule.csproj -a---- 8/3/2018 1:48 PM 1698 TestSampleCmdletCommand.cs

The sample from the template demonstrates a simple cmdlet with two parameters that outputs results with a custom class.

Building the module

Building the sample is code is easy with DotNet CLI:

PS C:\Users\James\myModule> dotnet build Microsoft (R) Build Engine version 15.7.179.6572 for .NET Core Copyright (C) Microsoft Corporation. All rights reserved. Restore completed in 76.85 ms for C:\Users\James\myModule\myModule.csproj. myModule -> C:\Users\James\myModule\bin\Debug

etstandard2.0\myModule.dll Build succeeded. 0 Warning(s) 0 Error(s) Time Elapsed 00:00:05.40

Testing the built module

To test this sample module, we just need to import it. We can check to see what it supports and try running it:

PS C:\Users\James\myModule> ipmo .\bin\Debug

etstandard2.0\myModule.dll PS C:\Users\James\myModule> Test-SampleCmdlet -? NAME Test-SampleCmdlet SYNTAX Test-SampleCmdlet [-FavoriteNumber] <int> [[-FavoritePet] {Cat | Dog | Horse}] [<CommonParameters>] ALIASES None REMARKS None PS C:\Users\James\myModule> Test-SampleCmdlet -FavoriteNumber 7 -FavoritePet Cat FavoriteNumber FavoritePet -------------- ----------- 7 Cat

This sample is pretty simple as it’s intended to just show how to get started on writing a PowerShell module from scratch. The important point is that using PowerShell Standard Library, this assembly can be used in both PowerShell Core 6 as well as Windows PowerShell. This sample will even work on Windows, Linux, or macOS without any changes.

In the next part of this series, I’ll cover other aspects of PowerShell module authoring such as module manifests and writing Pester tests.

James Truher Senior Software Engineer PowerShell Team