Executando verificação de segurança...
3

Mova Perfis de Usuário do Windows Entre Discos com PowerShell — Automatizado e Seguro

Se você já precisou mover perfis de usuário do Windows para outro disco (ex: de C:\Users para D:\Users), sabe que a tarefa pode ser complexa, especialmente mantendo todas as configurações intactas.

Pensando nisso, desenvolvi um script PowerShell que:

Lista todos os usuários locais e avisa se o perfil é Roaming (bloqueando a seleção desses).

Mostra os discos disponíveis no sistema para você escolher o destino.

Exibe um resumo antes de confirmar a ação.

Move o perfil com robocopy, exibindo uma barra de progresso.

Atualiza automaticamente o registro do Windows para o novo caminho do perfil.

Atualiza variáveis de ambiente do sistema e do usuário que apontem para o caminho antigo.

Permite mover vários perfis em sequência.

⚠️ Importante: execute como administrador e nunca mova o perfil do usuário logado no momento.

Se você administra estações Windows e precisa organizar perfis, este script vai acelerar e simplificar muito seu trabalho.

Quer o Script?

Tome aqui kkkk

move_user.ps1

    $caminhoUsuarios = "C:\Users"
    Get-ChildItem $caminhoUsuarios -Directory | ForEach-Object {
        $nome = $_.Name
        $perfil = (Get-WmiObject -Class Win32_UserProfile | Where-Object { $_.LocalPath -eq "$caminhoUsuarios\$nome" })
        if ($perfil) {
            [PSCustomObject]@{
                Nome    = $nome
                Caminho = $perfil.LocalPath
                SID     = $perfil.SID
                Tipo    = if ($perfil.RoamingConfigured) { "Roaming" } else { "Local" }
            }
        }
    }
}

function Obter-Discos {
    Get-PSDrive -PSProvider FileSystem | Where-Object { $_.Free -gt 0 } | ForEach-Object {
        [PSCustomObject]@{
            Nome   = $_.Name
            Caminho = "$($_.Root)"
        }
    }
}

function Mostrar-BarraProgresso($activity, $percentComplete) {
    Write-Progress -Activity $activity -PercentComplete $percentComplete
}

function Mover-PerfilUsuario($usuario, $destino) {
    $origem = $usuario.Caminho
    $destinoCompleto = Join-Path $destino "Users\$($usuario.Nome)"

    Write-Host "`n🚚 Movendo perfil de $($usuario.Nome) para $destinoCompleto..."
    robocopy $origem $destinoCompleto /MIR /COPYALL /XJ /R:0 /W:0 | Out-Null

    Mostrar-BarraProgresso "Copiando arquivos..." 70

    Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList\$($usuario.SID)" -Name "ProfileImagePath" -Value $destinoCompleto

    Mostrar-BarraProgresso "Atualizando registro..." 90

    Corrigir-VariaveisAmbiente $usuario $destinoCompleto

    Mostrar-BarraProgresso "Finalizando..." 100
    Start-Sleep 1
    Write-Progress -Activity "Concluído" -Completed
}

function Corrigir-VariaveisAmbiente($usuario, $novoCaminho) {
    $antigoCaminho = $usuario.Caminho
    Write-Host "`n🔍 Verificando variáveis de ambiente..."

    $userVars = [System.Environment]::GetEnvironmentVariables("User")
    $sysVars = [System.Environment]::GetEnvironmentVariables("Machine")

    foreach ($var in $userVars.Keys) {
        if ($userVars[$var] -like "$antigoCaminho*") {
            $novoValor = $userVars[$var] -replace [regex]::Escape($antigoCaminho), $novoCaminho
            [System.Environment]::SetEnvironmentVariable($var, $novoValor, "User")
            Write-Host "🔁 Variável de usuário '$var' atualizada."
        }
    }

    foreach ($var in $sysVars.Keys) {
        if ($sysVars[$var] -like "$antigoCaminho*") {
            $novoValor = $sysVars[$var] -replace [regex]::Escape($antigoCaminho), $novoCaminho
            [System.Environment]::SetEnvironmentVariable($var, $novoValor, "Machine")
            Write-Host "🔁 Variável de sistema '$var' atualizada."
        }
    }

    Write-Host "✅ Verificação de variáveis concluída."
}

# Loop principal
do {
    Clear-Host
    Write-Host "🧑‍💻 Seleção de Usuário"
    $usuarios = Obter-Usuarios
    for ($i = 0; $i -lt $usuarios.Count; $i++) {
        Write-Host "[$i] $($usuarios[$i].Nome) ($($usuarios[$i].Tipo))"
    }

    $idUsuario = Read-Host "`nDigite o número do usuário desejado"
    if ($usuarios[$idUsuario].Tipo -eq "Roaming") {
        Write-Host "`n❌ O usuário selecionado é do tipo Roaming e não pode ser movido automaticamente."
        Pause
        continue
    }

    $usuarioSelecionado = $usuarios[$idUsuario]

    Clear-Host
    Write-Host "💽 Seleção de Disco"
    $discos = Obter-Discos
    for ($j = 0; $j -lt $discos.Count; $j++) {
        Write-Host "[$j] $($discos[$j].Caminho)"
    }

    $idDisco = Read-Host "`nDigite o número do disco desejado"
    $discoSelecionado = $discos[$idDisco]

    Clear-Host
    Write-Host "⚙️ Resumo da Ação:"
    Write-Host "Usuário: $($usuarioSelecionado.Nome)"
    Write-Host "Tipo:    $($usuarioSelecionado.Tipo)"
    Write-Host "Origem:  $($usuarioSelecionado.Caminho)"
    Write-Host "Destino: $($discoSelecionado.Caminho)Users\$($usuarioSelecionado.Nome)"
    $confirmar = Read-Host "`nDeseja mover o usuário para o novo disco? (Y/N)"

    if ($confirmar -eq "Y") {
        Mover-PerfilUsuario $usuarioSelecionado $discoSelecionado.Caminho
        Write-Host "`n✅ Perfil movido com sucesso para $($discoSelecionado.Caminho)Users\$($usuarioSelecionado.Nome)"
    } else {
        Write-Host "❌ Ação cancelada pelo usuário."
    }

    $repetir = Read-Host "`nDeseja mover outro perfil? (Y/N)"
} while ($repetir -eq "Y")

Write-Host "`n🟢 Script finalizado."
Carregando publicação patrocinada...
-1

Compartilhe logo antes que as pessoas negativem a publicação por não ter uma informação realmente útil.

S2


Farei algo que muitos pedem para aprender a programar corretamente, gratuitamente (não vendo nada, é retribuição na minha aposentadoria) (links aqui no perfil também).