How to call a complex COM method from PowerShell?

后端 未结 1 1373
Happy的楠姐
Happy的楠姐 2020-11-30 01:46

Is it possible to call a COM method from PowerShell using named parameters? The COM object method I am working with has dozens of parameters:

object.GridData         


        
相关标签:
1条回答
  • 2020-11-30 02:24

    This problem did interest me, so I did some real digging and I have found a solution (though I have only tested on some simple cases)!

    Concept

    The key solution is using [System.Type]::InvokeMember which allows you to pass parameter names in one of its overloads.

    Here is the basic concept.

    $Object.GetType().InvokeMember($Method, [System.Reflection.BindingFlags]::InvokeMethod,
        $null,  ## Binder
        $Object,  ## Target
        ([Object[]]$Args),  ## Args
        $null,  ## Modifiers
        $null,  ## Culture
        ([String[]]$NamedParameters)  ## NamedParameters
    )
    

    Solution

    Here is a reusable solution for calling methods with named parameters. This should work on any object, not just COM objects. I made a hashtable as one of the parameters so that specifying the named parameters will be more natural and hopefully less error prone. You can also call a method without parameter names if you want by using the -Argument parameter

    Function Invoke-NamedParameter {
        [CmdletBinding(DefaultParameterSetName = "Named")]
        param(
            [Parameter(ParameterSetName = "Named", Position = 0, Mandatory = $true)]
            [Parameter(ParameterSetName = "Positional", Position = 0, Mandatory = $true)]
            [ValidateNotNull()]
            [System.Object]$Object
            ,
            [Parameter(ParameterSetName = "Named", Position = 1, Mandatory = $true)]
            [Parameter(ParameterSetName = "Positional", Position = 1, Mandatory = $true)]
            [ValidateNotNullOrEmpty()]
            [String]$Method
            ,
            [Parameter(ParameterSetName = "Named", Position = 2, Mandatory = $true)]
            [ValidateNotNull()]
            [Hashtable]$Parameter
            ,
            [Parameter(ParameterSetName = "Positional")]
            [Object[]]$Argument
        )
    
        end {  ## Just being explicit that this does not support pipelines
            if ($PSCmdlet.ParameterSetName -eq "Named") {
                ## Invoke method with parameter names
                ## Note: It is ok to use a hashtable here because the keys (parameter names) and values (args)
                ## will be output in the same order.  We don't need to worry about the order so long as
                ## all parameters have names
                $Object.GetType().InvokeMember($Method, [System.Reflection.BindingFlags]::InvokeMethod,
                    $null,  ## Binder
                    $Object,  ## Target
                    ([Object[]]($Parameter.Values)),  ## Args
                    $null,  ## Modifiers
                    $null,  ## Culture
                    ([String[]]($Parameter.Keys))  ## NamedParameters
                )
            } else {
                ## Invoke method without parameter names
                $Object.GetType().InvokeMember($Method, [System.Reflection.BindingFlags]::InvokeMethod,
                    $null,  ## Binder
                    $Object,  ## Target
                    $Argument,  ## Args
                    $null,  ## Modifiers
                    $null,  ## Culture
                    $null  ## NamedParameters
                )
            }
        }
    }
    

    Examples

    Calling a method with named parameters.

    $shell = New-Object -ComObject Shell.Application
    Invoke-NamedParameter $Shell "Explore" @{"vDir"="$pwd"}
    
    ## the syntax for more than one would be @{"First"="foo";"Second"="bar"}
    

    Calling a method that takes no parameters (you can also use -Argument with $null).

    $shell = New-Object -ComObject Shell.Application
    Invoke-NamedParameter $Shell "MinimizeAll" @{}
    
    0 讨论(0)
提交回复
热议问题