Home > Software engineering >  Powershell Reflection Invoke with Parameters
Powershell Reflection Invoke with Parameters

Time:09-28

I am learning reflection with PowerShell at the moment and I am struggling to find how to pass parameters to a static void function in a test DLL using reflection, been at this for hours and quite possibly ran past the answer in google or here on StackOverflow? Would be amazing if the Gurus here can help me out?

Example DLL Code:

using System;
using System.Diagnostics;

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

Current Powershell code:

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

Error received:

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

Yet adding $method.Invoke($null,$null) allows execution of the PowerShell script albeit with silent failure?

CodePudding user response:

In PowerShell, you don't need reflection to access types and their members from a dynamically loaded assembly - just use PowerShell's regular syntax:

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

As an interpreted language, all type (class) and member access is in PowerShell is in effect reflection-based, behind the scenes.

You only truly need reflection techniques in user code:

  • if you don't know the names of the types and / or members you want to access ahead of time
  • if you need access to non-public types and members.

Even providing names via variables or expressions doesn't strictly require reflection in PowerShell; a simple example:

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

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

If you do want to use reflection:

# 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'))
  • Related