# Version date: 2026-07-28 10:47 (CEST) # Verify this is running with Administrator rights; stop with a clear # message if not. if (-not ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) { Write-Host "ERROR: Run this script as Administrator." ; exit } # -------------------------------------------------------------------------- # SETTINGS - the only things you should need to change to adapt this script # to a different machine or folder layout. # # By default, $CsvFolder is the same folder this script itself is saved in - # PowerShell's built-in $PSScriptRoot variable always points there # automatically, so nothing needs to be typed in manually. To use a # different, fixed folder instead (e.g. C:\Temp), replace that line below # with a fixed path, for example: # $CsvFolder = "C:\Temp" # -------------------------------------------------------------------------- $CsvFolder = $PSScriptRoot # The Leica settings backup lives in a subfolder right next to the scripts, # rather than on a separately-specified drive - this way, the scripts and # their data always travel together and no drive letter needs to be # configured, regardless of which drive letter this happens to be on. To # use a different, fixed folder instead, replace the line below with a # fixed path, for example: # $SourceRoot = "E:\OldUsers_$($env:COMPUTERNAME)" $SourceRoot = Join-Path $PSScriptRoot "OldUsers_$($env:COMPUTERNAME)" # ------------------------------------------------------------ # Undo everything done on the NEW computer by CreateLocalUsers.ps1 and # RestoreLeicaSettings.ps1, using the undo logs those two scripts wrote, # both now in the same folder as the scripts themselves: # - CreateUsers_Undo_.csv (in $CsvFolder above) # - RestoreLeicaSettings_Undo_.csv (in $CsvFolder above) # # WHAT THIS CAN AND CANNOT UNDO: # - Local accounts this run of CreateLocalUsers.ps1 actually created are # fully removed, INCLUDING their whole Windows profile (C:\Users\ # and its registry entry) - so any Leica settings restored into that # profile are removed as part of this, automatically. # - For a user who already had a local account BEFORE the migration (i.e. # NOT created by CreateLocalUsers.ps1) but who had Leica settings # restored into their existing profile, this script removes ONLY the # restored LAS X settings folder. The account and the rest of their # profile are left alone, since this script did not create them. # - IMPORTANT - CANNOT BE UNDONE: if RestoreLeicaSettings.ps1 was told to # delete a user's pre-existing Leica settings before restoring the # backup (logged there as Action = "DeletedExistingThenRestored"), those # original files are permanently gone. This script can only remove what # was restored - it cannot bring back what was deleted. This script # prints a clear NOTE for every user affected by this. # - This script does NOT touch: the CSV files in $CsvFolder, the log files # from any script, the undo log files themselves, or anything on the # OLD computer. Only account/profile state on THIS (new) computer. # ------------------------------------------------------------ $CreateUndoFile = Join-Path $CsvFolder "CreateUsers_Undo_$($env:COMPUTERNAME).csv" $RestoreUndoFile = Join-Path $CsvFolder "RestoreLeicaSettings_Undo_$($env:COMPUTERNAME).csv" $LogFile = Join-Path $CsvFolder "UndoNewComputerSetup.log" # Start-Transcript overwrites an existing file without warning by default, # so check first and ask before silently discarding a previous log. if (Test-Path $LogFile) { Write-Host "File $LogFile is already present." $LogResponse = Read-Host "Overwrite or abort script? (O = overwrite, A = abort)" if ($LogResponse -ine "O") { Write-Host "Aborted by user." exit } } # If a previous run of this or another script was interrupted before it # could call Stop-Transcript, PowerShell can still consider a transcript # "active" in this session, which would make the next line fail. Close any # such leftover transcript first; if none is active, this is silently # ignored. try { Stop-Transcript -ErrorAction Stop | Out-Null } catch { } # Start logging Start-Transcript -Path $LogFile # Load the account-creation undo log, if present. $CreateUndoEntries = @() if (Test-Path $CreateUndoFile) { $CreateUndoEntries = @(Import-Csv $CreateUndoFile) } else { Write-Host "File $CreateUndoFile not found, skipping." } # Load the settings-restore undo log, if present. $RestoreUndoEntries = @() if (Test-Path $RestoreUndoFile) { $RestoreUndoEntries = @(Import-Csv $RestoreUndoFile) } else { Write-Host "File $RestoreUndoFile not found, skipping." } if ($CreateUndoEntries.Count -eq 0 -and $RestoreUndoEntries.Count -eq 0) { Write-Host "Nothing to undo." Stop-Transcript exit } # Usernames created by CreateLocalUsers.ps1 - these get full account + # profile removal below. Anyone else in the restore-undo log only gets # their restored settings folder removed, since their account pre-dates # this migration and was not created by these scripts. $CreatedUserNames = $CreateUndoEntries | ForEach-Object { $_.Name } Write-Host "" Write-Host "========================================" Write-Host "This undo will:" Write-Host " - Remove $($CreateUndoEntries.Count) local account(s) AND their whole Windows profile:" $CreateUndoEntries | ForEach-Object { Write-Host " $($_.Name)" } $SettingsOnlyEntries = @($RestoreUndoEntries | Where-Object { $_.Name -notin $CreatedUserNames }) Write-Host " - Remove restored Leica settings only (account left untouched) for $($SettingsOnlyEntries.Count) user(s):" $SettingsOnlyEntries | ForEach-Object { Write-Host " $($_.Name)" } Write-Host "========================================" Write-Host "This cannot be undone. Type UNDO (all caps) to proceed." $Confirm = Read-Host "Confirm" if ($Confirm -cne "UNDO") { Write-Host "Aborted by user - nothing was changed." Stop-Transcript exit } $AccountsRemoved = 0 $SettingsRemoved = 0 $Errors = 0 # -------------------------------------------------------------------------- # Part 1: fully remove accounts (and their profiles) that were created by # CreateLocalUsers.ps1. Removing the profile also removes any restored # Leica settings inside it, so no separate step is needed for those users. # -------------------------------------------------------------------------- foreach ($Entry in $CreateUndoEntries) { $UserName = $Entry.Name Write-Host "" Write-Host "----------------------------------------" Write-Host "Removing account: $UserName" try { # Remove the Windows profile properly (folder + registry entry), # not just the folder, using the same mechanism Windows itself uses. # This also removes any Leica settings restored into it. $ProfileToRemove = Get-CimInstance Win32_UserProfile -Filter "LocalPath='C:\\Users\\$UserName'" -ErrorAction SilentlyContinue if ($ProfileToRemove) { Remove-CimInstance -InputObject $ProfileToRemove -ErrorAction Stop Write-Host "Profile for $UserName removed (including any restored Leica settings)." } else { Write-Host "No profile found for $UserName - nothing to remove there." } if (Get-LocalUser -Name $UserName -ErrorAction SilentlyContinue) { Remove-LocalUser -Name $UserName -ErrorAction Stop Write-Host "Local account $UserName removed." } else { Write-Host "Local account $UserName already does not exist - nothing to remove there." } $AccountsRemoved++ } catch { Write-Host "ERROR removing $UserName`: $($_.Exception.Message)" Write-Host "If this is a 'file in use' error: a profile that was recently used (e.g. an account just created and/or restored into) can stay locked until the computer is rebooted. Reboot this computer and run this script again." $Errors++ } } # -------------------------------------------------------------------------- # Part 2: for users whose account was NOT created by CreateLocalUsers.ps1 # (i.e. it already existed before this migration), remove only the # restored Leica settings folder, leaving the account and rest of their # profile untouched. # -------------------------------------------------------------------------- foreach ($Entry in $SettingsOnlyEntries) { $UserName = $Entry.Name $Destination = $Entry.Destination Write-Host "" Write-Host "----------------------------------------" Write-Host "Removing restored settings only for: $UserName" try { if (Test-Path $Destination) { Remove-Item -Path $Destination -Recurse -Force -ErrorAction Stop Write-Host "Restored Leica settings removed: $Destination" $SettingsRemoved++ } else { Write-Host "Nothing to remove - $Destination does not exist." } # If the original restore had deleted this user's pre-existing # settings before restoring the backup, those original files are # permanently gone - this undo can only remove what was restored, # not recover what was deleted at that time. if ($Entry.Action -ieq "DeletedExistingThenRestored") { Write-Host "NOTE: $UserName had pre-existing Leica settings that were permanently deleted" Write-Host "when RestoreLeicaSettings.ps1 ran. Those original files CANNOT be recovered by" Write-Host "this undo. $UserName now has no Leica settings at all, not their original ones." } } catch { Write-Host "ERROR removing settings for $UserName`: $($_.Exception.Message)" $Errors++ } } Write-Host "" Write-Host "========================================" Write-Host "Undo summary" Write-Host "========================================" Write-Host "Accounts + profiles removed : $AccountsRemoved" Write-Host "Settings-only removals : $SettingsRemoved" Write-Host "Errors : $Errors" Write-Host "========================================" Stop-Transcript