【问题标题】:Loading C# DLL with powershell, [System.Type]::GetType returns null使用 powershell 加载 C# DLL,[System.Type]::GetType 返回 null
【发布时间】:2018-07-29 04:33:59
【问题描述】:

我有一个像这样的简单 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

有什么想法吗?

【问题讨论】:

  • 您没有加载程序集。 [System.Type]::GetType 不会加载程序集,除非它位于 GAC 或程序集搜索路径中。
  • 您可能需要使用LoadFilestackoverflow.com/questions/3079346/…

标签: c# powershell


【解决方案1】:
  • 使用 Add-Type -Path加载您的程序集

  • 加载后,要通过字符串变量获取对该程序集的[ClassLibrary1.Class1]类型的引用作为[Type]实例(用于反射),只需转换为[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(全局程序集缓存)中的程序集。
    • 根据定义,只有强命名程序集(使用与程序集全名中提到的公钥匹配的私钥签名的程序集)可以放入 GAC。

虽然您可以先调用 [System.Reflection.Assembly]::LoadFile($Full_Path) 以通过其文件系统路径加载程序集,然后 [System.Type]::GetType($Type_Name) 会成功,但使用 Add-Type -Path 加载最终更简单 - 并且更符合 PowerShell 习惯程序集(它具有不需要完整(绝对)文件路径的额外优势),并且一旦加载,就可以使用 [Type] 仅带有 type's 全名(不需要对程序集的引用不再)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-12-17
    • 2013-04-27
    • 2012-11-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多