Usually we can build out a new instance of a .Net object we have to use New-Object and pass the required parameters to accomplish this. Or at least that is the most common approach to the subject. We can also use [activator] type as well to build out the same instance with a little bit better performance. Both of these are compatible since at least V2 (I don’t deal with V1, so someone who still has this running can verify in the comments). And even sometimes you can use a hash table with a .Net type to build out the instance as well (works well with WPF and WinForms).

Refresher

We need to find a .Net type that will make for a good demo. For this I will go with Net.Sockets.TCPClient as it allows some extra arguments to supply if needed.

I now need to see what kind of parameters are available with this type. I can find this easily by using my Get-Constructor function that I wrote back here.

Get-Constructor Net.Sockets.TcpClient

I can see 4 possible constructor possibilities here. For the sake of examples, I will use the last one requiring a hostname and a port to check against.

On a side note, if you wanted to see how many .Net types have constructors, you can give this a run:

[appdomain]::CurrentDomain.GetAssemblies() | ForEach {$_.GetExportedTypes() | Where { $_.GetConstructors() }} | Select -Expand FullName | Sort | Out-Host -Paging

New-Object Approach

This is the most common approach that 99% of everyone in PowerShell uses when they create a .Net instance (or COM object, but I am not focused on COM today). Using New-Object is simple to use, just run the cmdlet, pass the .Net type and any arguments, if required.

New-Object Net.Sockets.TcpClient –ArgumentList $Env:Computername, 135

[activator] Approach

This is a lesser known (OK, probably more like almost unknown) approach that you can use to create both a .Net instance or COM object. This is done by using the [Activator] type accelerator and using the CreateInstance() method.

There are a lot of possible method parameters here, but the one I am focused on is the use of the Type and System.Object[] parameters to add the required values in the creation of the object.

[Activator]::CreateInstance([Net.Sockets.TcpClient], @($Env:Computername,135))

Same as New-Object, I connect to the system and validate that port 135 is open.

What’s NEW

Now for the new approach to performing the same thing as what we have done with New-Object and [Activator]::CreateInstance(). In PowerShell V5 (currently in September Preview at the time of this post), all .Net types have an added New() operator which allows you to construct .Net instances more easily. More than just that, you also now have a way to see the possible constructor parameter options as well.

Just like with my function, we can see the actual parameter name as well as the type that the parameter is expecting to be passed into it. So, in this case, I will use the same approach as before and supply the required parameters to do a port check.

[Net.Sockets.TcpClient]::New($Env:Computername, 135)

Perfect! As you can see, I get the exact same output as the previous approaches. So can this be used for anything that has an available constructor? Well, for the most part, you can. I have found at least one instance where there appears to be some sort of issue. For some reason, DateTime throws a casting error when using PSCreateInstanceBinder. I’m not sure why this is happening, but asked the question on the MVP mailing list and will provide an answer when I hear back from someone on whether this is a bug or something else. (08 SEPT 2014): This was confirmed as a bug by the PowerShell team.

Performance Testing

The last thing I wanted to see with this is which one is the fastest to build out the .Net instance. I wanted to use DateTime as the type, but since that one has some flawed issues with the New() method, I am going with Net.Sockets.TcpClient and supplying no parameters to make sure the test is as clean as possible in just creating an object that is waiting for some action. So with that I ran a quick check…

{$Time = (1..1E5 | ForEach { (Measure-Command { New-Object Net.Sockets.TcpClient }).TotalMilliseconds } | Measure-Object -Average).Average [pscustomobject]@{ Name = “New-Object” Type = 'Net.Sockets.TCPClient' Cycles = 100000 MillisecondsSeconds = [math]::Round($Time,4) } $Time = (1..1E5 | ForEach { (Measure-Command { [Activator]::CreateInstance([Net.Sockets.TcpClient]) }).TotalMilliseconds } | Measure-Object -Average).Average [pscustomobject]@{ Name = “[Activator]::CreateInstance()” Type = 'Net.Sockets.TCPClient' Cycles = 100000 MillisecondsSeconds = [math]::Round($Time,4) } $Time = (1..1E5 | ForEach { (Measure-Command { [Net.Sockets.TcpClient]::New() }).TotalMilliseconds } | Measure-Object -Average).Average [pscustomobject]@{ Name = “[&lt;Type&gt;]::New()” Type = 'Net.Sockets.TCPClient' Cycles = 100000 MillisecondsSeconds = [math]::Round($Time,4) }}.InvokeReturnAsIs() | Format-Table -AutoSize

… and got the following results:

The Activator approach has an incredibly small performance difference than with using the New() operator. In fact, those two could go either way (and in fact they did on multiple tests). But the bigger thing to notice is that New-Object is slower than both of them. In the big scheme of things, it really isn’t that big of a performance impact, but if you are looking to squeeze as much performance as you can from your scripts, then either New() or [activator]::CreateInstance() would be the way to go. Note that [activator] is good with PowerShell V2 for backwards compatibility on your scripts.