Migrating User profiles from Local accounts to Domain in Windows 10


  • Notification Spam Recipient

    So I'm working on getting my new workplace into sane practices, which includes making a Domain. We're now on a shiny new Windows 2016 Server domain, and now I get to put everyone in it!

    Naturally, everyone was using Local accounts, but at least it seems we have Windows Pro on all the computers, so that's a plus.

    Most of the instructions for moving accounts into the domain seem centered around Windows XP-era modifications, a few Regedits and File Permissions ACL adjustments, and Boom! Instant translation.

    Unfortunately, I haven't been able to actually get this to work. Following is a powershell script of the results of all my research:

    # Get the ID and security principal of the current user account
    $myWindowsID=[System.Security.Principal.WindowsIdentity]::GetCurrent()
    $myWindowsPrincipal=new-object System.Security.Principal.WindowsPrincipal($myWindowsID)
     
    # Get the security principal for the Administrator role
    $adminRole=[System.Security.Principal.WindowsBuiltInRole]::Administrator
     
    # Check to see if we are currently running "as Administrator"
    if ($myWindowsPrincipal.IsInRole($adminRole))
       {
       # We are running "as Administrator" - so change the title and background color to indicate this
       $Host.UI.RawUI.WindowTitle = $myInvocation.MyCommand.Definition + "(Elevated)"
       $Host.UI.RawUI.BackgroundColor = "DarkBlue"
       clear-host
       }
    else
       {
       # We are not running "as Administrator" - so relaunch as administrator
       
       # Create a new process object that starts PowerShell
       $newProcess = new-object System.Diagnostics.ProcessStartInfo "PowerShell";
       
       # Specify the current script path and name as a parameter
       $newProcess.Arguments = $myInvocation.MyCommand.Definition + " -IsAdmin";
       
       # Indicate that the process should be elevated
       $newProcess.Verb = "runas";
       
       #Check if we tried this already
       if ($myInvocation.MyCommand.Definition.Contains("-IsAdmin"))
       {
        Host-Write "Failed to elevate"
        sleep 15
        exit
       } else {
       # Start the new process
        [System.Diagnostics.Process]::Start($newProcess);
       
       # Exit from the current, unelevated, process
       exit
    
       }
       }
    
    
    
    
    
    
    
    
    
    # bring up an error prompt with OK button
    function dumbPrompt {
        param ($PromptText = $(throw “You must pass a text string.”))
        $a = new-object -comobject wscript.shell
        $b = $a.popup($PromptText,0,“Error”,0)
    }
    # authenticates PSCredentials to a domain.
    function auth-AdCreds {
        <#
        .SYNOPSIS
            Takes a PSCredential object and validates it against the domain (or local machine, or ADAM instance).
    
        .PARAMETER cred
            A PScredential object with the username/password you wish to test. Typically this is generated using the Get-Credential cmdlet. Accepts pipeline input.
    
        .PARAMETER context
            An optional parameter specifying what type of credential this is. Possible values are 'Domain','Machine',and 'ApplicationDirectory.' The default is 'Domain.'
    
        .OUTPUTS
            A boolean, indicating whether the credentials were successfully validated.
    
        #>
        param(
            [parameter(Mandatory=$true,ValueFromPipeline=$true)]
            [System.Management.Automation.PSCredential]$credential,
            [parameter()][validateset('Domain','Machine','ApplicationDirectory')]
            [string]$context = 'Domain'
        )
        begin {
            Add-Type -assemblyname system.DirectoryServices.accountmanagement
            $DS = New-Object System.DirectoryServices.AccountManagement.PrincipalContext([System.DirectoryServices.AccountManagement.ContextType]::$context, "office.local") 
        }
        process {
            $DS.ValidateCredentials($credential.UserName, $credential.GetNetworkCredential().password)
        }
    }    
    
    Write-Host "Migrating local account to the Domain."
    Write-Host "First, we need to know who you are in the new Domain"
    
    ## Get credentials and validate them ##
    # $count used to count the number of failed authentication attempts (3 max)
    $count = 0
    do {
        # $clear used to validate success or failure
        $clear = $true
        # prompt for the password of the current user
        $creds = get-credential  -EA SilentlyContinue
        # bypasses the checks if cancel/escape is pressed
        if ($creds) {
            write-host -f Green “Validating credentials…”
            # [optional] some programs authenticate without domain suffix/prefix. You cannot modify the credential username so you can prompt and resubmit if they are provided.
            # Another other option would be to ignore this, copy the username to a string var, then modify the string if you don’t have to pass a PSCredential.
            if ($creds.username.toUpper().startswith(‘OFFICE\‘) -or $creds.username.toLower().endswith(‘@office.local‘)) {
                $clear = $false
                dumbPrompt ‘You cannot use “OFFICE\” or “@office.local” in the username. Please use your account with no domain specified.‘
                Remove-Variable creds
            }
            # perform the actual authentication check if $clear is true
            if ($clear) {
                $clear = auth-AdCreds $creds
                # retry is authentication fails
                if (!$clear) {
                    dumbPrompt ‘Failed to authenticate the credentials to the office.local domain. Please try again.‘
                    Remove-Variable creds
                    $count++
                }
            }
        }
    } until ($clear -or $count -ge 3)
    # exit if user selected cancel/escape
    if (!$creds) {
        dumbPrompt ‘Valid credentials must be supplied to continue. Exiting the program.‘
        sleep 5
        exit
    }
    # exit if the three try limit was met
    if ($count -ge 3) {
        dumbPrompt ‘You have reached the three failure limit. Please make sure you are entering the correct password and that your account is not locked.’
        sleep 5
        exit
    }
    
    
    
    $localSID =  (Get-WmiObject win32_useraccount -Filter ("Status='OK' and name='" + $env:username + "' and domain!='office'")).SID
    $remoteSID = (New-Object System.Security.Principal.NTAccount("office.local", $creds.UserName)).Translate([System.Security.Principal.SecurityIdentifier]).Value
    
    Write-Host "Ok good. Now adjusting Registry..."
    
    $regCUacl = Get-Acl HKCU:
    $regCUacl.SetAccessRule((New-Object System.Security.AccessControl.RegistryAccessRule (("OFFICE\" + $creds.UserName),"FullControl","ContainerInherit","None","Allow")))
    $regCUacl | Set-Acl -Path HKCU:
    
    #Do the same with Classes
    $regCUacl = Get-Acl HKCU:\SOFTWARE\Classes
    $regCUacl.SetAccessRule((New-Object System.Security.AccessControl.RegistryAccessRule (("OFFICE\" + $creds.UserName),"FullControl","ContainerInherit","None","Allow")))
    $regCUacl | Set-Acl -Path HKCU:\SOFTWARE\Classes
    
    
    Write-Host "Now adjusting User Profile Permissions..."
    
    $profCUacl = Get-Acl $env:USERPROFILE
    $profCUacl.SetAccessRule((New-Object System.Security.AccessControl.FileSystemAccessRule (("OFFICE\" + $creds.UserName),"FullControl","ObjectInherit,ContainerInherit","None","Allow")))
    $profCUacl | Set-Acl -Path $env:USERPROFILE
    
    
    Write-Host "Renaming ProfileList entry..."
    
    #578
    Set-ItemProperty -Path ("HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList\" + $localSID) -Name "State" -Value 582
    Rename-Item -Path ("HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList\" + $localSID) -NewName $remoteSID
    Write-Host "Adjusting Logon settings..."
    
    
    Set-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon' -Name "AutoLogonSID" -Value $remoteSID 
    Set-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon' -Name "DefaultUserName" -Value ("office\"+$creds.UserName )
    Set-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon' -Name "LastUsedUsername" -Value ("office\"+$creds.UserName )
    
    
    Write-Host "Migration should be completed!"
    Write-Host "Please Reboot now to apply changes"
    

    Result: Windows is unable to load the profile properly, the desktop is completely broken, Explorer (as a shell) rapidly crashes and tries to relaunch repeatedly, and I'm completely unable to actually launch any programs:

    0_1481694494791_upload-760ab5d8-49e8-46de-a6d2-4b4bb4ec6d5e (mind not the activation notice, of course I'm testing on a VM)

    What do? Am I missing something?

    According to inspection, the registry edits and file permissions are correctly applied according to the script, I'm not sure what else should be done (well, other than just telling everyone "Hey guys, we're making new accounts for you, have fun setting everything back up again!").


  • sekret PM club

    Based on what I'm seeing, it would probably be MUCH easier to just create new domain accounts for them, and migrate their data over. USMT (Microsoft's User State Migration Tool) might help in retaining settings and stuff, or so this claims: http://superuser.com/questions/1011254/how-to-convert-regular-windows-10-account-to-an-active-directory-account)



  • @Tsaukpaetra
    Yeah, MS hasn't really supported migrating entire profiles since Windows XP. Largely because the side effect in that era was "target profile must remain a Local Administrator on the box for the duration of time", and that side effect was never really mitigated, so since the UAC era is trying to discourage Admin All The Accounts!, I think they just silently dropped support for profile migration.

    For W7+ computers, I usually settle for migrating the desktop shortcuts, Internet bookmarks (don't forget to look for Firefox and/or Chrome which use separate profile folders!), and documents libraries. The music libraries always seem to get mysteriously corrupted during the migration project ;) That solution removes the need for registry hacks or admin permissions, but does result in the desktop background, Outlook profiles, and saved passwords/form autofill not migrating. The Outlook issue is a nothingburger if you're a (properly configured) Exchange environment, and most of the time my users can deal with the loss of the rest when given advance warning.


  • Discourse touched me in a no-no place

    @izzion Yeah, this. Migrate the files etc but give them a fresh profile. It'll be much easier to live with.



  • @loopback0 said in Migrating User profiles from Local accounts to Domain in Windows 10:

    @izzion Yeah, this. Migrate the files etc but give them a fresh profile. It'll be much easier to live with.

    +1


  • FoxDev

    @No_1 said in Migrating User profiles from Local accounts to Domain in Windows 10:

    @loopback0 said in Migrating User profiles from Local accounts to Domain in Windows 10:

    @izzion Yeah, this. Migrate the files etc but give them a fresh profile. It'll be much easier to live with.

    +1

    +5


  • Notification Spam Recipient

    @loopback0 said in Migrating User profiles from Local accounts to Domain in Windows 10:

    @izzion Yeah, this. Migrate the files etc but give them a fresh profile. It'll be much easier to live with.

    I was trying to do USMT but bad things happened (well, not so bad as the Blinking Desktop issue).

    I'm now to the point where everything moves over pretty well, except Windows Apps is broken beyond repair, which somehow affects the Start Menu from opening at all (Described Here).

    I'm just worried about things like moving the licenses for Visual Studio over to the new profile and whatnot.



  • @Tsaukpaetra
    Is your VS license a MAK or an MSDN subscription or other?

    If it's an MAK, that's going to be checked at the machine level, and shouldn't matter how many user profiles are active / created / deleted on the machine.

    If it's an MSDN subscription, a user would likely be prompted to log in again, but it shouldn't consume an extra installation count since it's the same machine (and if you're really worried about that, just deactivate the license, convert to the new profile, and then reactivate?)


  • Grade A Premium Asshole

    @izzion said in Migrating User profiles from Local accounts to Domain in Windows 10:

    @Tsaukpaetra
    Yeah, MS hasn't really supported migrating entire profiles since Windows XP. Largely because the side effect in that era was "target profile must remain a Local Administrator on the box for the duration of time", and that side effect was never really mitigated, so since the UAC era is trying to discourage Admin All The Accounts!, I think they just silently dropped support for profile migration.

    For W7+ computers, I usually settle for migrating the desktop shortcuts, Internet bookmarks (don't forget to look for Firefox and/or Chrome which use separate profile folders!), and documents libraries. The music libraries always seem to get mysteriously corrupted during the migration project ;) That solution removes the need for registry hacks or admin permissions, but does result in the desktop background, Outlook profiles, and saved passwords/form autofill not migrating. The Outlook issue is a nothingburger if you're a (properly configured) Exchange environment, and most of the time my users can deal with the loss of the rest when given advance warning.

    ^ This.

    Don't fret about the rest of it. Move over what you can do so easily, let the users deal with the rest. They will grumble, but they will get over it quickly.


  • Impossible Mission - B


  • Notification Spam Recipient

    @masonwheeler said in Migrating User profiles from Local accounts to Domain in Windows 10:

    @Tsaukpaetra said in Migrating User profiles from Local accounts to Domain in Windows 10:

    Windows 10

    Yeah. I have a feeling the script would work just fine in Windows 7 environments...


Log in to reply