.NET Core,  dotNet,  Powershell,  VSCode

Powershell Core binary module with Visual Studio Code

I wrote countless scripts and a good amount of modules (and functions) in my years as Service Engineer but all of them are script modules, I never really created binary modules. The main reason is that I like to write in Powershell but I also like the fact that, not being a compiled language, it is very easy to share and modify the source code for a script module and it is immediately ready to be reloaded and used. Anyway out of curiosity and to learn a different approach to building modules, I decided to try to convert one of mine from script to binary; my first step was (of course) a quick search to find some samples and getting started articles and I found a few good ones (referenced below) but all of them use Visual Studio and the full version of the .NET Framework, while I want to use Visual Studio Code and .NET Core. So here’s what I came up with.

First off of course I need .NET Core (I am using the latest .NET Core 3 preview 8 at the moment), Visual Studio Code and the C# Extension. Next, I’m going to create a Class Library project using dotnet at the command line; note the -f parameter to indicate the framework version I want to use:

PS > dotnet new classlib -f netcoreapp3.0 -o HelloWorldCore
Couldn't find an installed template that matches the input, searching online for one that does...
Matches from template source: NuGet
-----------------------------------
Template name "Razor Class Library" (razorclasslib) from author "Microsoft" in pack Microsoft.DotNet.Web.ProjectTemplates.2.2
    To use this template, run the following command and try again:
        dotnet new -i Microsoft.DotNet.Web.ProjectTemplates.2.2::2.2.6

Since I am attempting this command on a fresh installation I am missing some templates but luckily dotnet suggests the command to run to fix this problem:

PS > dotnet new -i Microsoft.DotNet.Web.ProjectTemplates.2.2::2.2.6
  Restore completed in 1.73 sec for C:\Users\carlo\.templateengine\dotnetcli\v3.0.100-preview8-013656\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".
  --dry-run           Displays a summary of what would happen if the given command line were run if it would result in a template creation.
  --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.
  --update-check      Check the currently installed template packs for updates.
  --update-apply      Check the currently installed template packs for update, and install the updates.


Templates                                         Short Name               Language          Tags
----------------------------------------------------------------------------------------------------------------------------------
Console Application                               console                  [C#], F#, VB      Common/Console
Class library                                     classlib                 [C#], F#, VB      Common/Library
WPF Application                                   wpf                      [C#], VB          Common/WPF
WPF Class library                                 wpflib                   [C#], VB          Common/WPF
WPF Custom Control Library                        wpfcustomcontrollib      [C#], VB          Common/WPF
WPF User Control Library                          wpfusercontrollib        [C#], VB          Common/WPF
Windows Forms (WinForms) Application              winforms                 [C#], VB          Common/WinForms
Windows Forms (WinForms) Class library            winformslib              [C#], VB          Common/WinForms
Worker Service                                    worker                   [C#]              Common/Worker/Web
Unit Test Project                                 mstest                   [C#], F#, VB      Test/MSTest
NUnit 3 Test Project                              nunit                    [C#], F#, VB      Test/NUnit
NUnit 3 Test Item                                 nunit-test               [C#], F#, VB      Test/NUnit
xUnit Test Project                                xunit                    [C#], F#, VB      Test/xUnit
Razor Component                                   razorcomponent           [C#]              Web/ASP.NET
Razor Page                                        page                     [C#]              Web/ASP.NET
MVC ViewImports                                   viewimports              [C#]              Web/ASP.NET
MVC ViewStart                                     viewstart                [C#]              Web/ASP.NET
Blazor Server App                                 blazorserver             [C#]              Web/Blazor
ASP.NET Core Empty                                web                      [C#], F#          Web/Empty
ASP.NET Core Web App (Model-View-Controller)      mvc                      [C#], F#          Web/MVC
ASP.NET Core Web App                              webapp                   [C#]              Web/MVC/Razor Pages
ASP.NET Core with Angular                         angular                  [C#]              Web/MVC/SPA
ASP.NET Core with React.js                        react                    [C#]              Web/MVC/SPA
ASP.NET Core with React.js and Redux              reactredux               [C#]              Web/MVC/SPA
Razor Class Library                               razorclasslib            [C#]              Web/Razor/Library/Razor Class Library
ASP.NET Core Web API                              webapi                   [C#], F#          Web/WebAPI
ASP.NET Core gRPC Service                         grpc                     [C#]              Web/gRPC
dotnet gitignore file                             gitignore                                  Config
global.json file                                  globaljson                                 Config
NuGet Config                                      nugetconfig                                Config
Dotnet local tool manifest file                   tool-manifest                              Config
Web Config                                        webconfig                                  Config
Solution File                                     sln                                        Solution
Protocol Buffer File                              proto                                      Web/gRPC

Examples:
    dotnet new mvc --auth Individual
    dotnet new nunit-test
    dotnet new --help

Now I can re-run the dotnet new command:

PS > dotnet new classlib -f netcoreapp3.0 -o HelloWorldCore
The template "Class library" was created successfully.

Processing post-creation actions...
Running 'dotnet restore' on HelloWorldCore\HelloWorldCore.csproj...
  Restore completed in 70.99 ms for C:\Users\carlo\Git\HelloWorldCore\HelloWorldCore.csproj.

Restore succeeded.


PS > Get-ChildItem -Recurse

    Directory: C:\Users\carlo\Git\HelloWorldCore

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d----           8/19/2019  4:59 PM                bin
d----           8/19/2019  4:59 PM                obj
-a---           8/19/2019  4:44 PM             91 Class1.cs
-a---           8/19/2019  4:44 PM            144 HelloWorldCore.csproj

    Directory: C:\Users\carlo\Git\HelloWorldCore\bin

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d----           8/19/2019  4:59 PM                Debug

    Directory: C:\Users\carlo\Git\HelloWorldCore\bin\Debug

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d----           8/19/2019  4:59 PM                netcoreapp3.0

    Directory: C:\Users\carlo\Git\HelloWorldCore\obj

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d----           8/19/2019  4:59 PM                Debug
-a---           8/19/2019  4:44 PM            149 HelloWorldCore.csproj.nuget.cache
-a---           8/19/2019  4:44 PM           2253 HelloWorldCore.csproj.nuget.dgspec.json
-a---           8/19/2019  4:44 PM           1166 HelloWorldCore.csproj.nuget.g.props
-a---           8/19/2019  4:44 PM            294 HelloWorldCore.csproj.nuget.g.targets
-a---           8/19/2019  4:44 PM           2268 project.assets.json

    Directory: C:\Users\carlo\Git\HelloWorldCore\obj\Debug

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d----           8/19/2019  4:59 PM                netcoreapp3.0

    Directory: C:\Users\carlo\Git\HelloWorldCore\obj\Debug\netcoreapp3.0

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a---           8/19/2019  4:59 PM           1015 HelloWorldCore.AssemblyInfo.cs
-a---           8/19/2019  4:59 PM             42 HelloWorldCore.AssemblyInfoInputs.cache
-a---           8/19/2019  4:59 PM            188 HelloWorldCore.assets.cache
-a---           8/19/2019  4:59 PM             42 HelloWorldCore.csproj.CoreCompileInputs.cache
-a---           8/19/2019  4:59 PM         109810 HelloWorldCore.csprojAssemblyReference.cache

Even with .NET Core I still need to add a reference to the System.Management.Automation assembly, which is available as a nuget package. Visual Studio Code has a thriving marketplace with tons of very useful extension so I decided to check if something was available to help with this scenario and sure enough I found a number of suitable extensions. I went for NuGet Package Manager and I added a reference to System.Management.Automation version 6.2.2 to match my .NET Core version

add nuget package

Now I can import the System.Management.Automation namespace, decorate the class with the Cmdlet attribute, have it inherit from Cmdlet and override the ProcessRecord() method; for this sample I don’t need to be too fancy with my code so here it is:

using System.Management.Automation;

namespace HelloWorldCore
{
    [Cmdlet(VerbsCommon.Get, "HelloWorld")]
    public class Class1 : Cmdlet
    {
        private string _name;
        [Parameter(Mandatory = true)]
        public string Name
        {
            get { return _name; }
            set { _name = value; }
        }

        protected override void ProcessRecord()
        {
            WriteObject("Hey " + this.Name);
        }
    }
}

Next step, build the project and generate the .dll I will later import in my Powershell session; to do that I could use dotnet at the command line or use a VSCode extension such as Dotnet core commands

PS > dotnet build --configuration Debug
Microsoft (R) Build Engine version 16.3.0-preview-19377-01+dd8019d9e for .NET Core
Copyright (C) Microsoft Corporation. All rights reserved.

  Restore completed in 1.63 sec for C:\Users\carlo\Git\HelloWorldCore\HelloWorldCore.csproj.
  You are using a preview version of .NET Core. See: https://aka.ms/dotnet-core-preview
  HelloWorldCore -> C:\Users\carlo\Git\HelloWorldCore\bin\Debug\netcoreapp3.0\HelloWorldCore.dll

Build succeeded.
    0 Warning(s)
    0 Error(s)

Time Elapsed 00:00:02.76
build project

Finally, these are a few pointers to get started building binary Powershell modules


You cannot help men permanently by doing for them what they could and should do for themselves. – Abraham Lincoln

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.