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