This article offers an in-depth exploration of two internal PowerShell functions: “Invoke-CvCommand” and “Get-CvAdObject”. These functions are designed to help you perform tasks more efficiently when dealing with multiple forests.
Introduction
The “Invoke-CvCommand” and “Get-CvAdObject” commands are essential components of our system, created to handle customized PowerShell instructions. “Invoke-CvCommand” serves as an enhanced wrapper for the “Invoke-Command” cmdlet, while “Get-CvAdObject” wraps the “Get-AdObject” cmdlet.
Use of “Invoke-CvCommand”
“Invoke-CvCommand” executes commands on remote computers, akin to the “Invoke-Command” cmdlet, but with some differences.
Parameters
typeEnv
This parameter defines the environment for command execution. It accepts two values: ActiveDirectory and Exchange.
scriptblock
It specifies the commands to run. Given that typeEnv can accept ActiveDirectory or Exchange, a script block must not contain a mix of Active Directory and Exchange commands. Each script block should contain cmdlets for only one context.
argumentLists
It provides the values of parameters for the script block. The parameters in the script block are passed by position from the array value supplied to argumentLists.
source
It identifies the source used to establish a remote PowerShell session. The source can be a distinguished name, a security identifier (SID), or a fully qualified domain name (Fqdn).
externalFunctionsNames
It provides an array of function names that can be used in the script block.
Example 1: Invoke a command using a script block stored in a variable without any parameters.
In this example, the script block does not require any parameters, so we can exclude the argumentLists argument from the Invoke-CvCommand. The script block contains an Active Directory command: Get-AdUser, so the Invoke-CvCommand specifies the value ActiveDirectory as typeEnv. The Invoke-CvCommand uses a distinguished name as the source.
$sb = {
param()
Get-AdUser -Identity "CN=user,OU=OU_1,DC=Contoso,DC=local" | Select-Object
UserPrincipalName
}
$job = Invoke-CvCommand -typeEnv ActiveDirectory -scriptBlock $sb -source
"CN=user,OU=OU_1,DC=Contoso,DC=local"
return $job
The Invoke-CvCommand uses a FQDN as the source:
$fqdn = "Contoso.DC1.Local"
$sb = {
param()
Get-AdUser -Identity "CN=test user,OU=OU_1,DC=Contoso,DC=local" | Select-Object
UserPrincipalName
}
$job = Invoke-CvCommand -typeEnv ActiveDirectory -scriptBlock $sb -source $fqdn
return $job
The Invoke-CvCommand uses a SID as the source:
$UserSid = "S-1-5-21-507672319-2510724776-1356001139-3178"
$sb = {
param()
Get-AdUser -Identity "CN=test user,OU=OU_1,DC=Contoso,DC=local" | Select-Object
UserPrincipalName
}
$job = Invoke-CvCommand -typeEnv ActiveDirectory -scriptBlock $sb -source $userSid
return $job
Example 2: Invoke a command using a script block and the argumentLists parameter to pass variable values.
In this scenario, the Param keyword and the argumentLists parameter are used to pass variable values to a script block. The Invoke-CvCommand uses a script block that defines a single variable: $var1. The Get-AdUser cmdlet uses the named parameter Identity with the variable name. The argumentLists passes the values to the variable.
$userDn = "CN=user,OU=OU_1,DC=Contoso,DC=local"
$sb = {
param($var1)
Get-AdUser -Identity $var1 | Select-Object UserPrincipalName
}
$job = Invoke-CvCommand -typeEnv ActiveDirectory -scriptBlock $sb -argumentLists $userDn
-source $userDn
return $job
Example 3: Invoke a command that includes the Credential parameter
In this example, the Invoke-CvCommand automatically passes the appropriate credential object to the script block, specifying a PsCredential object named $cred as the last variable in the Param.
$userDn = "CN=test,OU=OU_1,DC=Contoso,DC=local"
$sb = {
param($var1, [System.Management.Automation.PSCredential]$cred)
Get-AdUser -Identity $var1 -Credential $cred | Select-Object UserPrincipalName
}
$job = Invoke-CvCommand -typeEnv ActiveDirectory -scriptBlock $sb -argumentLists $userDn
-source $userDn
return $job
Example 4: Invoke a script block with external PowerShell functions
This example demonstrates how to include external PowerShell functions within a script block. Split-DisplayName is a PowerShell function defined outside the script block, it accepts the parameter $displayName and calls the Split method. The ExternalFunctionsNames can be used to include one or more PowerShell functions into a script block as an array. In this example, we're passing an array containing a single element: “Split-DisplayName”.
Note: you can pass the helper functions described in the following article: Custom action cheat sheet.
function Split-DisplayName( $displayName){
$split = $displayName.Split(" ", [System.StringSplitOptions]::RemoveEmptyEntries)
return $split[0]
}
$userDn = "CN=test user,OU=OU_1,DC=Contoso,DC=local"
$displayName = "test user"
$sb = {
param($displayName, [System.Management.Automation.PSCredential]$cred)
$firstName = Split-DisplayName -displayName $displayName
Get-AdUser -Filter "givenName -eq '$firstName'" -Credential $cred | Select-Object
UserPrincipalName
}
$job = Invoke-CvCommand -typeEnv ActiveDirectory -scriptBlock $sb -argumentLists
$displayName -source $userDn -externalFunctionsNames "Split-DisplayName"
return $job
Example 5: Invoke a script block with on-premises Exchange commands
This example illustrates how to invoke the on-premises Exchange cmdlet in a script block. The on-premises Exchange cmdlets must specify the prefix “onprem”; for example, the “Get-User” cmdlet becomes “Get-onpremUser” in the script block.
$userDn = "CN=user test,OU=OU_1,DC=Contoso,DC=local"
$sb = {
param($var1)
Get-onpremRemoteMailbox -Identity $var1 | Select-Object RecipientTypeDetails
}
$job = Invoke-CvCommand -typeEnv Exchange -scriptBlock $sb -argumentLists $userDn -
source $userDn
return $job
Example 6: Get the domain controller from a source
This example demonstrates how to retrieve and use the domain controller. The DomainController parameter is only available in on-premises Exchange and specifies the domain controller used by a cmdlet to read or write data to Active Directory. Get-CvFqdnFromForestCache can retrieve the domain controller from a distinguished name or a security identifier.
Note: this example is applicable only in an “Organizational forest model.”
$userDn = "CN=user test,OU=OU_1,DC=Contoso,DC=local"
$domainController = Get-CvFqdnFromForestCache -target $userDn
$sb = {
param( $identity, $domainController)
$user = Get-onpremUser -Identity $identity -DomainController $domainController |
Select-Object DistinguishedName
$recipientType = Get-onpremRemoteMailbox -Identity $user.DistinguishedName -
DomainController $domainController
return $recipientType
}
$job = Invoke-CvCommand -typeEnv Exchange -scriptBlock $sb -argumentLists "user test",
$domainController -source $userDn
return $job
Use of “Get-CvAdObject”
The “Get-CvAdObject” function is designed to fetch a single Active Directory object by leveraging the Global Catalog. The Global Catalog is a centralized information repository for an entire forest in Active Directory. It contains a partial representation of every object, so the Get-CvAdObject can help to identify objects without requiring a reference that pinpoints the domain that stores the complete version of the object. When a client sends a request to the Global Catalog, it connects via port 3269. By default, the Global Catalog is accessed over port 3268 for standard LDAP queries, and port 3269 for LDAP
over SSL.
Note: This function may take some time to locate an object. Therefore, it’s recommended to use the Invoke-CvCommand cmdlet frequently.
Parameters
typeAdObject
This parameter determines the type of object to retrieve. It can accept one of the following values: User, Group, and Contact.
target
It specifies the Full Qualified Domain Name (FQDN) of the forest where the search will be executed.
identity
It defines the identity to be retrieved. Depending on the “typeAdObject” set, the identity can be:
- “sAMAccountName”, “UserPrincipalName” or “objectGUID” if the typeAdObject is set to “User”;
- “sAMAccountName” if typeAdObject is set to “Group”;
- “Name” or “Mail” field if typeAdObject is set to “Contact”.
Example 1: Retrieve user information using UserPrincpalName as identity
$target = "Contoso.DC1.Local"
$upn = "user@contoso.com"
$params = @{
"typeAdObject" = "User"
"target" = $target
"Identity" = $upn
}
return Get-CvAdObject @params
This command retrieves and displays a subset of information for the user identified by “user@contoso.com”.
Example 2: Retrieve group information using sAMAccountName as identity
$target = "Contoso.DC1.Local"
$group = "group test"
$params = @{
"typeAdObject" = "Group"
"target" = $target
"Identity" = $group
}
return Get-CvAdObject @params
Example 3: Retrieve contact information using Mail as identity
$target = "Contoso.DC1.Local"
$mailContact = "user@contoso.onmicrosoft.com"
$params = @{
"typeAdObject" = "Contact"
"target" = $target
"Identity" = $mailContact
}
return Get-CvAdObject @params
Output
The Output will include the following properties: “RunspaceId”, “DistinguishedName”, “Name”,
“ObjectClass” and “ObjectGUID”.