Reputation: 23501
I have a simple DotNet DLL like this
namespace ClassLibrary1
{
public class Class1
{
public static void Test()
{
Process.Start("CMD.exe", "/C calc");
}
}
}
When I try to load this DLL with powershell
$Path = "c:\\test\\ClassLibrary1.dll";
$Namespace = "ClassLibrary1";
$ClassName = "Class1";
$Method = "Test";
$Arguments = $null
$Full_Path = [System.IO.Path]::GetFullPath($Path);
$AssemblyName = [System.Reflection.AssemblyName]::GetAssemblyName($Full_Path)
$Full_Class_Name = "$Namespace.$ClassName"
$Type_Name = "$Full_Class_Name, $($AssemblyName.FullName)"
$Type = [System.Type]::GetType($Type_Name)
$MethodInfo = $Type.GetMethod($Method)
$MethodInfo.Invoke($null, $Arguments)
It does not work, because [System.Type]::GetType($Type_Name)
returned $null
Any ideas?
Upvotes: 2
Views: 2184
Reputation: 437558
Use Add-Type -Path
to load your assembly.
After loading, to get a reference to that assembly's [ClassLibrary1.Class1]
type as a [Type]
instance (to use for reflection) via a string variable, simply cast to [Type]
.
The following corrected and annotated version of your code demonstrates the approach:
# Compile the C# source code to assembly .\ClassLibrary1.dll
Add-Type -TypeDefinition @'
namespace ClassLibrary1
{
public class Class1
{
public static void Test()
{
System.Diagnostics.Process.Start("CMD.exe", "/C calc");
}
}
}
'@ -OutputAssembly .\ClassLibrary1.dll
# Define the path to the assembly. Do NOT use "\\" as the path separator.
# PowerShell doesn't use "\" as the escape character.
$Path = ".\ClassLibrary1.dll"
$Namespace = "ClassLibrary1"
$ClassName = "Class1"
$Method = "Test"
$Arguments = $null
# Load the assembly by its filesystem path, using the Add-Type cmdlet.
# Use of relative paths works.
Add-Type -Path $Path
$Full_Class_Name = "$Namespace.$ClassName"
# To get type [ClassLibrary1.Class1] by its full name as a string,
# simply cast to [type]
$Type = [type] $Full_Class_Name
$MethodInfo = $Type.GetMethod($Method)
$MethodInfo.Invoke($null, $Arguments)
As for what you tried:
As PetSerAl points out, [System.Type]::GetType()
can only find a given type if:
mscorlib
assembly, or an assembly located in the GAC (Global Assembly Cache).
While you could have called [System.Reflection.Assembly]::LoadFile($Full_Path)
first in order to load the assembly via its filesystem path, after which [System.Type]::GetType($Type_Name)
would have succeeded, it is ultimately simpler - and more PowerShell-idiomatic - to use Add-Type -Path
to load the assembly (which has the added advantage of not requiring a full (absolute) file path), and, once loaded, to use [Type]
with just the type's full name (no reference to the assembly needed anymore).
Upvotes: 2