Search

my categories

Blogroll

SnapInini - Lite portable SnapIns with no need of registration/installation.

June 7th, 2008 by Karl

One thing that has bothered me about true cmdlets in contrast scripts is that they lived in SnapIns and couldn’t be deployed with xcopy as scripts can because SnapIns required Registration/Installation. I build my own way to deal with this need some time ago, and thought that I’d start a blog series covering it. I call them Snapininis or SnapIn-Lites.

 

So how does this work?

1) you have to load an assembly into memory in powershell that contains your snapin.
2) you add the cmdlets directly into the runspace that is running and tell powershell to update its list of cmdlets.

Here is the C# code for a sample barebones SnapInini.

using System;
using System.Collections.Generic;
using System.Text;
using System.Management.Automation;
using System.Management.Automation.Runspaces;
 
namespace Snapinini
{
    public class DynamicCmdLet
    {
        public static void Load()
        {
            CmdletConfigurationEntry conf = new CmdletConfigurationEntry("dummy-cmdlet", typeof(ForeachDictionaryCmdLet), null);
            Runspace.DefaultRunspace.RunspaceConfiguration.Cmdlets.Append(conf);
            Runspace.DefaultRunspace.RunspaceConfiguration.Cmdlets.Update();
            Runspace.DefaultRunspace.CreateNestedPipeline(
                "new-alias dcmd dummy-cmdlet; write-host ’snapinini loaded’", 
                false).Invoke();
        }
    }
    [Cmdlet("dummy", "cmdlet")]
    public class ForeachDictionaryCmdLet : System.Management.Automation.PSCmdlet
    {
        protected override void EndProcessing()
        {
            WriteObject("hello from the dummy cmdlet");
        } 
    }
}

In the above sample I have a very very simple cmdlet. You can see that i get the defaultrunspace, go into its RunspaceConfiguration and add the cmdlets and update the list. I am additionally running some powershell script that adds an alias to the cmdlet and writes a message to the screen just as an example showing you that you can do more stuff if you wish. In the above code the load is a static method so its easy to call from powershell once you’ve loaded the assembly, but in all honesty the Load() code could just as well have been written in the calling PowerShell.

So how do we load and use this in PowerShell?

[system.Reflection.Assembly]::LoadFrom("snapinini.dll")
[snapinini.DynamicCmdLet]::load()
dummy-cmdlet
dcmd

 

Where to from here? This example is very simple, you could easily add multiple cmdlets into the equation, specify help files, add custom type definitions etc. Another thing I had experimented with is taking a real snapin and using reflection to see the cmdlets in it and adding them directly, however unless you know exactly what a snapin does this is dangerous because in its registration it might set up a bunch of other things also that are important.

Another thing I should cover next time is a safe way to load assemblies from any location and ensure that all their references get resolved seamlessly.

-Karl

Posted in Powershell |

Leave a Comment

Please note: Comment moderation is enabled and may delay your comment. There is no need to resubmit your comment.