Compiling Binary Cmdlets

by May 21, 2014

PowerShell functions can mimick all the features found in a true binary cmdlet–but PowerShell functions are plain PowerShell code, so anyone can view it.

If you are a developer and interested in creating binary cmdlets, here is a quick starter. It illustrates how to create and compile true cmdlets with pure PowerShell:

# C# definition for cmdlet                
$code = @'
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Management.Automation;

namespace CustomCmdlet
{
    [Cmdlet("Get", "Magic", SupportsTransactions = false)]
    public class test : PSCmdlet
    {
        private int _Age;

        [Alias(new string[]
        {
            "HowOld", "YourAge"
        }), Parameter(Position = 0,ValueFromPipeline = true)]
        
        public int Age
        {
            get { return _Age; }
            set { _Age = value; }
        }

        private string _Name;

        [Parameter(Position = 1)]
        public string Name
        {
            get { return _Name; }
            set { _Name = value; }
        }


        protected override void BeginProcessing()
        {
            this.WriteObject("Good morning...");
            base.BeginProcessing();
        }
        protected override void ProcessRecord()
        {
            this.WriteObject("Your name is " + Name + " and your age is " + Age);
            base.ProcessRecord();
        }
        protected override void EndProcessing()
        {
            this.WriteObject("That's it for now.");
            base.EndProcessing();
        }
    }
}

'@


# compile C# code to DLL
# use a timestamp to create unique file names
# while testing, when a DLL was imported before, it is in use until PowerShell closes
# so to do repeated tests, use different DLL file names
$datetime = Get-Date -Format yyyyMMddHHmmssffff
$DLLPath = "$env:temp\myCmdlet($datetime).dll"
Add-Type -TypeDefinition $code -OutputAssembly $DLLPath

# import a module
Import-Module -Name $DLLPath -Verbose

Now you are ready to use the new Get-Magic cmdlet. It features all the things a cmdlet can do, including parameters, parameter aliases, and even pipeline support:

Note that the majority of PowerShell code in the example is needed only to create and compile the DLL. Once the DLL exists, all you need is this line (for example, in your shipping product):

Import-Module -Name $DLLPath

To develop sophisticated binary cmdlets, you will want to work in a C# development environment such as Visual Studio. All you need is adding a reference to the PowerShell assembly. The path to the PowerShell assembly can be easily retrieved with this line:

It will place the path to the PowerShell assembly into your clipboard.

Note that compiling a C# code by itself will not add much additional protection to your intellectual property as it can be decompiled. So do not use this to "protect" secret information such as passwords. With binary cmdets, you do get the option to use professional copy protection software and obfuscators. These extra layers of protection are not available with plain PowerShell code.

Twitter This Tip! ReTweet this Tip!