PowerShell with a Purpose Blog

Creating a Custom Type Extension

Take almost any object in PowerShell - a process, a service, or what have you. Pipe it to Get-Member. You'll doubtless notice properties and methods, and perhaps even an event or two. Those are the things that object was "born" with; you'll also notice additional members like ScriptProperty, ScriptMethod, AliasProperty, and so on. Those were dynamically added to the object by PowerShell's Extensible Type System, or ETS. Why? What for?

In most cases, those extensions were added to provide better consistency (giving an object a Name property when it didn't natively have one), convenience (the date/time conversion methods of any WMI object), or to make difficult-to-obtain information easier to access (the various ScriptMethods of a Process object are a good example). 

Most type extensions are defined in a file called types.ps1xml, which is located in PowerShell's installation folder. Don't modify it: It's got a Microsoft digital signature, and modifying the file will break that signature and prevent PowerShell from using it. You can, however, create your own.

In "Windows PowerShell v2: TFM (3rd Edition)" I outlined the various extensions you can define, and provide examples. Here's one: I'm adding an "IsPingable" property to the String object. To do so, I defined the extension in a file called Mine.ps1xml. I then loaded it into the shell by running "Update-TypeData -prepend Mine.ps1xml". That places my extension ahead of any Microsoft might have provided; if I'd used -append instead of -prepend, Microsoft's extensions would have had precedence over mine.

xml version="1.0" encoding="utf-8" ?>
 Types>
  Type>
    Name>System.StringName>
    Members>
      ScriptProperty>
        Name>IsPingableName>
        GetScriptBlock>
$result = test-connection $this -count 1
if ($result.statuscode -eq 0) { write $true } else { $false }
        GetScriptBlock>
      ScriptProperty>
    Members>
  Type>
Types>

With this in place, I can pipe any string to Get-Member:

"Hello" | GM 

to see the new ScriptProperty. From there, I can use it: Just run 

"localhost".IsPingable 

to test it. Of course, it'll only work if the string contains a computer name or IP address, but hopefully you get the idea. It even works if the string is in a variable:

$str = 'localhost'
$str.ispingable

This can be a powerful way to add new functionality to existing objects, in such a way that EVERY object of that type will gain your addition. 




My PowerShell home page (http://windowsitpro.com/go/donjonespowershell) offers access to the latest blog articles, along with PowerShell FAQs - why not bookmark it? You can also get the latest on Windows PowerShell in my Twitter feed @concentrateddon (http://twitter.com/concentrateddon). And, if you’d like to download recent conference materials (slide decks, scripts, etc) I’ve delivered, visit http://ConcentratedTech.com. That site also contains details on upcoming classes and conferences.
Hide comments

Comments

  • Allowed HTML tags: <em> <strong> <blockquote> <br> <p>

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.
Publish