Categories

Creating Objects

There is a post on the PowerShell Team blog about using New-Object - http://blogs.msdn.com/powershell/archive/2009/12/05/new-object-psobject-property-hashtable.aspx

The –property parameter discussed in this post is something that I had only come across recently.  In a number of recent posts I have used Add-Type to create a new object by using C# code to define a new class rather than using New-Object and Add-Member.  The post on the team blog, plus questions I’d been asked about why I used add-type got me thinking about creating objects.

In PowerShell v1 we used to do this

001
002
003
$new1 = New-Object -TypeName PSObject
$new1 | Add-Member -Name p1 -Value 1 -MemberType NoteProperty -PassThru |
        Add-Member -Name p2 -Value "a" -MemberType NoteProperty

 

We would create an object and then use Add-Member to add the properties.  The object could then be used

001
002
003
004
$new1 | ft -AutoSize

$new1.p1 = "b"
$new1 | ft -AutoSize

 

This would give the results we expect

p1 p2
-- --
1 a

p1 p2
-- --
b  a

Notice that we have been able to change the type of p1 from an integer to a string.

In v2 we get the –property parameter on New-Object

001
002
003
004
005
$p = @{
    p1 = 1
    p2 = "a"
}
$new2 = New-Object -TypeName PSObject -Property $p

In this method we create a hash table holding the properties and the values. It can be used when we create the object so that the properties are immediately populated.  This is a neater method than the multiple calls to Add-Member we saw earlier.

The object can be used as before

001
002
003
004
$new2 | ft -AutoSize
$new2.p1 = "b"

$new2 | ft -AutoSize

 

with the following results

p2 p1
-- --
a   1

p2 p1
-- --
a  b

Again notice that we can change the type of p1.

If we want to use a PSObject and create properties then using a hash table in v2 involves less typing, looks neater and is probably easier to understand.

In a number of recent posts I have been creating a C# class rather than using PSObject. This is a better variant of that technique showed to me by Doug Finke (thanks Doug)

001
002
003
004
005
006
007
008
009
010
011
012
013
$code = @"
public class testobject {
    public int p1 {get; set;}
    public string p2 {get; set;}
}
"@

Add-Type -TypeDefinition $code -Language CSharpversion3
$p = @{
    p1 = 1
    p2 = "a"
}

$new3 = New-Object -TypeName testobject -Property $p

 

I have created a simple .NET class with our two properties. Add-Type is used to add the definition into PowerShell.  I can then create an object using a hash table for the properties. This probably looks more complicated but there is a significant difference when we come to use it

001
002
003
004
$new3 | ft -AutoSize
$new3.p1 = "b"

$new3 | ft -AutoSize

 

gives us

p1 p2
-- --
1 a

Exception setting "p1": "Cannot convert value "b" to type "System.Int32". Error: "Input string was not in a correct format.""
At line:16 char:7
+ $new3. <<<< p1 = "b"
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : PropertyAssignmentException

p1 p2
-- --
1 a

We can’t change the type of p1 because it is defined by the class we created.  This gives me an extra level of protection on what I’m doing as I can’t make a mistake and set the property to the wrong type.

PowerShell often gives us a number of ways of achieving the goal. In this case choose the one that best fits your requirements.

Technorati Tags: ,

One Response to Creating Objects

  • Dmitry says:

    Hello Richard!

    I’ve been reading your blog for a while and I find it very useful. Especially the information about Powershell 2 that you are sharing.

    I’ve been anxiously waiting for Powershell 2 release and now that it is out I feel that it suffers from a lack of well-documented best practices. In fact, many of the new features brought by Powershell 2 seem like esoteric knowledge available to a chosen few.

    One of the questions that interests me most is a way to make a background job communicate with the current session. The ability to run tasks in the background introduced in Powershell 2 is really really great, since typical scripting languages do not support threads. However, it would be even greater if there was a way for the current Powershell session to somehow communicate with the threads it creates.

    I tried to find an answer to this question. A few hours of searching the web turned up nothing. Then I found a forum thread on the stackoverflow.com site. A Microsoft MVP said that it was in fact possible to raise custom events from within a background job and act on them in the current session and promised to write a few words about it. You can find the thread here:
    http://stackoverflow.com/questions/1392699/powershell-job-progress-monitoring

    However, the man seemed to break his promise and forgot about it.

    Richard, may be you can shed some light on this? Please, please, please!

Leave a Reply