使用powershell加载C#DLL,[System.Type] :: GetType返回null

时间:2018-07-29 04:34:00

标签: c# powershell

我有一个像这样的简单DotNet DLL

namespace ClassLibrary1
{
    public class Class1
    {
        public static void Test()
        {
           Process.Start("CMD.exe", "/C calc"); 
        }
    }
}

当我尝试使用Powershell加载此DLL

$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)

它不起作用,因为[System.Type]::GetType($Type_Name)返回了$null

有什么想法吗?

1 个答案:

答案 0 :(得分:1)

  • 使用 Add-Type -Path 加载程序集

  • 加载后,要通过 string变量[ClassLibrary1.Class1]实例的形式引用该程序集的[Type]类型(用于反射),只需< strong>广播到[Type]

以下经过更正和注释的代码版本演示了该方法:

# 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)

关于您尝试过的事情

PetSerAl指出,[System.Type]::GetType()仅在以下情况下才能找到给定类型:

  • 其程序集已加载
  • 它的程序集可以通过标准的程序集分辨率进行定位,如详细的here所述,其中涉及许多复杂的规则,其中只有两个适用于您的方案,如果您要引用一个 mscorlib程序集或 GAC (全局程序集缓存)中的程序集的-in 类型。
    • 根据定义,只有重命名程序集-用与程序集全名中提到的公钥匹配的私钥签名的程序集-可以放置在GAC中。

虽然您可以先调用[System.Reflection.Assembly]::LoadFile($Full_Path)才能通过其文件系统路径加载程序集,然后[System.Type]::GetType($Type_Name)成功了,但最终使用{ {1}}加载程序集(具有不需要完整(绝对)文件路径的附加优势),并且在加载后仅使用类型完整的Add-Type -Path名称(不再需要引用程序集)。