Skip to content

Instantly share code, notes, and snippets.

@danjpadgett
Last active January 13, 2017 18:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save danjpadgett/3a584969b067ff29080bf58a0d02827e to your computer and use it in GitHub Desktop.
Save danjpadgett/3a584969b067ff29080bf58a0d02827e to your computer and use it in GitHub Desktop.
Copies userdata between two file servers, resets ACL and Owner to user account.
<#
.NOTES
===========================================================================
Created on: 11/01/2017 11:59
Created by: Dan Padgett (C)
Filename: UserMigration.ps1
Version: 1.0
Web: www.execmgr.net
===========================================================================
.SYNOPSIS
Copies userdata between two file servers, resets ACL and Owner to user account.
.NOTES
This script was built for the purpose of copying data from previously redirected user profiles (that were used for folder redirection),
these directories has broken ACL's and admins could not read special folders. Users migrated would be using WorkFolders.
Previously edirected folders like Desktop, Documents and Favorites. This script was initially built using robocopy, however without even READ access to the directories
i had to switch to Dell Secure Copy (much faster than robocopy), which enables folder copies even without read access. Once the files are copied it will be repermissioned
to give the AD user specified Modify access, then that user will be set as the Owner for all files and folders.
Modify the following variables.
$workfolder = "\\serverdestination\users"
If you run this script on a server with Dell Secure Copy, you can utilise that instead of robocopy.
This setting is controlled by:
$useRobocopy = $false
If you plan on renaming files or folders after copy use this switch and add files/folders to the rename region.
$renamefolders = $true
REQUIREMENTS:
PSCX Module - http://pscx.codeplex.com/
Dell Secure Copy (if used) - https://www.quest.com/products/secure-copy/
.DISCLAIMER
All scripts are provided AS IS without warranty of any kind. The author further disclaims all implied warranties including, without limitation,
any implied warranties of merchantability or of fitness for a particular purpose.
The entire risk arising out of the use or performance of the sample scripts and documentation remains with you.
In no event shall the author,or anyone else involved in the creation, production, or delivery of the scripts be liable for any damages whatsoever
including, without limitation, damages for loss of business profits, business interruption, loss of business information, or other pecuniary loss
arising out of the use of or inability to use the sample scripts or documentation, even if the author has been advised of the possibility of such damages.
#>
#region InstallModule
#// Begin script by importing PSCX Module, required for setting ownership
#// Script will exit if module is not found
if ((Get-Module).name -Match "PSCX")
{} #Null
else
{
try {
Write-Host "Importing PSCX Module..please wait" -ForegroundColor Green
Import-Module "PSCX"
}
catch
{
Write-Host "Module PSCX not found, Module is required from http://pscx.codeplex.com/ , script aborting" -ForegroundColor Red
}
} # Module is required from http://pscx.codeplex.com/
#endregion
#SetScriptValues
$useRobocopy = $false
#//Set value to use robocopy
$renamefolders = $true
#//Set value to rename folders within #region FileNames
$rootpath = (Read-Host "Enter rootpath to source")
#//Prompts user to enter rootpath, script checks this path after appending SamAccountName
$username = (Read-Host "Enter Username")
#//Prompts user to username, checks against AD
try {
(Get-ADUser $username | select-object -expandproperty samAccountName)
}
catch
{
throw "(The User has not been found in AD...exiting)"
}
$destination = "\\serverdestination\users"
#// Uncomment below block to prompt user for destination path
<#$destination = (Read-Host "Enter Destination root path")
if (!(test-path $destination))
{
Write-Host "Destination is not valid, you entered '$destination' - script will exit, try again"
pause
exit
}
else {
#continue
}
#>
$path = $rootpath+$username
#// Appends username to root path
$destination = "$destination\$username"
#// Appends username to destination path
$source = $path
#// Assigns $path to $source for readability later
if (!(test-path $source))
#//checks if $source is valid, otherwise exits
{
Write-Host "Source is not valid, you entered '$source' - script will exit, try again"
pause
exit
}
else {
#continue
}
$choice = ""
#resets choice
while ($choice -notmatch "[y|n]"){
$choice = read-host "Do you want to continue migrating data from $source to $destination (Y/N)"
}
#// Sanity check to ensure $source and $destination are as intended
if ($choice -eq "y")
{
#region SetACLVars
Set-Privilege (new-object Pscx.Interop.TokenPrivilege "SeRestorePrivilege", $true) #Necessary to set Owner Permissions
Set-Privilege (new-object Pscx.Interop.TokenPrivilege "SeBackupPrivilege", $true) #Necessary to bypass Traverse Checking
Set-Privilege (new-object Pscx.Interop.TokenPrivilege "SeTakeOwnershipPrivilege", $true) #Necessary to override FilePermissions & take Ownership
$blankdirAcl = New-Object System.Security.AccessControl.DirectorySecurity
$blankdirAcl.SetOwner([System.Security.Principal.NTAccount]'BUILTIN\Administrators')
#//Created an ACL template of setting the built in admin account as owner.
#endregion
if ($useRobocopy -eq $true)
#//Will process if $robocopy was set to true at beginning.
{
#region RoboCopy
Write-Host "Starting file copy from '$source' to Destination" -ForegroundColor Yellow
$date = Get-Date -UFormat %d-%m-%y
$logfile = "$destination\Log\$date-$username.txt"
if (!(test-path $logfile)) { New-Item $logfile -ItemType file }
$RobocopyParams = @("/IS", "/MIR", "/r:1", "/w:1", "/COPY:DAT", "/NJS", "/E")
$XD = @("WINDOWS", "APPDATA", "SendTo", "Temp", "Temporary Internet Files", "`$RECYCLE.BIN")
$XF = @("*.pif", "*.EXE", "*.ini", "*.bat", "*.tmp", "thumbs.db")
& C:\cmtrace.exe $logfile
robocopy.exe $source $destination $RobocopyParams /XD @XD /XF @XF /log+:$logfile
Write-Host "Copy Complete to Destination, adjusting permissions" -ForegroundColor Yellow
#endregion
}
else
{
#region DellSecureCopy
#// Will process copy with Dell Secure Copy
if (Test-Path "C:\Program Files\Dell\Secure Copy 7")
{
Set-Location "C:\Program Files\Dell\Secure Copy 7"
# Switches /DB = Job Database, /Name = Job Name
# see http://documents.software.dell.com/secure-copy/7.0/user-guide/using-the-command-line/using-securecopycmd-exe
$argsu = "/DB=SecureCopy.ssd /Name=JOBNAME /Source=$source /Target=$destination /CopySubFolders=True"
Start-Process SecureCopyCmd.exe $argsu
Write-Host "Running batch job externally with Dell Secure Copy! `nCopying Data from $source to $destination! " -ForegroundColor Yellow
Write-Host "When Secure Copy shows complete, close Secure Copy window to continue..(waiting for process to close)... " -ForegroundColor Green
wait-process -Name SecureCopyCmd
#//Waits for user to close Security Copy window, window can be supressed with /quiet switch in $argsu
Write-Host "Batch job completed..moving to permissions" -ForegroundColor Green
Set-Location "C:\"
}
else
{
Write-Error "Dell Secure Copy Not found!"
}
#endregion
}
#region Set-Acl
$paths = (Get-Item -Path $destination )
#//Gathers top level folders of $destination
##Blank Out ACL Info On path and reset
(Get-Item $paths.FullName).SetAccessControl($blankdirAcl)
#Lookup Current Path and Extract username ($samccountname)
try {
$sAMAccountName = (Get-ADUser $username | select-object -expandproperty samAccountName)
write-host $_.Directory
} catch {
Write-Warning "($_. - The User has not been found in AD)"
return
}
$FileSystemAccessRights = [System.Security.AccessControl.FileSystemRights]"Modify"
$InheritanceFlags = [System.Security.AccessControl.InheritanceFlags]::"ContainerInherit", "ObjectInherit"
$PropagationFlags = [System.Security.AccessControl.PropagationFlags]::None
$AccessControl =[System.Security.AccessControl.AccessControlType]::Allow
$NewAccessrule = New-Object System.Security.AccessControl.FileSystemAccessRule ` ($sAMAccountName, $FileSystemAccessRights, $InheritanceFlags, $PropagationFlags, $AccessControl)
$currentACL = Get-Acl -path $paths
$currentACL.SetAccessRule($NewAccessrule)
#// Builds new ACL based off domain user
Write-Host "Managing Permissions for $sAMAccountName - in folder path '$paths'.....please wait.." -ForegroundColor Yellow
Set-Acl -path $paths -AclObject $currentACL
#Set Owner back to SamAccountUser
$RepairedACL = New-Object System.Security.AccessControl.DirectorySecurity
#set owner for folder root
$RepairedACL.SetOwner([System.Security.Principal.NTAccount]$sAMAccountName)
(Get-Item $paths.FullName).SetAccessControl($RepairedACL)
#endregion
#region FileNames
if ($renamefolders -eq $true)
#//Will rename and folders or files specified, follow below example
{
if (Test-Path $destination\Desktop)
{Rename-Item -path "$destination\Desktop" -newName ‘Archived Desktop’}
}
#endregion
#region Reset Owner
$SubDirectories = (Get-ChildItem $destination)
$ntAccount = New-Object System.Security.Principal.NTAccount("$sAMAccountName")
Foreach ($FolderName in $SubDirectories) {
#Set Parent Folder Ownership
Get-Item -LiteralPath "$destination\$FolderName" -ErrorAction SilentlyContinue | Get-Acl |
ForEach-Object {
$_.SetOwner($ntAccount)
Set-Acl -aclobject $_ -Path $_.PSPath
$Path = Split-Path $_.Path -NoQualifier
Write-Host $Path "Folder Owner Set -" $ntAccount
}
#Set Child Item Ownership
Get-ChildItem -LiteralPath "$destination\$FolderName" -Recurse –ErrorAction SilentlyContinue | Get-Acl |
ForEach-Object {
$_.SetOwner($ntAccount)
Set-Acl -aclobject $_ -Path $_.PSPath
$Path = Split-Path $_.Path -NoQualifier
Write-Host "File Owner Set to -" $ntAccount "in $Path"
}
}
#// Region above resets owner on all files to domain user specified at beginning of script
#endregion
Write-Host "Completed migration for '$sAMAccountName' - in folder path '$destination'" -ForegroundColor Yellow
}
else
{write-host "Script Exiting"}
#// Processed if user selects NO to proceeding with copy.
#End of script.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment