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/