{"id":14275,"date":"2018-08-06T13:03:09","date_gmt":"2018-08-06T20:03:09","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/powershell\/?p=14275"},"modified":"2019-02-26T18:01:27","modified_gmt":"2019-02-27T02:01:27","slug":"powershell-standard-library-build-single-module-that-works-across-windows-powershell-and-powershell-core","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/powershell\/powershell-standard-library-build-single-module-that-works-across-windows-powershell-and-powershell-core\/","title":{"rendered":"PowerShell Standard Library: Build single module that works across Windows PowerShell and PowerShell Core"},"content":{"rendered":"<p>This is the first of a series of blog posts that will help you take advantage of a new NuGet package\u00a0<a href=\"https:\/\/www.nuget.org\/packages\/PowerShellStandard.Library\" rel=\"nofollow\">PowerShellStandard Library 5.1.0<\/a>. 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!<\/p>\n<p>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\u00a0<a href=\"https:\/\/www.nuget.org\/packages\/PowerShellStandard.Library\/3.0.0-preview-02\" rel=\"nofollow\">PowerShell Standard Library v3<\/a>\u00a0is 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.<\/p>\n<h2><a id=\"user-content-creating-a-powershell-module\" class=\"anchor\" href=\"#creating-a-powershell-module\"><\/a>Creating a PowerShell Module<\/h2>\n<p>In this post, I&#8217;ll walk through the steps for creating a simple C# module with a single cmdlet. I will also be using the\u00a0<a href=\"https:\/\/docs.microsoft.com\/en-us\/dotnet\/core\/tools\/?tabs=netcore2x\" rel=\"nofollow\">DotNet CLI<\/a>\u00a0tools for creating everything I need.<\/p>\n<h3><a id=\"user-content-installing-the-powershell-standard-module-template\" class=\"anchor\" href=\"#installing-the-powershell-standard-module-template\"><\/a>Installing the PowerShell Standard Module Template<\/h3>\n<p>First, we can leverage a new template that we published for DotNet CLI, but we need to install it first:<\/p>\n<div class=\"highlight highlight-source-powershell\">\n<pre class=\"lang:default decode:true\">PS&gt; dotnet new -i Microsoft.PowerShell.Standard.Module.Template\r\n  Restoring packages for C:\\Users\\James\\.templateengine\\dotnetcli\\v2.1.302\\scratch\\restore.csproj...\r\n  Installing Microsoft.PowerShell.Standard.Module.Template 0.1.3.\r\n  Generating MSBuild file C:\\Users\\James\\.templateengine\\dotnetcli\\v2.1.302\\scratch\\obj\\restore.csproj.nuget.g.props.\r\n  Generating MSBuild file C:\\Users\\James\\.templateengine\\dotnetcli\\v2.1.302\\scratch\\obj\\restore.csproj.nuget.g.targets.\r\n  Restore completed in 1.66 sec for C:\\Users\\James\\.templateengine\\dotnetcli\\v2.1.302\\scratch\\restore.csproj.\r\n\r\nUsage: new [options]\r\n\r\nOptions:\r\n  -h, --help          Displays help for this command.\r\n  -l, --list          Lists templates containing the specified name. If no name is specified, lists all templates.\r\n  -n, --name          The name for the output being created. If no name is specified, the name of the current directory is used.\r\n  -o, --output        Location to place the generated output.\r\n  -i, --install       Installs a source or a template pack.\r\n  -u, --uninstall     Uninstalls a source or a template pack.\r\n  --nuget-source      Specifies a NuGet source to use during install.\r\n  --type              Filters templates based on available types. Predefined values are \"project\", \"item\" or \"other\".\r\n  --force             Forces content to be generated even if it would change existing files.\r\n  -lang, --language   Filters templates based on language and specifies the language of the template to create.\r\n\r\n\r\nTemplates                                         Short Name         Language          Tags                             \r\n----------------------------------------------------------------------------------------------------------------------------\r\nConsole Application                               console            [C#], F#, VB      Common\/Console                   \r\nClass library                                     classlib           [C#], F#, VB      Common\/Library                   \r\nPowerShell Standard Module                        psmodule           [C#]              Library\/PowerShell\/Module    \r\n...<\/pre>\n<\/div>\n<p>A new template called\u00a0<code>psmodule<\/code>\u00a0is 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\u00a0<a href=\"https:\/\/github.com\/powershell\/powershellstandard\">PowerShell Standard repo<\/a>.<\/p>\n<h3><a id=\"user-content-creating-a-new-project\" class=\"anchor\" href=\"#creating-a-new-project\"><\/a>Creating a new project<\/h3>\n<p>We need to create a location for our new project and then use the template to create the project:<\/p>\n<div class=\"highlight highlight-source-powershell\">\n<pre class=\"lang:default decode:true\">PS&gt; mkdir myModule\r\nDirectory: C:\\Users\\James\r\nMode LastWriteTime Length Name\r\n---- ------------- ------ ----\r\nd----- 8\/3\/2018 2:41 PM myModule\r\nPS&gt; cd myModule\r\nPS C:\\Users\\James\\myModule&gt; dotnet new psmodule\r\nThe template \"PowerShell Standard Module\" was created successfully.\r\n\r\nProcessing post-creation actions...\r\nRunning 'dotnet restore' on C:\\Users\\James\\myModule\\myModule.csproj...\r\n  Restoring packages for C:\\Users\\James\\myModule\\myModule.csproj...\r\n  Installing PowerShellStandard.Library 5.1.0-preview-06.\r\n  Generating MSBuild file C:\\Users\\James\\myModule\\obj\\myModule.csproj.nuget.g.props.\r\n  Generating MSBuild file C:\\Users\\James\\myModule\\obj\\myModule.csproj.nuget.g.targets.\r\n  Restore completed in 1.76 sec for C:\\Users\\James\\myModule\\myModule.csproj.\r\n\r\nRestore succeeded.<\/pre>\n<\/div>\n<p>You can see that the dotnet cli has created a source file and .csproj file for my project:<\/p>\n<div class=\"highlight highlight-source-powershell\">\n<pre class=\"lang:default decode:true\">PS C:\\Users\\James\\myModule&gt; dir\r\n\r\n\r\n    Directory: C:\\Users\\James\\myModule\r\n\r\n\r\nMode                LastWriteTime         Length Name\r\n----                -------------         ------ ----\r\nd-----         8\/3\/2018   1:48 PM                obj\r\n-a----         8\/3\/2018   1:48 PM            376 myModule.csproj\r\n-a----         8\/3\/2018   1:48 PM           1698 TestSampleCmdletCommand.cs<\/pre>\n<\/div>\n<p>The sample from the template demonstrates a simple cmdlet with two parameters that outputs results with a custom class.<\/p>\n<h3><a id=\"user-content-building-the-module\" class=\"anchor\" href=\"#building-the-module\"><\/a>Building the module<\/h3>\n<p>Building the sample is code is easy with DotNet CLI:<\/p>\n<div class=\"highlight highlight-source-powershell\">\n<pre class=\"lang:default decode:true\">PS C:\\Users\\James\\myModule&gt; dotnet build\r\nMicrosoft (R) Build Engine version 15.7.179.6572 for .NET Core\r\nCopyright (C) Microsoft Corporation. All rights reserved.\r\n\r\n  Restore completed in 76.85 ms for C:\\Users\\James\\myModule\\myModule.csproj.\r\n  myModule -&gt; C:\\Users\\James\\myModule\\bin\\Debug\\netstandard2.0\\myModule.dll\r\n\r\nBuild succeeded.\r\n    0 Warning(s)\r\n    0 Error(s)\r\n\r\nTime Elapsed 00:00:05.40<\/pre>\n<\/div>\n<h3><a id=\"user-content-testing-the-built-module\" class=\"anchor\" href=\"#testing-the-built-module\"><\/a>Testing the built module<\/h3>\n<p>To test this sample module, we just need to import it. We can check to see what it supports and try running it:<\/p>\n<div class=\"highlight highlight-source-powershell\">\n<pre class=\"lang:default decode:true\">PS C:\\Users\\James\\myModule&gt; ipmo .\\bin\\Debug\\netstandard2.0\\myModule.dll\r\nPS C:\\Users\\James\\myModule&gt; Test-SampleCmdlet -?\r\n\r\nNAME\r\n    Test-SampleCmdlet\r\n\r\nSYNTAX\r\n    Test-SampleCmdlet [-FavoriteNumber] &lt;int&gt; [[-FavoritePet] {Cat | Dog | Horse}] [&lt;CommonParameters&gt;]\r\n\r\n\r\nALIASES\r\n    None\r\n\r\n\r\nREMARKS\r\n    None\r\n\r\n\r\n\r\nPS C:\\Users\\James\\myModule&gt; Test-SampleCmdlet -FavoriteNumber 7 -FavoritePet Cat\r\n\r\nFavoriteNumber FavoritePet\r\n-------------- -----------\r\n             7 Cat<\/pre>\n<\/div>\n<p>This sample is pretty simple as it&#8217;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.<\/p>\n<p>In the next part of this series, I&#8217;ll cover other aspects of PowerShell module authoring such as module manifests and writing Pester tests.<\/p>\n<p>James Truher\nSenior Software Engineer\nPowerShell Team<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This is the first of a series of blog posts that will help you take advantage of a new NuGet package\u00a0PowerShellStandard 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 [&hellip;]<\/p>\n","protected":false},"author":685,"featured_media":13641,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[],"class_list":["post-14275","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-powershell"],"acf":[],"blog_post_summary":"<p>This is the first of a series of blog posts that will help you take advantage of a new NuGet package\u00a0PowerShellStandard 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 [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/posts\/14275","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/users\/685"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/comments?post=14275"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/posts\/14275\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/media\/13641"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/media?parent=14275"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/categories?post=14275"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/tags?post=14275"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}