Using PowerShell and System.DirectoryServices
, I\'ve been given an object that looks like this:
TypeName: System.__ComObject
Name
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.
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/