Chat now with support
Chat with Support

On Demand Migration Current - Entra ID for Devices User Guide

Troubleshooting

  • Problem: A workstation that has been successfully cutover no longer responds to any additional jobs, such as Cleanup.  

    Solution: If a workstation that has been successfully cutover now fails to respond to any additional jobs, such as Cleanup, check the Application event log. If you see a "The remote name could not be resolved" error, this most likely means that the SRV record for the Entra ID for Devices Server can no longer be resolved due to a DNS lookup failure.

    If you cannot "Ping" the Entra ID for Devices server from any other machines in the target domain, then you will need to remedy this on a more global scale, such as creating a conditional forwarder on the target machines' current DNS server pointing to the appropriate location.

    If you are able to "Ping" the Entra ID for Devices server, then check the Network Profile that was used during the Cutover to verify that the DNS settings were correct in that profile.

Cutover Job Result Codes

Result Code Error Rollback Possible
1 Unidentified Error - PowerShell Command Error No
2 Source Domain could not be contacted No
4 Bad Source Credentials No
8 Target Domain could not be contacted No
16 Bad Target Credentials No
32 Target DNS Server could not be contacted or could not resolve the target DNS domain No
64 Change Obtain DNS by DHCP  
128 Set DNS Server IPs  
256 Set WINS Servers  
512 Register NIC with DNS  
1024 Clear DNS Suffix Search List / Set to use NIC  
2048 Set Alternate DNS Suffix List  
4096 Enable Dynamic DNS Registration  
8192 Set NIC Specific DNS Suffix  
16384 Domain Disjoin Failed  
32768 Domain Join Failed  
65536 Source domain name does not match the system's domain No
131072 Computer Reboot failed  
262144 Target Domain Name could not be resolved via existing DNS, and new DNS Servers were not provided No

Note: An odd numbered result code represents an error running the Cutover PowerShell script. The most common cause of an odd numbered result code during Cutover is that the computer either has no network card with a default gateway or more than one network card with a default gateway.

Note: Result codes are additive. There are likely multiple errors if the result code is not represented in the table.

Upload Logs Result Codes

This table includes result codes for BT-UploadLogs PowerShell jobs.

Result Code Error Rollback Possible
32 (zip folder) could not be created. No
64 Failed to Zip log files on computer. No
128 Upload failed to contact the server. Please verify the URL (url) is correct and BITS is enabled. No

CSV Import File Script

Import File Script Guide
### A.) AD Express mapper helper script
 
- script contains functions which helps user to convert the AD object search results into .csv mapping files
- documentation will explain only the function that is correlated to AD Express mapping for EntraId for Device
 
1. ADConvertToCsv function
- helps organize the search result into .csv list files or .csv mapping files
- called by adding to AD object search pipeline:
 
<AD object search command> | ADConvertToCsv
(AD object search commands are explained in section C.)
 
- will create .csv file to the current script directory from the search result
- if "-Path" is specified, will create file in the path (... | ADConvertToCsv -Path "C:\Users\userx\objects.csv")
- if "-Append" switch is specified, will append existing file (must be called with -Path)
- if "-EntraId" switch is specified, will create mapping file required by ADExpress EntraId for Device
- supports powershell AD(on-prem) and microsoft graph (cloud) search command results
- does not support powershell AzureAD (cloud) search command results, because of deprecated state and insufficient functionality 
 
### B.) INSTRUCTIONS
 
1. prepare powershell window
-for getting AD on-prem objects (section C.1.)
    - available by default
    - any version (https://learn.microsoft.com/en-us/powershell/module/activedirectory/?view=windowsserver2022-ps&source=recommendations)
 
-for getting AD cloud objects via microsoft graph (section C.2.)
    - https://learn.microsoft.com/en-us/powershell/microsoftgraph/installation?view=graph-powershell-1.0
    - powershell version 5.1 and higher (powershell 7 recommended)
    - powershell 7 installation guide https://learn.microsoft.com/en-us/powershell/scripting/install/installing-powershell-on-windows?view=powershell-7.4
 
2. Import script to the current powershell session
- run powershell
- move to directory where helper script is located (find directory/folder in UI -> shift-rightmouseclick -> "copy as path"
"cd <directory_path>"
- load script
". .\BT-ADObjectMapper.ps1"
 
3. Create mapping file with source (on-prem) objects filled 
 
-this will create .csv mapping file with source objects filled (on-prem) and empty target objects 
-this requires rights to search through on-prem AD
-function ADConvertToCsv will require switch "-Source" and "-EntraId" to be used
    - "-Source" specifies that we want to create mapping file and fill source objects
    - "-EntraId" specifies that we want to create mapping file for "ADExpress for EntraId"
-use section C.1. to learn about AD on-prem object search commands
-when creating mapping file for DEVICEs, do not continue with step 4. and 5. The mapping file for DEVICEs is final with step 3.
 
-structure:
<AD object search command> |  ADConvertToCsv -Source -EntraId
 
-example:
Get-ADUser -Filter * -SearchBase "OU=Finance,OU=UserAccounts,DC=FABRIKAM,DC=COM"   |   ADConvertToCsv -Source -EntraId
 
 
4. Create object file with target (cloud) objects
 
-this step is required for USERs and GROUPs, not to be used for DEVICEs
-this will create standalone file with target objects that will need to be matched with source objects in next step
-requires rights to search through cloud AD
-function ADConvertToCsv does not require any switch for this step
-use section C.2. to learn about AD cloud object search commands
 
-structure:
<AD cloud object search command> | ADConvertToCsv
 
-example:
Get-MgUser -All | ADConvertToCsv
 
5. Map source objects to target objects
 
-this step is required for USERs and GROUPs, not to be used for DEVICEs
-match objects in the mapping file the way you want
-need to manually map target objects from object file created in step 4 to the source objects in the mapping file created in step 3
-copy respective attributes of object in the mapping file to columns prefixed with "Target"
 
 
### C.) AD Object search commands
 
#C.1. AD (on-premises)
 
C.1.0 Filtering Local objects
-Filter <query>
specifies query string that retrieves AD objects
-SearchBase <path> 
specifies Active Directory path to search under
 
#examples:
Get-ADUser -Filter * -SearchBase "OU=Finance,OU=UserAccounts,DC=FABRIKAM,DC=COM"
-gets all users (specified by -Filter *) in the container "OU=Finance,OU=UserAccounts,DC=FABRIKAM,DC=COM"
 
Get-ADUser -Filter 'SamAccountName -like "*test"' -SearchBase "OU=Finance,OU=UserAccounts,DC=FABRIKAM,DC=COM"
-gets all users, which have SamAccountName ending with "test" in the container "OU=Finance,OU=UserAccounts,DC=FABRIKAM,DC=COM"
 
*more in doc links
 
C.1.1 USER
function:
Get-AdUser (https://learn.microsoft.com/en-us/powershell/module/activedirectory/get-aduser?view=windowsserver2022-ps)
example:
Get-ADUser -Filter * -SearchBase "OU=Finance,OU=UserAccounts,DC=FABRIKAM,DC=COM"| ADConvertToCsv
 
C.1.2 GROUP
function:
Get-ADGroup (https://learn.microsoft.com/en-us/powershell/module/activedirectory/get-adgroup?view=windowsserver2022-ps)
example:
Get-ADGroup -Filter * -SearchBase "OU=Finance,OU=UserAccounts,DC=FABRIKAM,DC=COM" | ADConvertToCsv
 
C.1.3 DEVICE 
function:
Get-ADComputer (https://learn.microsoft.com/en-us/powershell/module/activedirectory/get-adcomputer?view=windowsserver2022-ps)
example:
Get-ADComputer -Filter * -SearchBase "OU=Finance,OU=UserAccounts,DC=FABRIKAM,DC=COM" | ADConvertToCsv
 
 
#C.2 AD (cloud) using Microsoft Graph 
 
C.2.0 Filtering Cloud objects using Microsoft Graph
before calling any function we need to call Connect-MgGraph to connect to the azure entra id (https://learn.microsoft.com/en-us/powershell/module/microsoft.graph.authentication/connect-mggraph?view=graph-powershell-1.0)
 
-All
returns all users
 
-Filter <filter>
allows for OData v3.0 filtering (https://www.odata.org/documentation/odata-version-3-0/odata-version-3-0-core-protocol/#queryingcollections)
 
-Search <phrase>
search items by search phrases
 
-examples:
Get-MgUser -Filter "startsWith(DisplayName, 'a')"
-search users which displayname starts with "a" (case-insensitive)
Get-MgUser -Search '"Mail:Peter"'
-search users which email adress contains "Peter"
 
*more in doc links
 
C.2.1 USER
function:
Get-MgUser (https://learn.microsoft.com/en-us/powershell/module/microsoft.graph.users/get-mguser?view=graph-powershell-1.0&preserve-view=true)
example:
Connect-MgGraph -Scopes 'User.Read.All' (to get permissions and choose entra id- interactive login)
Get-MgUser -All | ADConvertToCsv
 
C.2.2 GROUP
function:
Get-MgGroup (https://learn.microsoft.com/en-us/powershell/module/microsoft.graph.groups/get-mggroup?view=graph-powershell-1.0)
example:
Connect-MgGraph -Scopes 'Group.Read.All' (to get permissions and choose entra id- interactive login)
Get-MgGroup -All | ADConvertToCsv
 
C.2.3 DEVICE
function:
Get-MgDevice (https://learn.microsoft.com/en-us/powershell/module/microsoft.graph.identity.directorymanagement/get-mgdevice?view=graph-powershell-1.0)
example:
Connect-MgGraph -Scopes 'Device.Read.All' (to get permissions and choose entra id- interactive login)
Get-MgDevice -All | ADConvertToCsv
 
*to switch entra id
-disconnect
Disconnect-MgGraph
-connect to a different one
Connect-MgGraph -Scopes <required_scopes>

 

Import File Script
function ADConvertToCsv() #Used to convert AD(onprem/cloud) objects (users,groups,devices/computers) to a .csv list for AD Express mapping file.
{
    Param(
        [Parameter(
            Mandatory=$true, 
            ValueFromPipeline=$true)]
        $InputObject, #Can take input from pipeline
 
        [Parameter(Mandatory=$false)] 
        [string]$Path, #Path to output .csv file, if not provided, output will be created in current ps directory
 
        [Parameter(Mandatory=$false)]
        [switch]$Append, #Appends existing .csv file (-Path must be specified)
 
        [Parameter(Mandatory=$false)]
        [switch]$Source, #To create template mapping file with input as source objects
 
        [Parameter(Mandatory=$false)]
        [switch]$EntraId #To create mapping file for 'EntraID for Device' (can only be used in conjunction with -Source switch)
    )
    Begin
    {
        #append or rewrite
        if ($Append)
        {
            if (!$Path)
            {
                Throw "[ERROR]: Path must be specified (-Path) in order to append existing file."
            }
            elseif (!(Test-Path $Path))
            {
                Throw "[ERROR]: File does not exist. It needs to exist in order to be appended."
            }
 
            $saveOperationType = @{ Append = $true }
        }
        else {
            $saveOperationType = @{ Force = $true }
        }
 
        #specify output path
        $outputPath = ""
        if ($Path)
        {
            $outputPath = $Path
        }
        else
        {
            if ($Source)
            {
                $outputPath = "$PSScriptRoot\object_mapping_file_" + [DateTime]::Now.ToString('yyyy_MM_dd_HH_mm_ss') + ".csv"
            }
            else 
            {
                $outputPath = "$PSScriptRoot\object_list_" + [DateTime]::Now.ToString('yyyy_MM_dd_HH_mm_ss') + ".csv"
            }
        }
 
        if ($EntraId -and (-not $Source))
        {
            Throw "[ERROR]: Switch -EntraId can only be used in conjunction with -Source switch."
        }
 
        $inputList = @()
        $inputType = ""
        $uniqueDomainList = @()
 
    }
    Process
    {
        if ($InputObject)
        {
            #make sure the type is allowed and all objects are of same type
            if ($inputType -eq "")
            {
                $inputType = $InputObject.GetType().FullName
 
                if ($EntraId) #switch only for on-prem objects for 'EntraID for Device'
                {
                    if ($inputType -notin @("Microsoft.ActiveDirectory.Management.ADUser", 
                                        "Microsoft.ActiveDirectory.Management.ADGroup", 
                                        "Microsoft.ActiveDirectory.Management.ADComputer"))
                    {
                        Throw "[ERROR]: Type $inputType is not one of the accepted types."
                    }
                }
                else 
                {
                    if ($inputType -notin @("Microsoft.ActiveDirectory.Management.ADUser", 
                                            "Microsoft.ActiveDirectory.Management.ADGroup", 
                                            "Microsoft.ActiveDirectory.Management.ADComputer", 
                                            "Microsoft.Graph.PowerShell.Models.MicrosoftGraphUser",
                                            "Microsoft.Graph.PowerShell.Models.MicrosoftGraphGroup",
                                            "Microsoft.Graph.PowerShell.Models.MicrosoftGraphDevice",
                                            "Microsoft.Open.AzureAD.Model.User", 
                                            "Microsoft.Open.AzureAD.Model.Group", 
                                            "Microsoft.Open.AzureAD.Model.Device"))
                    {
                        Throw "[ERROR]: Type $inputType is not one of the accepted types."
                    }
                }
            }
            elseif ($InputObject.GetType().FullName -ne $inputType)
            {
                Throw "[ERROR]: Type $($InputObject.GetType().FullName) is not the same type as previous $inputType."
            }
 
            if ($EntraId) #get DC from distinguished name and get domain info
            {
                $dnList = $InputObject.DistinguishedName -split '(?<!\\),' | Where-Object { $_ -like "DC*" }
                $dnDC = $dnList -join ","
 
                if ($uniqueDomainList.DNPath -notcontains $dnDC)
                {
                    $result = Get-ADDomain -Identity $dnDC
                    if (-not $result)
                    {
                        Throw "[ERROR]: Domain not found for object " + $InputObject.Name
                    }
 
                    $domainObject = [PSCustomObject]@{
                        DNPath = $dnDC
                        NetBIOSName = $result.NetBIOSName
                        DomainName = $result.Name
                    }
 
                    $uniqueDomainList += $domainObject
                }
                else
                {
                    $domainObject = $uniqueDomainList | Where-Object {$_.DNPath -eq $dnDC}
                }
 
                $InputObject | Add-Member -NotePropertyName NetBIOSName -NotePropertyValue $domainObject.NetBIOSName -Force
                $InputObject | Add-Member -NotePropertyName DomainName -NotePropertyValue $domainObject.DomainName -Force
            }
 
            $inputList += $InputObject
        }
    }
    End 
    {
 
        if ($inputList.Count -eq 0)
        {
            Write-Host "[INFO]: There are no records. Csv file will not be created."
            return
        }
 
        #transform input into .csv file
        switch ($inputType)
        {
            "Microsoft.ActiveDirectory.Management.ADUser" 
            {
                if ($Source)
                {
                    if ($EntraId)
                    {
                        $inputList | 
                            Select-Object -Property @{Name="SourceObjectId"; Expression={$_.ObjectGUID}}, `
                                @{Name="SourceUserPrincipalName"; Expression={$_.UserPrincipalName}}, `
                                @{Name="SourceSamAccountName"; Expression={$_.SamAccountName}}, `
                                @{Name="SourceNetBIOSName"; Expression={$_.NetBIOSName}}, `
                                @{Name="SourceDomainName"; Expression={$_.DomainName}}, `
                                @{Name="SourceObjectSID"; Expression={$_.SID}}, `
                                @{Name="TargetObjectId"; Expression={""}}, `
                                @{Name="TargetUserPrincipalName"; Expression={""}}, `
                                @{Name="TargetSamAccountName"; Expression={""}}, `
                                @{Name="Comments (Optional)"; Expression={""}} |
                                    Export-Csv -Path $outputPath -Delimiter "," -NoTypeInformation @saveOperationType
                    }
                    else
                    {
                        $inputList | 
                            Select-Object -Property @{Name="SourceObjectId"; Expression={$_.ObjectGUID}}, `
                                @{Name="SourceUserPrincipalName (Optional)"; Expression={$_.UserPrincipalName}}, `
                                @{Name="SourceSamAccountName (Optional)"; Expression={$_.SamAccountName}}, `
                                @{Name="TargetObjectId"; Expression={""}}, `
                                @{Name="TargetUserPrincipalName (Optional)"; Expression={""}}, `
                                @{Name="TargetSamAccountName (Optional)"; Expression={""}}, `
                                @{Name="Comments (Optional)"; Expression={""}} |
                                    Export-Csv -Path $outputPath -Delimiter "," -NoTypeInformation @saveOperationType
                    }
                }
                else 
                {
                    $inputList | 
                        Select-Object -Property @{Name="ObjectId"; Expression={$_.ObjectGUID}}, `
                            @{Name="UserPrincipalName"; Expression={$_.UserPrincipalName}}, `
                            @{Name="SamAccountName"; Expression={$_.SamAccountName}} | 
                                Export-Csv -Path $outputPath -Delimiter "," -NoTypeInformation @saveOperationType
                }
            }
 
            "Microsoft.ActiveDirectory.Management.ADGroup" 
            {
                if ($Source)
                {
                    if ($EntraId)
                    {
                        $inputList | 
                            Select-Object -Property @{Name="SourceObjectId"; Expression={$_.ObjectGUID}}, `
                                @{Name="SourceSamAccountName"; Expression={$_.SamAccountName}}, `
                                @{Name="SourceNetBIOSName"; Expression={$_.NetBIOSName}}, `
                                @{Name="SourceDomainName"; Expression={$_.DomainName}}, `
                                @{Name="SourceObjectSID"; Expression={$_.SID}}, `
                                @{Name="TargetObjectId"; Expression={""}}, `
                                @{Name="TargetSamAccountName"; Expression={""}}, `
                                @{Name="Comments (Optional)"; Expression={""}} |
                                    Export-Csv -Path $outputPath -Delimiter "," -NoTypeInformation @saveOperationType
                    }
                    else
                    {
                        $inputList | 
                            Select-Object -Property @{Name="SourceObjectId"; Expression={$_.ObjectGUID}}, `
                                @{Name="SourceSamAccountName (Optional)"; Expression={$_.SamAccountName}}, `
                                @{Name="TargetObjectId"; Expression={""}}, `
                                @{Name="TargetSamAccountName (Optional)"; Expression={""}}, `
                                @{Name="Comments (Optional)"; Expression={""}} |
                                    Export-Csv -Path $outputPath -Delimiter "," -NoTypeInformation @saveOperationType
                    }
                }
                else 
                {
                    $inputList | 
                        Select-Object -Property @{Name="ObjectId"; Expression={$_.ObjectGUID}}, `
                            @{Name="SamAccountName"; Expression={$_.SamAccountName}} | 
                                Export-Csv -Path $outputPath -Delimiter "," -NoTypeInformation @saveOperationType
                }
            }
            "Microsoft.ActiveDirectory.Management.ADComputer" {
                if ($Source)
                {
                    if ($EntraId)
                    {
                        $inputList | 
                            Select-Object -Property @{Name="SourceObjectId"; Expression={$_.ObjectGUID}}, `
                                @{Name="SourceSamAccountName"; Expression={$_.SamAccountName}}, `
                                @{Name="SourceDomainName"; Expression={$_.DomainName}}, `
                                @{Name="Comments (Optional)"; Expression={""}} | 
                                    Export-Csv -Path $outputPath -Delimiter "," -NoTypeInformation @saveOperationType
                    }
                    else
                    {
                        $inputList | 
                            Select-Object -Property @{Name="SourceObjectId"; Expression={$_.ObjectGUID}}, `
                                @{Name="SourceSamAccountName (Optional)"; Expression={$_.SamAccountName}}, `
                                @{Name="Comments (Optional)"; Expression={""}} | 
                                    Export-Csv -Path $outputPath -Delimiter "," -NoTypeInformation @saveOperationType
                    }
                }
                else 
                {
                    $inputList | 
                        Select-Object -Property @{Name="ObjectId"; Expression={$_.ObjectGUID}}, `
                            @{Name="SamAccountName"; Expression={$_.SamAccountName}} | 
                                Export-Csv -Path $outputPath -Delimiter "," -NoTypeInformation @saveOperationType
                }
            }
            "Microsoft.Graph.PowerShell.Models.MicrosoftGraphUser"{
                if ($Source)
                {
                    $inputList | 
                        Select-Object -Property @{Name="SourceObjectId"; Expression={$_.Id}}, `
                            @{Name="SourceUserPrincipalName (Optional)"; Expression={$_.UserPrincipalName}}, `
                            @{Name="SourceSamAccountName (Optional)"; Expression={$_.OnPremisesSamAccountName}}, `
                            @{Name="TargetObjectId"; Expression={""}}, `
                            @{Name="TargetUserPrincipalName (Optional)"; Expression={""}}, `
                            @{Name="TargetSamAccountName (Optional)"; Expression={""}}, `
                            @{Name="Comments (Optional)"; Expression={""}} |
                                Export-Csv -Path $outputPath -Delimiter "," -NoTypeInformation @saveOperationType
                }
                else 
                {
                    $inputList | 
                        Select-Object -Property @{Name="ObjectId"; Expression={$_.Id}}, `
                            @{Name="UserPrincipalName"; Expression={$_.UserPrincipalName}}, `
                            @{Name="SamAccountName"; Expression={$_.OnPremisesSamAccountName}} | 
                                Export-Csv -Path $outputPath -Delimiter "," -NoTypeInformation @saveOperationType
                }
            }
            "Microsoft.Graph.PowerShell.Models.MicrosoftGraphGroup"{
                if ($Source)
                {
                    $inputList | 
                        Select-Object -Property @{Name="SourceObjectId"; Expression={$_.Id}}, `
                            @{Name="SourceSamAccountName (Optional)"; Expression={$_.OnPremisesSamAccountName}}, `
                            @{Name="TargetObjectId"; Expression={""}}, `
                            @{Name="TargetSamAccountName (Optional)"; Expression={""}}, `
                            @{Name="Comments (Optional)"; Expression={""}} |
                                Export-Csv -Path $outputPath -Delimiter "," -NoTypeInformation @saveOperationType
                }
                else 
                {
                    $inputList | 
                        Select-Object -Property @{Name="ObjectId"; Expression={$_.Id}}, `
                            @{Name="SamAccountName"; Expression={$_.OnPremisesSamAccountName}}, `
                            @{Name="DisplayName"; Expression={$_.DisplayName}}, `
                            @{Name="EmailAddress"; Expression={$_.Mail}} | 
                                Export-Csv -Path $outputPath -Delimiter "," -NoTypeInformation @saveOperationType
                }
            }
            "Microsoft.Graph.PowerShell.Models.MicrosoftGraphDevice"{
                if ($Source)
                {
                    $inputList | 
                        Select-Object -Property @{Name="SourceObjectId"; Expression={$_.Id}}, `
                            @{Name="SourceSamAccountName (Optional)"; Expression={$_.OnPremisesSamAccountName}}, `
                            @{Name="Comments (Optional)"; Expression={""}} | 
                                Export-Csv -Path $outputPath -Delimiter "," -NoTypeInformation @saveOperationType
                }
                else 
                {
                    $inputList | 
                        Select-Object -Property @{Name="ObjectId"; Expression={$_.Id}}, `
                            @{Name="SamAccountName"; Expression={$_.OnPremisesSamAccountName}}, `
                            @{Name="DisplayName"; Expression={$_.DisplayName}} | 
                                Export-Csv -Path $outputPath -Delimiter "," -NoTypeInformation @saveOperationType
                }
            }
            "Microsoft.Open.AzureAD.Model.User" {
                if ($Source)
                {
                    $inputList | 
                        Select-Object -Property @{Name="SourceObjectId"; Expression={$_.ObjectId}}, `
                            @{Name="SourceUserPrincipalName (Optional)"; Expression={$_.UserPrincipalName}}, `
                            @{Name="SourceSamAccountName (Optional)"; Expression={""}}, `
                            @{Name="TargetObjectId"; Expression={""}}, `
                            @{Name="TargetUserPrincipalName (Optional)"; Expression={""}}, `
                            @{Name="TargetSamAccountName (Optional)"; Expression={""}}, `
                            @{Name="Comments (Optional)"; Expression={""}} |
                                Export-Csv -Path $outputPath -Delimiter "," -NoTypeInformation @saveOperationType
                }
                else 
                {
                    $inputList | 
                        Select-Object -Property @{Name="ObjectId"; Expression={$_.ObjectId}}, `
                            @{Name="UserPrincipalName"; Expression={$_.UserPrincipalName}}, `
                            @{Name="SamAccountName"; Expression={""}} | 
                                Export-Csv -Path $outputPath -Delimiter "," -NoTypeInformation @saveOperationType
                }
            }
            "Microsoft.Open.AzureAD.Model.Group" {
                if ($Source)
                {
                    $inputList | 
                        Select-Object -Property @{Name="SourceObjectId"; Expression={$_.ObjectId}}, `
                            @{Name="SourceSamAccountName (Optional)"; Expression={""}}, `
                            @{Name="TargetObjectId"; Expression={""}}, `
                            @{Name="TargetSamAccountName (Optional)"; Expression={""}}, `
                            @{Name="Comments (Optional)"; Expression={""}} |
                                Export-Csv -Path $outputPath -Delimiter "," -NoTypeInformation @saveOperationType
                }
                else 
                {
                    $inputList | 
                        Select-Object -Property @{Name="ObjectId"; Expression={$_.ObjectId}}, `
                            @{Name="SamAccountName"; Expression={""}}, `
                            @{Name="DisplayName"; Expression={$_.DisplayName}}, `
                            @{Name="EmailAddress"; Expression={$_.Mail}} | 
                                Export-Csv -Path $outputPath -Delimiter "," -NoTypeInformation @saveOperationType
                }
            }
            "Microsoft.Open.AzureAD.Model.Device" {
                if ($Source)
                {
                    $inputList | 
                        Select-Object -Property @{Name="SourceObjectId"; Expression={$_.ObjectId}}, `
                            @{Name="SourceSamAccountName (Optional)"; Expression={""}}, `
                            @{Name="Comments (Optional)"; Expression={""}} | 
                                Export-Csv -Path $outputPath -Delimiter "," -NoTypeInformation @saveOperationType
                }
                else 
                {
                    $inputList | 
                        Select-Object -Property @{Name="ObjectId"; Expression={$_.ObjectId}}, `
                            @{Name="SamAccountName"; Expression={""}}, `
                            @{Name="DisplayName"; Expression={$_.DisplayName}} | 
                                Export-Csv -Path $outputPath -Delimiter "," -NoTypeInformation @saveOperationType
                }
            }
            default {
                Throw "[ERROR]: Type $inputType is not one of the accepted types."
            }
        }
        
        if ($Append)
        {
            Write-Host "[INFO]: File '$($outputPath)' appended"
        }
        else
        {
            Write-Host "[INFO]: File '$($outputPath)' created"
        }
    }
}
 
 
function ADMapLocalUsers($sourceUsersPath, $targetUsersPath) #Map two user files based on SamAccountName
{
    $sourceUsers = Import-Csv -Path $sourceUsersPath -Delimiter ","
    $targetUsers = Import-Csv -Path $targetUsersPath -Delimiter ","
    $mappedUsers = @()
    $nonMappedUsers = @()
 
    #for each source user, try to find target user via SamAccountName
    $sourceUsers | % {
        $sourceObject = $_
        $targetMatch = $null
        if ($sourceObject.SamAccountName -ne "")
        {
            $targetMatch = $targetUsers | Where-Object {$_.SamAccountName -eq $sourceObject.SamAccountName}
        }
        
        if ($targetMatch) #if found, create match record
        {
            if ($targetMatch.Count -gt 1)
            {
                throw "[ERROR]: Target User SamAccountName is not unique '$($sourceObject.SamAccountName)'"
            }
 
            $mappedUsers += [PSCustomObject]@{
                SourceObjectId = $sourceObject.ObjectId
                SourceUserPrincipalName = $sourceObject.UserPrincipalName
                SourceSamAccountName = $sourceObject.SamAccountName
                TargetObjectId = $targetMatch.ObjectId
                TargetUserPrincipalName = $targetMatch.UserPrincipalName
                TargetSamAccountName = $targetMatch.SamAccountName
                Comments = ""
            }
        }
        else #if havent found, create record without 
        {
            $nonMappedUsers += [PSCustomObject]@{
                SourceObjectId = $sourceObject.ObjectId
                SourceUserPrincipalName = $sourceObject.UserPrincipalName
                SourceSamAccountName = $sourceObject.SamAccountName
                TargetObjectId = ""
                TargetUserPrincipalName = ""
                TargetSamAccountName = ""
                Comments = ""
            }
        }
    }
 
    #save target users which dont have source user match
    $sourceUsersWithSam = $sourceUsers | Where-Object {$_.SamAccountName -ne ""} 
    $targetUsersWithoutSourceSam = $targetUsers | Where-Object { $_.SamAccountName -notin $sourceUsersWithSam.SamAccountName}
    $targetUsersWithoutSourceSam | % {
        $nonMappedUsers += [PSCustomObject]@{
            SourceObjectId = ""
            SourceUserPrincipalName = ""
            SourceSamAccountName = ""
            TargetObjectId = $_.ObjectId
            TargetUserPrincipalName = $_.UserPrincipalName
            TargetSamAccountName = $_.SamAccountName
            Comments = ""
        }
    }
 
    #save
    $mappedUsers += $nonMappedUsers
    $outputPath = "$PSScriptRoot\user_map_" + [DateTime]::UtcNow.ToString('yyyy_MM_dd_HH_mm_ss') + ".csv"
    $mappedUsers | Export-Csv -Path $outputPath -Delimiter "," -NoTypeInformation
    Write-Host "[INFO]: File '$($outputPath)' created"
}
function ADMapLocalGroups($sourceGroupsPath, $targetGroupsPath) #Map two group files based on SamAccountName
{
    $sourceGroups = Import-Csv -Path $sourceGroupsPath -Delimiter ","
    $targetGroups = Import-Csv -Path $targetGroupsPath -Delimiter ","
    $mappedGroups = @()
    $nonMappedGroups = @()
 
    #for each source group, try to find target group via SamAccountName
    $sourceGroups | % {
        $sourceObject = $_
        $targetMatch = $null
        if ($sourceObject.SamAccountName -ne "")
        {
            $targetMatch = $targetGroups | Where-Object {$_.SamAccountName -eq $sourceObject.SamAccountName}
        }
        
        if ($targetMatch) #if found, create match record
        {
            if ($targetMatch.Count -gt 1)
            {
                throw "Target Group SamAccountName is not unique '$($sourceObject.SamAccountName)'"
            }
 
            $mappedGroups += [PSCustomObject]@{
                SourceObjectId = $sourceObject.ObjectId
                SourceSamAccountName = $sourceObject.SamAccountName
                TargetObjectId = $targetMatch.ObjectId
                TargetSamAccountName = $targetMatch.SamAccountName
                Comments = ""
            }
        }
        else #if havent found, create record without 
        {
            $nonMappedGroups += [PSCustomObject]@{
                SourceObjectId = $sourceObject.ObjectId
                SourceSamAccountName = $sourceObject.SamAccountName
                TargetObjectId = ""
                TargetSamAccountName = ""
                Comments = ""
            }
        }
    }
 
    #save target groups which dont have source group match
    $sourceGroupsWithSam = $sourceGroups | Where-Object {$_.SamAccountName -ne ""} 
    $targetGroupsWithoutSourceSam = $targetGroups | Where-Object { $_.SamAccountName -notin $sourceGroupsWithSam.SamAccountName}
    $targetGroupsWithoutSourceSam | % {
        $nonMappedGroups += [PSCustomObject]@{
            SourceObjectId = ""
            SourceSamAccountName = ""
            TargetObjectId = $_.ObjectId
            TargetSamAccountName = $_.SamAccountName
            Comments = ""
        }
    }
 
    #save
    $mappedGroups += $nonMappedGroups
    $outputPath = "$PSScriptRoot\group_map_" + [DateTime]::UtcNow.ToString('yyyy_MM_dd_HH_mm_ss') + ".csv"
    $mappedGroups | Export-Csv -Path $outputPath -Delimiter "," -NoTypeInformation
    Write-Host "[INFO]: File '$($outputPath)' created"
}
Related Documents

The document was helpful.

Select Rating

I easily found the information I needed.

Select Rating