带参数的 Powershell 反射调用

Psy*_*n25 1 c# powershell

我目前正在使用 PowerShell 学习反射,并且正在努力寻找如何使用反射将参数传递给测试 DLL 中的静态 void 函数,已经研究了几个小时,很可能在 google 或 StackOverflow 上找到了答案?如果这里的大师能帮助我,那就太棒了?

DLL 代码示例:

using System;
using System.Diagnostics;

namespace ExampleProject
{
    public class Class1
    {
        public static void RunProcess(string fullFileName)
        {
            var p = new Process
            {
                 StartInfo =
                 {
                     FileName = fullFileName
                 }
            }.Start();
        }  
    }
}
Run Code Online (Sandbox Code Playgroud)

当前的Powershell代码:

$data = "C:\temp\mytestlib.dll')
$assem = [System.Reflection.Assembly]::Load($data)
$class = $assem.GetType("ExampleProject.Class1")
$method = $class.GetMethod("RunProcess")
$fullName = "C:\\Windows\\System32\\calc.exe"
$method.Invoke($null,$fullName)
Run Code Online (Sandbox Code Playgroud)

收到错误:

Exception calling "Invoke" with "2" argument(s): "Parameter count mismatch."
At line:6 char:1
+ $method.Invoke($null,$fullName)
Run Code Online (Sandbox Code Playgroud)

然而添加 $method.Invoke($null,$null) 允许执行 PowerShell 脚本,尽管会出现静默失败?

mkl*_*nt0 5

在 PowerShell 中,您不需要反射即可从动态加载的程序集中访问类型及其成员 - 只需使用 PowerShell 的常规语法

# Load the assembly
Add-Type -LiteralPath C:\temp\mytestlib.dll

# Use its types and access its members as you normally would in PowerShell.
[ExampleProject.Class1]::RunProcess('C:\Windows\System32\calc.exe')
Run Code Online (Sandbox Code Playgroud)

作为一种解释性语言, PowerShell 中的所有类型(类)和成员访问实际上都是在幕后基于反射的。

只真正需要用户代码中的反射技术:

  • 如果您不知道要提前访问的类型和/或成员的名称
  • 如果您需要访问非公共类型和成员

即使通过变量或表达式提供名称也并不严格要求在 PowerShell 中进行反射;一个简单的例子:

# The following:
[string]::Concat('foo', 'bar') # -> 'foobar'

# ... can also be expressed as:
$type = [type] 'string'
$method = 'Concat'
$type::$method('foo', 'bar')
Run Code Online (Sandbox Code Playgroud)

如果您确实想使用反射

# Load the assembly
$assembly = [System.Reflection.Assembly]::LoadFrom('C:\temp\mytestlib.dll')

# Get a reference to the type.
# Use .GetTypes() to enumerate all types.
$type = $assembly.GetType('ExampleProject.Class1')

# Get a reference to the method.
# Use .GetMethods() to enumerate all methods.
$method = $type.GetMethod('RunProcess')

# Invoke the method:
# * $null as the first argument means that no instance is to be
#   to be targeted, implying a *static* method call.
# * the second argument is an array containing the arguments
#   to pass to the methods.
$method.Invoke($null, @('C:\Windows\System32\calc.exe'))
Run Code Online (Sandbox Code Playgroud)