Home Made OBN

It is no secret that PowerCLI has lots of amazing options and well-thought trough features. But there is one feature that most of PowerCLI’s users take for granted, and most probably do not even realise that they are using what is called Object By Name or OBN. In this post I’ll show you one way of creating your own OBN, a home made Object By Name, which you can use in your own functions and modules.

OBN allows you to refer to a PowerCLI object by name, instead of passing an actual PowerCLI object. A classic example is “Get-VM -Datastore DS1“, where we are retrieving all VMs that live on a specific datastore. If one looks at the description of the Datastore parameter, it clearly states that a value of type StorageResource is expected, but we are able to provide the datastorename, a string. Under the cover, PowerCLI converts this string to the required PowerCLI object for the parameter.

When we are writing our own functions, it would be very handy to have the same functionality at our disposal. Define a parameter to be of the type of a PowerCLI object, but then be able to pass the name of the object, instead of the object itself.
The solution is here, with the MyOBN attribute. We now have the same functionality available, that was until now only available for PowerCLI cmdlets.

Update September 14th 2017

  • Added support for VIServer
  • Added support for arrays of objects
  • Fixed an issue with the VirtualMachine object

Some History

To have a better understanding, I’ll show some example functions.

The first function, Invoke-Test1, uses a Datastore parameter, that accepts a PowerCLI Datastore object.

If we execute this, we get the Name of the VMs that live on the datastore.

But if we try to use the name of the datastore, as we are used to doing with the Datastore parameter on the Get-VM cmdlet for example, we get an error.

To get our function to behave more like OBN on the PowerCLI cmdlets, we can define the parameter as a general PSObject object. And perform the type casting inside the function. Something like this.

Our function now works with a Datastore object

but also with a String.

Note that this way of simulating the OBN functionality is far from fool-proof. There is for example no strict type checking, we could pass a VirtualMachine object on the Datastore parameter, and our function would throw an error.

When I first read about Custom Attributes, in a blog post, named Powershell: Creating and using custom attributes, from Kevin Marquette, I immediately saw the potential to get one step closer to a proper OBN in my functions.

For now, I have implemented the Attribute as a class, which implies it’s use is limited to PowerShell v5 or higher.

The Code

 

Annotations

Line 1: this code requires PowerShell v5 or up

Line 3: we base the MyOBN class on the ArgumentTransformationAttribute class. We inherit the Transform method from this class. Our override of the Transform method will contain the logic to simulate the OBN functionality.

Line 5-8: currently the Transform method in the MyOBN class supports these PowerCLI types.

Line 11: We need a way to tell the Transform method, which objecttype we want to use. That’s why we add a property Type to the MyOBN class.

Line 9-12: the class has a constructor which allows us to initiate the Type property.

Line 13-44: the Transform method override is where all the magic happens

Line 15: we need to detect if the parameter is a String, in other words if the parameter was passed as an “Object By Name”.

Line 21: with the help of the Type property we invoke the correct PowerCLI cmdlet to convert the String to a PowerCLI obejct

Line 26-29: if the value passed to the parameter was already a PowerCLI object, we just pass that object along

Line 30-42: These lines handle the request for an array of supported objects

Sample Runs

To use this new parameter attribute is quite straightforward. Make sure the MyOBN class is loaded (this can be through dot-sourcing, adding it to your profile or just including it in your .ps1 file).

Then add the MyOBN attribute like any other parameter attribute. Make sure to specify the “Type” for which you want MyOBN to work. Like this

We can now call our function with a Datastore object

but also with a String that contains the name of the Datastore.

And all that without adding any extra code in our function, besides the MyOBN attribute.

 

Enjoy!

2 Comments

    Erwan

    Hi Luc,
    Thanks for those informations!
    I guess I did not completly understand how type’s transformation works because I facing an issue with arrays…
    In your example how could you manage the transformation of an array of datastores ?
    Regards,

      LucD

      Hi Erwan,
      You are seeing it correctly, currently the MyOBN attribute doesn’t accept arrays I’m afraid.
      The only way around is to use a wrapper function that will call the actual function for each object in the array.

      I’m currently testing some possibilities to support arrays.

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.