Use PowerShell to wrap an existing COM object Use PowerShell to wrap an existing COM object powershell powershell

Use PowerShell to wrap an existing COM object


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 escapingSet-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.


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 EscapedModeComInvoke 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 NameTranslateComInvoke -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/