MIM 2016: Perform AD Functions in FIM/MIM Workflow without importing the AD PS Module – Part I

MIM/FIM workflow engine is compiled with Dotnet 3.5, don’t ask me why it has not been re-compiled in Dotnet 4. Anyway if you try introducing a library that is compiled in Dotnet 4.0 or greater you will get a failure message. The Active Directory PowerShell module version 3.0 and greater is compiled in Dotnet 4.0 and greater, this means you cannot call it in the MIM/FIM PowerShell workflow window.  You have 2 options.

  1. You can run the PS script outside the workflow engine. See this blogpost
  2. You can use the DirectoryServices library to interact with AD within the workflow engine.

I will show you how you can use option 2. I have built these three functions using the Directory Service library which should cover most of the operations you would do in AD. In part II, I will expose some more functions.

For the get-ADDomainController use

Function GetADDC

{

$root=[system.directoryservices.activedirectory.domain]::GetCurrentDomain()

$context=new-object System.DirectoryServices.ActiveDirectory.DirectoryContext(“Domain”,$root)

$domainController=[System.DirectoryServices.ActiveDirectory.DomainController]::findOne($context)

Return $domainController

}

For the Get-ADUser/Get-ADObject use

Function GetADObject

{

PARAM($FilterString)

END

{

$strFilter = $FilterString

#$strFilter = “((samaccountname=$myAccountName))”

$objDomain=$null

$objSearcher=$null

Try{

$objDomain = New-Object System.DirectoryServices.DirectoryEntry

$objSearcher = New-Object System.DirectoryServices.DirectorySearcher

$objSearcher.SearchRoot = $objDomain

$objSearcher.PageSize = 1000

$objSearcher.Filter = $strFilter

$objSearcher.SearchScope = “Subtree”

$existingObject = $objSearcher.FindAll()

If ($existingObject.count -ne 1)

{

throw (“Error setting the user in AD, User not found: ” + $strFilter)

}

Else

{

$myuser=$existingObject.GetDirectoryEntry()

Return $myuser

}

}

Finally{

#Dispose the searcher to prevent memory leak

if ($objDomain -ne $null)

{

$objDomain.Dispose()

}

if ($objSearcher -ne $null)

{

$objSearcher.Dispose()

}

}

}

For the Set-ADUser/Set-ADObject use

Function SetADObject

{

PARAM($FilterString, $DomainController, $attributeToUpdate, $attributeValue)

END

{

$strFilter = $FilterString

#$strFilter = “((samaccountname=$myAccountName))”

$objDomain=$null

$objSearcher=$null

Try{

$objDomain = New-Object System.DirectoryServices.DirectoryEntry

$objSearcher = New-Object System.DirectoryServices.DirectorySearcher

$objSearcher.SearchRoot = $objDomain

$objSearcher.PageSize = 1000

$objSearcher.Filter = $strFilter

$objSearcher.SearchScope = “Subtree”

$existingObject = $objSearcher.FindAll()

If ($existingObject.count -ne 1)

{

throw (“Error setting the user in AD, User not found: ” + $strFilter)

}

Else

{

#Bind to the object

$tmpObj=$existingobject.GetDirectoryEntry()

$tmpObj.Put($attributeToUpdate,$AttributeValue)

$tmpObj.SetInfo()

}

}

Finally{

#Dispose the searcher to prevent memory leak

if ($objDomain -ne $null)

{

$objDomain.Dispose()

}

if ($objSearcher -ne $null)

{

$objSearcher.Dispose()

}

}

}

}

So here is an example of the use of some of the functions

#Check what is my DC
$myDC=getaddc
write-host $myDC

#Check if lastname is present
$myAccountName=”cballoma”
$myfilter = “((samaccountname=$myAccountName))”
$myuser=getADObject $myfilter
write-host $myuser.sn
If ($myuser.sn -ne $null){write-host “Account has a lastname”}