Go Premium for a chance to win a PS4. Enter to Win

x
?
Solved

powershell code needs amending

Posted on 2016-07-26
9
Medium Priority
?
94 Views
Last Modified: 2016-07-27
Dear Experts,

I have this excellent code written by one you experts and did the job for me. However, I need to change it get inputs from .csv file for user names ( firstname.surname) and move their home drives from old server (server1) to new server ( server2, retaining the permissions on the home folders and finally change their home drive path in AD ( from server1 to server2.

Could you help me on this please? thanks
$oldRootServerPath = "\\localhost\share\"
$newRootServerPath = "\\localhost\share2\"
$errorLog = "C:\Users\Administrator\Desktop\error.txt"
$copyLog = "C:\Users\Administrator\Desktop\copy.txt"
$sourceOU = "OU=TestCompany,OU=Clients,OU=zUsers,DC=myDC,DC=local"

function WriteError($message)
{
    $stamp = Get-Date
    $error = $stamp.ToString() + " -- " + $message
    Add-Content -Path $errorLog -Value $error
}

function WriteCopy($message)
{
    $stamp = Get-Date
    $msg = $stamp.ToString() + " -- " + $message
    Add-Content -Path $copyLog -Value $msg
}


function CopyHomeDirectory($source)
{
    $newRoot = $source -replace [regex]::Escape($oldRootServerPath),$newRootServerPath
    if (!(Test-Path $newRoot)) 
    {
        New-Item -ItemType Directory $newRoot
        $acl = Get-Acl $source
        Set-Acl -Path $newRoot -AclObject $acl
    }
    $folders = Get-ChildItem $source -Recurse | ?{$_.PSIsContainer}
    foreach ($folder in $folders)
    {
        try {
        $oldFolder = $folder.FullName
        $acl = Get-Acl $oldFolder
        $newFolder = $oldFolder -replace [regex]::Escape($oldRootServerPath),$newRootServerPath
        if (!(Test-Path $newFolder)) {
            New-Item -ItemType Directory $newFolder
            Set-Acl -Path $newFolder -AclObject $acl
            }
        }
        catch {
        $eMessage = "Could not copy folder " + $oldFolder
        WriteError($eMessage)
        $errors++
        }
    }

        $files = Get-ChildItem $source -Recurse | ?{!$_.PsIsContainer}
        foreach ($file in $files)
        {
            try {
            $oldFile = $file.FullName
            $acl = Get-Acl $oldFile
            $newFile = $oldFile -replace [regex]::Escape($oldRootServerPath),$newRootServerPath
            Copy-Item $oldFile -Destination $newFile
            Set-Acl -Path $newFile -AclObject $acl
            }
            catch {
            $eMessage = "Could not copy file " + $oldFile
            WriteError($eMessage)
            $errors++
            }
        }


}

$users = Get-ADUser -Filter * -SearchBase $sourceOU -Properties homeDirectory | ?{$_.homeDirectory} | select  sAMAccountName,homeDirectory

foreach ($user in $users)
{
    $errors = 0
    $path = $user.homeDirectory.ToString()
    CopyHomeDirectory($path)
    $copyMsg = "Copy completed for " + $path + " -- " + $errors + " errors occurred."
    WriteCopy($copyMsg)
    $newPath = $path -replace [regex]::Escape($oldRootServerPath),$newRootServerPath
    Set-AdUser -Identity $user.sAMAccountName -HomeDrive "H:" -HomeDirectory $newPath
}

Open in new window

0
Comment
Question by:kuzum
  • 4
  • 2
  • 2
8 Comments
 
LVL 71

Expert Comment

by:Qlemo
ID: 41729301
What's the exact structure of the CSV file? Can you show a short mock-up example?
Am I correct that you want to change the script from searching in a specific OU to using specific names coming from the CSV?
0
 
LVL 71

Expert Comment

by:Qlemo
ID: 41729317
Assuming you have a CSV file like
FirstName,SurName
Charles,Bronson
River,Phoenix

Open in new window

replace line 5 with the complete path to it:
$userfile = 'C:\Users\Administrator\Desktop\Users.CSV'

Open in new window

and line 70 with
$users = Import-CSV $userfile | % { Get-ADUser -Filter {GivenName -eq $_.FirstName -and SurName -eq $_.SurName} -Properties homeDirectory | ?{$_.homeDirectory} | select  sAMAccountName,homeDirectory

Open in new window

0
 

Author Comment

by:kuzum
ID: 41729373
Qlemo,

thanks for your response.  Yes, you are right. instead of searching for a OU, it should read through the csv file and copy the home folders to new server, Of course with permissions and change the home folder path in AD for those users. ,  ( I do not want home folders to be deleted in old location)

csv file sample is attached.
Doc3.docx
0
 The Evil-ution of Network Security Threats

What are the hacks that forever changed the security industry? To answer that question, we created an exciting new eBook that takes you on a trip through hacking history. It explores the top hacks from the 80s to 2010s, why they mattered, and how the security industry responded.

 

Author Comment

by:kuzum
ID: 41729374
basically, csv file will be Firstname.surname
0
 
LVL 14

Accepted Solution

by:
Dustin Saunders earned 2000 total points
ID: 41729465
These changes will perform the search:

@line5
$userfile = 'C:\Users\Administrator\Desktop\name.CSV'

Open in new window


@line70
$users = Import-CSV $userfile | % {Get-ADUser -Filter "sAMAccountName -eq '$($_.SamAccountName)'" -Properties homeDirectory | ?{$_.homeDirectory} | select  sAMAccountName,homeDirectory }

Open in new window


The whole thing:
$oldRootServerPath = "\\localhost\share\"
$newRootServerPath = "\\localhost\share2\"
$errorLog = "C:\Users\Administrator\Desktop\error.txt"
$copyLog = "C:\Users\Administrator\Desktop\copy.txt"
$userfile = 'C:\Users\Administrator\Desktop\name.CSV'

function WriteError($message)
{
    $stamp = Get-Date
    $error = $stamp.ToString() + " -- " + $message
    Add-Content -Path $errorLog -Value $error
}

function WriteCopy($message)
{
    $stamp = Get-Date
    $msg = $stamp.ToString() + " -- " + $message
    Add-Content -Path $copyLog -Value $msg
}


function CopyHomeDirectory($source)
{
    $newRoot = $source -replace [regex]::Escape($oldRootServerPath),$newRootServerPath
    if (!(Test-Path $newRoot)) 
    {
        New-Item -ItemType Directory $newRoot
        $acl = Get-Acl $source
        Set-Acl -Path $newRoot -AclObject $acl
    }
    $folders = Get-ChildItem $source -Recurse | ?{$_.PSIsContainer}
    foreach ($folder in $folders)
    {
        try {
        $oldFolder = $folder.FullName
        $acl = Get-Acl $oldFolder
        $newFolder = $oldFolder -replace [regex]::Escape($oldRootServerPath),$newRootServerPath
        if (!(Test-Path $newFolder)) {
            New-Item -ItemType Directory $newFolder
            Set-Acl -Path $newFolder -AclObject $acl
            }
        }
        catch {
        $eMessage = "Could not copy folder " + $oldFolder
        WriteError($eMessage)
        $errors++
        }
    }

        $files = Get-ChildItem $source -Recurse | ?{!$_.PsIsContainer}
        foreach ($file in $files)
        {
            try {
            $oldFile = $file.FullName
            $acl = Get-Acl $oldFile
            $newFile = $oldFile -replace [regex]::Escape($oldRootServerPath),$newRootServerPath
            Copy-Item $oldFile -Destination $newFile
            Set-Acl -Path $newFile -AclObject $acl
            }
            catch {
            $eMessage = "Could not copy file " + $oldFile
            WriteError($eMessage)
            $errors++
            }
        }


}

$users = Import-CSV $userfile | % {Get-ADUser -Filter "sAMAccountName -eq '$($_.SamAccountName)'" -Properties homeDirectory | ?{$_.homeDirectory} | select  sAMAccountName,homeDirectory }

foreach ($user in $users)
{
    $errors = 0
    $path = $user.homeDirectory.ToString()
    CopyHomeDirectory($path)
    $copyMsg = "Copy completed for " + $path + " -- " + $errors + " errors occurred."
    WriteCopy($copyMsg)
    $newPath = $path -replace [regex]::Escape($oldRootServerPath),$newRootServerPath
    Set-AdUser -Identity $user.sAMAccountName -HomeDrive "H:" -HomeDirectory $newPath
}

Open in new window


Be sure to take that top line out of your CSV (#TYPE Selected.Microsoft.ActiveDirectory.Management.ADUsers)
0
 

Author Comment

by:kuzum
ID: 41729525
Hi Dustin,

is it also possible to add what-if in the end and run it first please?
0
 
LVL 14

Expert Comment

by:Dustin Saunders
ID: 41729536
This should be in 'test mode'.  There are 3 whatif(s)
$oldRootServerPath = "\\localhost\share\"
$newRootServerPath = "\\localhost\share2\"
$errorLog = "C:\Users\Administrator\Desktop\error.txt"
$copyLog = "C:\Users\Administrator\Desktop\copy.txt"
$userfile = 'C:\Users\Administrator\Desktop\name.CSV'

function WriteError($message)
{
    $stamp = Get-Date
    $error = $stamp.ToString() + " -- " + $message
    Add-Content -Path $errorLog -Value $error
}

function WriteCopy($message)
{
    $stamp = Get-Date
    $msg = $stamp.ToString() + " -- " + $message
    Add-Content -Path $copyLog -Value $msg
}


function CopyHomeDirectory($source)
{
    $newRoot = $source -replace [regex]::Escape($oldRootServerPath),$newRootServerPath
    if (!(Test-Path $newRoot)) 
    {
        New-Item -ItemType Directory $newRoot
        $acl = Get-Acl $source
        Set-Acl -Path $newRoot -AclObject $acl
    }
    $folders = Get-ChildItem $source -Recurse | ?{$_.PSIsContainer}
    foreach ($folder in $folders)
    {
        try {
        $oldFolder = $folder.FullName
        $acl = Get-Acl $oldFolder
        $newFolder = $oldFolder -replace [regex]::Escape($oldRootServerPath),$newRootServerPath
        if (!(Test-Path $newFolder)) {
            New-Item -ItemType Directory $newFolder 
            Set-Acl -Path $newFolder -AclObject $acl
            }
        }
        catch {
        $eMessage = "Could not copy folder " + $oldFolder
        WriteError($eMessage)
        $errors++
        }
    }

        $files = Get-ChildItem $source -Recurse | ?{!$_.PsIsContainer}
        foreach ($file in $files)
        {
            try {
            $oldFile = $file.FullName
            $acl = Get-Acl $oldFile
            $newFile = $oldFile -replace [regex]::Escape($oldRootServerPath),$newRootServerPath
            Copy-Item $oldFile -Destination $newFile -whatif
            Set-Acl -Path $newFile -AclObject $acl -whatif
            }
            catch {
            $eMessage = "Could not copy file " + $oldFile
            WriteError($eMessage)
            $errors++
            }
        }


}

$users = Import-CSV $userfile | % {Get-ADUser -Filter "sAMAccountName -eq '$($_.SamAccountName)'" -Properties homeDirectory | ?{$_.homeDirectory} | select  sAMAccountName,homeDirectory }

foreach ($user in $users)
{
    $errors = 0
    $path = $user.homeDirectory.ToString()
    CopyHomeDirectory($path)
    $copyMsg = "Copy completed for " + $path + " -- " + $errors + " errors occurred."
    WriteCopy($copyMsg)
    $newPath = $path -replace [regex]::Escape($oldRootServerPath),$newRootServerPath
    Set-AdUser -Identity $user.sAMAccountName -HomeDrive "H:" -HomeDirectory $newPath -whatif
}

Open in new window


@line80
Set-AdUser -Identity $user.sAMAccountName -HomeDrive "H:" -HomeDirectory $newPath -whatif

Open in new window


@line57-58
Copy-Item $oldFile -Destination $newFile -whatif
            Set-Acl -Path $newFile -AclObject $acl -whatif

Open in new window


Test mode will create directories but simulate the file copy (@line-57-58 restricts this) so you don't have to wait for the copy to finish to confirm results.  Remove these 3 or run the previous code when ready to migrate.
0
 

Author Closing Comment

by:kuzum
ID: 41731166
excellent work
0

Featured Post

Vote for the Most Valuable Expert

It’s time to recognize experts that go above and beyond with helpful solutions and engagement on site. Choose from the top experts in the Hall of Fame or on the right rail of your favorite topic page. Look for the blue “Nominate” button on their profile to vote.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This article provides a convenient collection of links to Microsoft provided Security Patches for operating systems that have reached their End of Life support cycle. Included operating systems covered by this article are Windows XP,  Windows Server…
A bad practice commonly found during an account life cycle is to set its password to an initial, insecure password. The Password Reset Tool was developed to make the password reset process easier and more secure.
In a recent question (https://www.experts-exchange.com/questions/29004105/Run-AutoHotkey-script-directly-from-Notepad.html) here at Experts Exchange, a member asked how to run an AutoHotkey script (.AHK) directly from Notepad++ (aka NPP). This video…
Exchange organizations may use the Journaling Agent of the Transport Service to archive messages going through Exchange. However, if the Transport Service is integrated with some email content management application (such as an antispam), the admini…
Suggested Courses

876 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question