Use PowerShell to wrap an existing COM object

前端 未结 2 1670
死守一世寂寞
死守一世寂寞 2020-12-16 03:17

Using PowerShell and System.DirectoryServices, I\'ve been given an object that looks like this:

   TypeName: System.__ComObject

Name                    


        
相关标签:
2条回答
  • 2020-12-16 04:01

    PowerShell reflection doesn't properly "see" these objects' properties and methods. To get to the properties and methods, I use some wrapper functions. Here is an example:

    function Get-Property {
      param(
        [__ComObject] $object,
        [String] $propertyName
      )
      $object.GetType().InvokeMember($propertyName,"GetProperty",$NULL,$object,$NULL)
    }
    
    function Set-Property {
      param(
        [__ComObject] $object,
        [String] $propertyName,
        $propertyValue
      )
      [Void] $object.GetType().InvokeMember($propertyName,"SetProperty",$NULL,$object,$propertyValue)
    }
    
    function Invoke-Method {
      param(
        [__ComObject] $object,
        [String] $methodName,
        $methodParameters
      )
      $output = $object.GetType().InvokeMember($methodName,"InvokeMethod",$NULL,$object,$methodParameters)
      if ( $output ) { $output }
    }
    
    $ADS_ESCAPEDMODE_ON = 2      # see ADS_ESCAPE_MODE_ENUM
    $ADS_SETTYPE_DN = 4          # see ADS_SETTYPE_ENUM
    $ADS_FORMAT_X500_PARENT = 8  # see ADS_FORMAT_ENUM
    
    $Pathname = New-Object -ComObject "Pathname"
    # store initial EscapedMode
    $escapedMode = Get-Property $PathName "EscapedMode"
    # Enable all escaping
    Set-Property $PathName "EscapedMode" @($ADS_ESCAPEDMODE_ON)
    Invoke-Method $Pathname "Set" @("CN=Ken Dyer,OU=H/R,DC=fabrikam,DC=com",$ADS_SETTYPE_DN)
    Invoke-Method $Pathname "Retrieve" @($ADS_FORMAT_X500_PARENT)
    # outputs 'OU=H\/R,DC=fabrikam,DC=com'
    $escapedMode = Set-Property $PathName "EscapedMode" @($escapedMode)
    # set EscapedMode property back to initial value
    

    Note that the Set-Property and Invoke-Method use an array as their final parameter, so I use @( ) when calling those functions.

    0 讨论(0)
  • 2020-12-16 04:05

    Just a little different approach then Bill Stewart’s:

    The idea is that usually you do not need/want to create multiple instances of the ComObject:

    Function Invoke-ComObject([Parameter(Mandatory = $true)]$ComObject, [Switch]$Method, [Parameter(Mandatory = $true)][String]$Property, $Value) {
        If ($ComObject -IsNot "__ComObject") {
            If (!$ComInvoke) {$Global:ComInvoke = @{}}
            If (!$ComInvoke.$ComObject) {$ComInvoke.$ComObject = New-Object -ComObject $ComObject}
            $ComObject = $ComInvoke.$ComObject
        }
        If ($Method) {$Invoke = "InvokeMethod"} ElseIf ($MyInvocation.BoundParameters.ContainsKey("Value")) {$Invoke = "SetProperty"} Else {$Invoke = "GetProperty"}
        [__ComObject].InvokeMember($Property, $Invoke, $Null, $ComObject, $Value)
    }; Set-Alias ComInvoke Invoke-ComObject
    

    If it concerns a method, you need to add the –Method switch, in the case of a property, the cmdlet will automatically determine whether the property need to be get or set depending on whether a value is supplied. With this cmdlet you do not require the to create the ComObject first and retrieve e.g. to get the ComputerName (DN) from ADSystemInfo in a simple oneliner:

    ComInvoke ADSystemInfo ComputerName
    

    To do a the same with the PathName:

    $EscapedMode = ComInvoke PathName EscapedMode
    ComInvoke PathName EscapedMode @($ADS_ESCAPEDMODE_ON)
    ComInvoke Pathname -Method Set @("CN=Ken Dyer,OU=H/R,DC=fabrikam,DC=com", $ADS_SETTYPE_DN)
    ComInvoke Pathname -Method Retrieve @($ADS_FORMAT_X500_PARENT)
    ComInvoke PathName EscapedMode @($EscapedMode)
    

    A name NameTranslate example:

    ComInvoke -Method NameTranslate Init @(1, "domain.com")
    ComInvoke -Method NameTranslate Set @(8, "User001")
    ComInvoke -Method NameTranslate Get @(1)
    

    Or if you do want to have multiple instances you can first create the ComObject instance and then supply it to the ComInvoke function:

    $NameTranslate = New-Object -ComObject NameTranslate
    ComInvoke -Method $NameTranslate Init @(1, "domain.com")
    ComInvoke -Method $NameTranslate Set @(8, "User001")
    ComInvoke -Method $NameTranslate Get @(1)
    

    For the latest Invoke-ComObject version, see: https://powersnippets.com/invoke-comobject/

    0 讨论(0)
提交回复
热议问题