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\netstandard2.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\netstandard2.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