Autologon and Domain Join Issue with Sysprep Image

PauloHDallaCosta-3656 0 Reputation points
2024-12-02T15:07:25.58+00:00

During the preparation of an image using sysprep for deployment, an unattend answer file is utilized that includes the following steps:

  1. Rename the machine and restart. (Efforts to rename and join the domain in a single step have not been successful.)
  2. Join the domain and remove the local user.

The issue arises when the system restarts to complete the operation; Windows sometimes logs in automatically as the local user or remains on a login screen for a user that has been removed. Various entries in the Windows registry related to the local user have been deleted in attempts to resolve this.

However, if the domain is joined manually without the commands in the unattend file, the undesired behavior does not occur.

What might be missing in this process?

Unattend.xml

<?xml version="1.0" encoding="utf-8"?>
<unattend xmlns="urn:schemas-microsoft-com:unattend">
    <settings pass="oobeSystem">
        <component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
            <AutoLogon>
                <Enabled>true</Enabled>
                <LogonCount>2</LogonCount>
                <Username>TI</Username>
                <Password>
                    <PlainText>true</PlainText>
                    <Value></Value>
                </Password>
            </AutoLogon>
            <FirstLogonCommands>
                <SynchronousCommand wcm:action="add">
                    <CommandLine>powershell.exe Set-ExecutionPolicy Bypass -Scope Process -Force</CommandLine>
                    <Order>1</Order>
                    <RequiresUserInput>false</RequiresUserInput>
                    <Description>ativa scripts</Description>
                </SynchronousCommand>
                <SynchronousCommand wcm:action="add">
                    <CommandLine>powershell.exe -ExecutionPolicy Bypass -File C:\Windows\System32\SetComputerName.ps1</CommandLine>
                    <Order>2</Order>
                    <Description>Set Computer Name based on MAC Address</Description>
                    <RequiresUserInput>false</RequiresUserInput>
                </SynchronousCommand>
                <!-- Comando para excluir o script após a execução -->
                <SynchronousCommand wcm:action="add">
                    <CommandLine>cmd.exe /c del C:\Windows\System32\SetComputerName.ps1</CommandLine>
                    <Order>3</Order>
                    <Description>Excluir o script após execução</Description>
                    <RequiresUserInput>false</RequiresUserInput>
                </SynchronousCommand>
				<SynchronousCommand wcm:action="add">
                    <CommandLine>cmd.exe /c "rmdir C:\Windows.old</CommandLine>
                    <Order>4</Order>
                    <Description>Excluir o script após execução</Description>
                    <RequiresUserInput>false</RequiresUserInput>
                </SynchronousCommand>				
				<SynchronousCommand wcm:action="add">
					<CommandLine>shutdown /r /t 0</CommandLine>
					<Order>5</Order>
					<Description>Reiniciar o computador</Description>
					<RequiresUserInput>false</RequiresUserInput>
				</SynchronousCommand>
				<SynchronousCommand wcm:action="add">
                    <CommandLine>powershell.exe Set-ExecutionPolicy Bypass -Scope Process -Force</CommandLine>
                    <Order>6</Order>
                    <RequiresUserInput>false</RequiresUserInput>
                    <Description>ativa scripts</Description>
                </SynchronousCommand>
				<SynchronousCommand wcm:action="add">
                    <CommandLine>powershell.exe -ExecutionPolicy Bypass -File C:\Windows\System32\JoinDomainRemoTI.ps1</CommandLine>
                    <Order>7</Order>
                    <Description>Executa o script após execução</Description>
                    <RequiresUserInput>false</RequiresUserInput>
                </SynchronousCommand>
				<SynchronousCommand wcm:action="add">
                    <CommandLine>cmd.exe /c del C:\Windows\System32\JoinDomainRemoTI.ps1</CommandLine>
                    <Order>8</Order>
                    <Description>Excluir o script após execução</Description>
                    <RequiresUserInput>false</RequiresUserInput>
                </SynchronousCommand>
				<SynchronousCommand wcm:action="add">
					<CommandLine>shutdown /r /t 0</CommandLine>
					<Order>9</Order>
					<Description>Reiniciar o computador</Description>
					<RequiresUserInput>false</RequiresUserInput>
                <!-- Reiniciar o computador após renomear e excluir o script -->
            </FirstLogonCommands>
            <OOBE>
                <HideEULAPage>true</HideEULAPage>
                <HideOEMRegistrationScreen>true</HideOEMRegistrationScreen>
                <HideOnlineAccountScreens>true</HideOnlineAccountScreens>
                <HideWirelessSetupInOOBE>true</HideWirelessSetupInOOBE>
                <NetworkLocation>Work</NetworkLocation>
                <ProtectYourPC>3</ProtectYourPC>
                <SkipMachineOOBE>true</SkipMachineOOBE>
                <SkipUserOOBE>true</SkipUserOOBE>
                <UnattendEnableRetailDemo>false</UnattendEnableRetailDemo>
                <HideLocalAccountScreen>true</HideLocalAccountScreen>
            </OOBE>
            <UserAccounts>
                <LocalAccounts>
                    <LocalAccount>
                        <DisplayName>TI</DisplayName>
                        <Group>Administrators</Group>
                        <Name>TI</Name>
                        <Password>
                            <PlainText>true</PlainText>
                            <Value></Value>
                        </Password>
                    </LocalAccount>
                </LocalAccounts>
            </UserAccounts>
        </component>
        <component name="Microsoft-Windows-International-Core" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
            <InputLocale>0416:00010416</InputLocale>
            <UILanguage>pt-BR</UILanguage>
            <UILanguageFallback>pt-BR</UILanguageFallback>
            <UserLocale>pt-BR</UserLocale>
            <SystemLocale>pt-BR</SystemLocale>
        </component>
    </settings>
    <cpi:offlineImage cpi:source="wim:c:/users/ti/desktop/nova%20pasta/sources/install.wim#Windows 11 Enterprise" xmlns:cpi="urn:schemas-microsoft-com:cpi" />
</unattend>

JoinDomainRemoTI.ps1

#Validação do canal seguro com o domínio
try {
    if (-not (Test-ComputerSecureChannel -Verbose)) {
        Write-Log "Conexão segura com o domínio falhou. Abortando script para evitar perda de acesso."
        exit
    } else {
        Write-Log "Conexão segura com o domínio validada."
    }
} catch {
    Write-Log "Erro ao validar o canal seguro com o domínio: $_"
}
$USERNAME = "TI"
# Remover o perfil do usuário do registro
try {
    Remove-Item -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList\$USERNAME" -Force -ErrorAction SilentlyContinue
    Write-Log "Perfil do usuário $USERNAME removido do registro."
} catch {
    Write-Log "Erro ao remover o perfil do usuário $USERNAME do registro: $_"
}
# Remover o usuário de todos os grupos
Get-LocalGroup | ForEach-Object {
    $groupName = $_.Name
    try {
        Remove-LocalGroupMember -Group $groupName -Member $USERNAME -ErrorAction SilentlyContinue
        Write-Log "Usuário $USERNAME removido do grupo $groupName."
    } catch {
        Write-Log "Erro ao remover $USERNAME do grupo $groupName: $_"
    }
}
# Passo 1: Configurar para não exibir o último nome de usuário
try {
    Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" -Name "DontDisplayLastUserName" -Value 1
    Write-Log "Configurado para não exibir o último nome de usuário."
} catch {
    Write-Log "Erro ao configurar DontDisplayLastUserName: $_"
}
# Passo 2: Desativar login automático após reinicialização
try {
    Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" -Name "DisableAutomaticRestartSignOn" -Value 1
    Write-Log "Configurado para desativar login automático após reinicialização."
} catch {
    Write-Log "Erro ao configurar DisableAutomaticRestartSignOn: $_"
}
# Passo 3: Retardar processamento de GPOs do domínio
try {
    Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\System" -Name "GroupPolicyRefreshTime" -Value 90
    Write-Log "Configuração ajustada para retardar o processamento de GPOs do domínio."
} catch {
    Write-Log "Erro ao configurar GroupPolicyRefreshTime: $_"
}
# Remover o usuário
try {
    Remove-LocalUser -Name $USERNAME
    Write-Log "Usuário $USERNAME removido com sucesso."
} catch {
    Write-Log "Erro ao remover o usuário $USERNAME: $_"
}
# Remove o usuário de todos os arquivos e diretórios
Get-ChildItem -Path "C:\" -Recurse -Force | ForEach-Object {
    if (Test-Path $_) {
        $acl = Get-Acl $_
        $acl.Access | Where-Object { $_.IdentityReference -eq "$env:COMPUTERNAME\$USERNAME" } | ForEach-Object {
            $acl.RemoveAccessRule($_)
        }
        Set-Acl -Path $_ -AclObject $acl
    }
}
function Remove-UserPolicyEntries {
    param([string]$BasePath)
    
    # Verifica se a chave existe
    if (Test-Path $BasePath) {
        try {
            Write-Log "Removendo a chave do registro: $BasePath"
            Remove-Item -Path $BasePath -Recurse -Force -ErrorAction SilentlyContinue
            Write-Log "Chave $BasePath removida com sucesso."
        } catch {
            Write-Log "Erro ao remover a chave $BasePath: $_"
        }
    } else {
        Write-Log "A chave $BasePath não existe. Nenhuma ação necessária."
    }
    # Recriar a chave vazia
    try {
        Write-Log "Recriando a chave do registro: $BasePath"
        New-Item -Path $BasePath -Force | Out-Null
        Write-Log "Chave $BasePath recriada com sucesso."
    } catch {
        Write-Log "Erro ao recriar a chave $BasePath: $_"
    }
}
# Executa limpeza em caminhos padrão de políticas de grupo
Remove-UserPolicyEntries -BasePath "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Group Policy\DataStore" 
Remove-UserPolicyEntries -BasePath "HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Group Policy\DataStore" 
$registryPaths = @(
    # Entradas de login e autenticação
    "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\LogonUI\UserTiles\$Username",
    "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\UserList\$Username",
    # Entradas de preferências de usuário
    "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\UserAssist\*\Count\$Username",
    # Entradas relacionadas a últimos usuários logados
    "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\LogonUI\SessionData\*",
    # Entradas de credenciais
    "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\Credential Roaming\*\$Username"
)
# Resetar valores diretamente na chave LogonUI
$logonUIKey = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\LogonUI"
if (Test-Path $logonUIKey) {
    try {
        $values = Get-ItemProperty -Path $logonUIKey
        foreach ($value in $values.PSObject.Properties.Name) {
            if ($value -ne "(default)") {
                Write-Log "Removendo valor: $value"
                Remove-ItemProperty -Path $logonUIKey -Name $value -ErrorAction Stop
            }
        }
        Write-Log "Valores resetados na chave $logonUIKey."
    } catch {
        Write-Log "Erro ao resetar valores da chave $logonUIKey: $_"
    }
} else {
    Write-Log "A chave $logonUIKey não existe. Nenhuma ação necessária."
}
# Remover entradas de caminhos específicos
foreach ($path in $registryPaths) {
    try {
        if (Test-Path $path) {
            Remove-Item -Path $path -Recurse -Force -ErrorAction SilentlyContinue
            Write-Log "Removida entrada do registro: $path"
        }
    } catch {
        Write-Log "Erro ao remover entrada do registro $path: $_"
    }
}
# Limpar entradas de autologon
try {
    $USERNAME = "TI"
    $winlogonKey = "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon"
    # Multiple user removal methods
    wmic useraccount where name='$USERNAME' delete
    net user $USERNAME /delete
    Remove-LocalUser -Name $USERNAME -ErrorAction SilentlyContinue
    
    # Remove entradas padrão já existentes
    Remove-ItemProperty -Path $winlogonKey -Name "DefaultUserName" -ErrorAction SilentlyContinue
    Remove-ItemProperty -Path $winlogonKey -Name "LastUsedUsername" -ErrorAction SilentlyContinue
    
    # Entradas adicionais de autologon
    $autologonEntries = @(
        "AutoAdminLogon",
        "DefaultPassword",
        "LastPassword",
        "AutoLogonCount",
        "LoginDomain",
        "UserName"
    )
    
    foreach ($entry in $autologonEntries) {
        try {
            Remove-ItemProperty -Path $winlogonKey -Name $entry -ErrorAction SilentlyContinue
            Write-Log "Removida entrada de autologon: $entry"
        } catch {
            Write-Log "Erro ao remover entrada de autologon $entry: $_"
        }
    }
    
    Write-Log "Limpeza de entradas de autologon concluída."
} catch {
    Write-Log "Erro ao limpar entradas de Winlogon: $_"
}
try {
    $unattendPaths = @(
        "C:\Windows\Panther\Unattend.xml",
        "C:\Windows\System32\Sysprep\Unattend.xml"
		"C:\Windows\System32\JoinDomainRemoTI.ps1"
    )
    foreach ($path in $unattendPaths) {
        if (Test-Path $path) {
            Remove-Item $path -Force -ErrorAction SilentlyContinue
        }
    }
    Write-Log "Usuário $USERNAME foi completamente removido e suas configurações foram limpas."
} catch {
    Write-Log "Erro ao remover arquivos Unattend.xml"
}
Windows 11
Windows 11
A Microsoft operating system designed for productivity, creativity, and ease of use.
11,094 questions
PowerShell
PowerShell
A family of Microsoft task automation and configuration management frameworks consisting of a command-line shell and associated scripting language.
2,861 questions
0 comments No comments
{count} votes

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.