PowerShell: Hashtables and Objects   Leave a comment

I use hash tables all the time – they’re dead useful and when we were building PowerShell I used them as surrogate objects.  However, they don’t quite behave like an object – display is problematic and it’s tougher to add methods, etc, so, how do I get what I want?  There are a couple of ways to add functionality to the PowerShell environment. Scripts and functions are the usual way to add to a shell environment, but one of the things I really like about PowerShell is the dynamic nature of the snapin model. This allows me to add cmdlets and providers to my environment – and since one of the things I use all the time is a hashtable as an object, I figured that I would create a hashtable converterto do the trick.   The converter itself could be done as a script (and is left as an excercise for the reader)
using System;
using System.ComponentModel;
using System.Collections.ObjectModel;
using System.Collections.Generic;
using System.Management.Automation;
using System.Management.Automation.Runspaces;

namespace System.Management.Automation.Demos
{
    // This class defines the properties of a snapin
    [RunInstaller(true)]
    public class ConversionCmdlets : PSSnapIn
    {
        /// <summary>Creates an instance of DemoSnapin class.</summary>
        public ConversionCmdlets() : base()
        {
        }
        ///<summary>The snapin name which is used for registration</summary>
        public override string Name
        { get
            { return "ConversionCmdlets";
            }
        }
        /// <summary>Gets vendor of the snapin.</summary>
        public override string Vendor
        { get
            { return "Vendor String - JWT";
            }
        }
        /// <summary>Gets description of the snapin. </summary>
        public override string Description
        { get
            { return "This snapin contains demo conversion cmdlets";
            }
        }
        private string[] formats = null;

        public override string[] Formats
        { get 
            { return formats;
            }
        }
    }
}

That’s the code that allows me to create a snapin, now I need the actual cmdlet code
using System;
using System.Management.Automation;
using System.Collections;
using System.Collections.ObjectModel;

namespace JWT.Conversion.Cmdlets
{
    [Cmdlet("Convert","HashToObject")]
    public class ConvertHashToObjectCommand : PSCmdlet
    {
        private Hashtable hash;
        [Parameter(Mandatory=true,Position=0,ValueFromPipeline=true)]
        public Hashtable Hash
        {
            get { return hash; }
            set { hash = value; }
        }
        private String[] name = { "ConvertedHashTable" };
        [Parameter(Position=1)]
        public String[] Names
        {
            get { return name; }
            set { name = value; }
        }
        protected override void ProcessRecord()
        {
            PSObject obj = new PSObject();
            // Go through each key and create a property and
            // assign the value to the new property.
            // In the case that the value is a script block, create
            // a ScriptMethod instead.
            foreach ( string key in Hash.Keys )
            {
                if ( Hash[key].GetType().Name == "ScriptBlock" )
                    obj.Methods.Add(
                        new PSScriptMethod(key,(ScriptBlock)Hash[key])
                        );
                else
                    obj.Properties.Add(
                        new PSNoteProperty(key, Hash[key])
                        );
            }
            // update the type names for the new object
            Collection<string> tnames = new Collection<string>();
            obj.TypeNames.Clear();
            foreach ( string tname in Names )
            {
                obj.TypeNames.Add(tname);
            }
            WriteObject(obj);
        }
    }
}

Then I built a script to build and install the snapin
# make.ps1
# build my ConversionCmdlets PowerShell
$out          = "Conversion-Cmdlets.dll"
$src          = "convert-HashToObject.cs","convert-snapin.cs"
$ref          = "${pshome}/system.management.automation.dll"
$frameworkDir = "${env:windir}/Microsoft.Net/Framework/v2.0.50727"
$csc          = "${frameworkDir}/csc.exe"
$installutil  = "${frameworkDir}/installutil.exe"
&$csc /target:library /out:$out /r:$ref $src
if ( ! (test-path $out) )
{
    Write-Host -red "$out could not be built"
    exit
}
&$installutil $out > install.out 2> install.err
$snapin = get-pssnapin -reg | where {$_.modulename -match $out}
if ( ! $snapin )
{
    Write-Host -red "$out could not be installed"
    exit
}
else
{
    "Snapin created and installed"
}

Here’s what it looks like when you use it!
PS> add-pssnapin ConversionCmdlets
PS> get-command convert-hashtoobject

CommandType     Name                            Definition
-----------     ----                            ----------
Cmdlet          Convert-HashToObject            Convert-HashToObject [-Hash]...

PS> $a = @{A=1;B=2;C={$this.A};D={$this.A=$args[0]}}|convert-hashtoobject
PS> $a|format-table -auto
A B
- -
1 2
PS> $a.C()
1
PS> $a.D(10)
PS> $a|format-table -auto
 A B
 - -
10 2
PS> $A.C()
10
PS>
Advertisements

Posted May 5, 2006 by jtruher3 in PowerShell

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: