Creating a .NET object / psObject
An instance of a
.NET object is created by specifying the
type of a .NET Framework class. The optional
-typeName argument can be used to explicitly mark the argument as a type name.
PS C:\> $webClient = new-object System.Net.WebClient
PS C:\> $webClient.GetType().FullName
System.Net.WebClient
PS C:\> $webClient.psObject.GetType().FullName
System.Management.Automation.PSObject
PS C:\> $webClient.psObject.ImmediateBaseObject.GetType().FullName
System.Net.WebClient
Constructor
If the .NET object to be created does not provide a default constructor, the arguments to the constructor need to be passed after the type name:
$txt = new-object System.String 'Hello world'
psObject
PS C:\> $obj = new-object psObject
PS C:\> $obj.GetType().FullName
System.Management.Automation.PSCustomObject
With new-object psObject, PowerShell also creates a PSObject with ImmediateBaseObject referencing the PSCustomObject.
Beware of particularities of argument parsing mode
One of the main differences of these
parsing modes is that
argument parsing mode does not recognize the type reference (for example
[System.Console]) but assumes it to be a string.
Thus, if a method on a type is called to fill an argument to the constructor of the object being created, such a type reference must be enclosed in parenthesis:
$obj = new-object type.name ( [Another.type.name]::method() )
Creating an object from inline C-Sharp code
The
add-type cmdLet allows to compile
C# classes that then can be created in PowerShell:
add-Type -typedef @'
using System;
namespace tq84 {
public class CLS {
private String txt;
public void writeTxt() {
Console.WriteLine("txt is {0}", txt);
}
public CLS(String txt_) {
txt = txt_;
}
}
}
'@
$obj_1 = new-object tq84.CLS 'Hello world'
$obj_2 = new-object tq84.CLS 'The number is 42'
$obj_1.writeTxt()
#
# txt is Hello world
$obj_2.writeTxt()
#
# txt is The number is 42
-property
An object with such an interface can be created with the
@{ … } syntax (which creates a
hash table.
psObject
In the following example, a Powershell custom object is created with the property names and values of the hash table ($probs) that is first created:
$props = @{
num = 42
txt ='Hello world'
}
$props.GetType().FullName
#
# System.Collections.Hashtable
$obj = new-object psObject -property $props
$obj | get-member -memberType noteProperty
#
# TypeName: System.Management.Automation.PSCustomObject
#
# Name MemberType Definition
# ---- ---------- ----------
# num NoteProperty int num=42
# txt NoteProperty string txt=Hello world
#
# The properties of the object can
# now be changed
#
$obj.num = 4
$obj | format-table
#
# num txt
# --- ---
# 4 Hello world
.NET class
This example is similar to the previous one, but this time a «real»
.NET class is created. This class already has the two properties
num and
txt. Thus, the member type of the properties is
property as opposed to
noteProperty in
psObject objects:
add-Type -typedef @'
using System;
public class XYZ {
public int num;
public String txt;
}
'@
$props = @{
num = 4
txt ='four'
}
$obj_1 = new-object XYZ -property $props
#
# Note: the memberType we're looking for is
# property, not noteProperty:
#
$obj_1 | get-member -memberType property
#
# TypeName: XYZ
#
# Name MemberType Definition
# ---- ---------- ----------
# num Property int num {get;set;}
# txt Property string txt {get;set;}
Instantiating an object from a DLL
The following simple example tries to demonstrate how a class from a
DLL can be used in
PowerShell.
First, we need to create such a DLL. Here's the
C# source code:
namespace TQ84 {
public class Obj {
private string name_;
public Obj(string name) {
name_ = name;
System.Console.WriteLine("Obj's constructor was called");
}
public static int twice(int a) {
return 2*a;
}
public void saySomeThing(string someThing) {
System.Console.WriteLine(name_ + " says " + someThing);
}
}
}
The source code is compiled into a DLL (-target:library):
PS C:\path\to\somewhere > csc -nologo -target:library .\obj.cs
In order to use the class, the DLL needs to be added to the current
PowerShell session:
PS C:\path\to\somewhere > add-type -path 'obj.dll'
Static methods can be called without instantiating a class.
PS C:\path\to\somewhere > [TQ84.Obj]::twice(21)
However, member methods require an object, which is what new-object creates.
When the object is created, its constructor is automatically called. Because the constructor contains a System.Console.WriteLine statement, Obj's constructor was called is printed.
PS C:\path\to\somewhere > $obj_1 = new-object TQ84.Obj one
Obj's constructor was called
PS C:\path\to\somewhere > $obj_2 = new-object TQ84.Obj two
Obj's constructor was called
Now, that the objects have been created, we can use them:
PS C:\path\to\somewhere > $obj_1.saySomeThing('eins')
one says eins
PS C:\path\to\somewhere > $obj_2.saySomeThing('zwei')
two says zwei
Error message: Cannot find type …: verify that the assembly containing this type is loaded
Some assemblies need to be explicitly added to a PowerShell session in order to use them, otherwise, an Cannot find type …: verify that the assembly containing this type is loaded error is thrown:
PS C:\> $bmp = new-object Drawing.Bitmap 200, 40
new-object : Cannot find type [Drawing.Bitmap]: verify that the assembly containing this type is loaded.o
… etc. etc. …
PS C:\> add-type -assembly 'System.Drawing'
PS C:\> $bmp = new-object Drawing.Bitmap 200, 40