ChangeOwner Script

This topic contains 0 replies, has 1 voice, and was last updated by Profile photo of Forums Archives Forums Archives 5 years, 5 months ago.

  • Author
    Posts
  • #6222

    by Sentri at 2012-11-30 15:33:11

    Hello All!

    Over the past couple of months, I have been trying to figure out a way to point our users Local profile, to their soon to be, Domain profile. After lots of research, the Change Owner method, found in the WMI UserProfile class seemed to be a viable option for our environment. A user's Local account name will be the same as their Domain account name once they log in, and all of the domain accounts have currently been created and sitting in AD, waiting to be used. All my script needs is the computer name and it can go ahead and supplant every local user SID on that specified computer, with the corresponding Domain SID. As you will see in the notes, this script takes input of single or multiple values from the pipeline, parameter, and if you have a .csv you're working off of, it will take whatever is in there as well, if you wish. So, if anyone is in the middle of a profile migration and has a similar scenario, feel free to take a look and use whatever or all of what you see below! Profile migrations are never fun, so hopefully this can help anyone in need! Finger point to Don Jones and his Powershell Month of Lunches; this ebook has been EXTREMELY instrumental in everything I know about Powershell, including lots of functionality I've been able to incorporate into this script. I can't say enough about how fantastic that book is and what it has done for me– thank you, DJ!

    Without further ado, script below:

    ##The ChangeOwner function in this script will supplant a user's Local SID with their Domain SID
    ##This script can run in 3 different ways:
    ##Modify the UserList.csv 'ComputerName' field
    ##Pipe in single or multiple values
    ##Feed single or multiple values through the 'ComputerName' parameter
    ##An error log is also generated on the Administrator's machine and located in c:\errors.txt

    $WorkingDirectory = $ENV:Userprofile+"\Documents\Scripts\ADBulkImport\"
    $UserList = Import-Csv ($WorkingDirectory + "UserList.csv")
    $Computers = $UserList | Select-Object -ExpandProperty ComputerName

    function ChangeOwnerWork {
    param ([string] $ComputerName)

    $Users = gwmi win32_useraccount -ComputerName $Computer | foreach{$_.Name}

    foreach($User in $Users) {
    Trap {
    $_ | Out-File c:\errors.txt -append
    continue
    }

    $OriginalUser = gwmi win32_UserAccount -ComputerName $Computer -Filter "Name= '$User' AND LocalAccount=True"
    $NewUser = gwmi "win32_UserAccount WHERE Name= '$User' AND Domain='Cul'"
    $Profile = gwmi win32_UserProfile -ComputerName $Computer -filter "SID= '$($OriginalUser.SID)'"
    $Profile.ChangeOwner($NewUser.SID,0)

    }
    }

    function ChangeOwner {
    param (
    [Parameter(ValueFromPipeline=$True,
    ValueFromPipelineByPropertyName=$True)]
    [string[]]$ComputerName
    )

    BEGIN {
    del c:\errors.txt -ea SilentlyContinue
    $usedParameter = $False
    if ($PSBoundParameters.ContainsKey('computername')) {
    $usedParameter = $True
    }
    }
    PROCESS {
    if ($usedParameter) {
    foreach($Computer in $ComputerName) {
    ChangeOwnerWork -ComputerName $Computer
    }
    } else {

    foreach($Computer in $Computers) {

    $Users = gwmi win32_useraccount -ComputerName $Computer | foreach{$_.Name}

    foreach($User in $Users) {
    Trap {
    $_ | Out-File c:\errors.txt -append
    continue
    }

    $OriginalUser = gwmi win32_UserAccount -ComputerName $Computer -Filter "Name= '$User' AND LocalAccount=True"
    $NewUser = gwmi "win32_UserAccount WHERE Name= '$User' AND Domain='Cul'"
    $Profile = gwmi win32_UserProfile -ComputerName $Computer -filter "SID= '$($OriginalUser.SID)'"
    $Profile.ChangeOwner($NewUser.SID,0)

    }
    }
    }
    }
    END{}
    }
    ChangeOwner
    Write-host "DONE!" -ForegroundColor Green

    by DonJ at 2012-12-01 14:42:53

    As a tip, you can use the Code or PowerShell buttons in the editor toolbar to format your code here in the forums. Helps preserve indentation and so forth! And thanks very much for the kind words – glad you found it to be helpful!

    by Sentri at 2012-12-01 22:50:22

    That is good to know! Also, I realized I had the cmdlet binding parameter pipeline values in there, and they are not needed in this script, since I do check for parameter usage; however, I may go back and add the cmdlet binding as a part of my function to make my code a little more concise! I'm looking forward to your latest and greatest, Don!

    by RichardSiddaway at 2012-12-03 07:09:15

    Don't forget the [CmdletBinding()] also gives you the verbose & debug parameters which can be very useful in their own right

    I would also recommend against using aliases in your scripts

    by Sentri at 2012-12-03 14:09:09

    Good points, Rich! I actually just added in cmdlet binding for -whatif and confirmation box before running. I actually came on here to update with that note and found that you've read my mind!

    by Sentri at 2013-04-15 14:03:43

    Here's the final version of this script:
    # The ChangeOwner function will supplant a user's Local SID with their Domain SID
    # This script receives input in 4 different ways:
    # Modify the values of the UserList.csv 'ComputerName' field, and feed the '$Computers' variable to the 'ComputerName' parameter
    # By parameter(single or multiple values)
    # Pipline by value(single or multiple values)
    # Pipeline by property name(single or multiple values)
    # An error log is generated on the Administrator's machine for all user accounts that fail to change owner.
    # Error log location is c:\errors.txt

    $WorkingDirectory = $ENV:Userprofile+"\Documents\Scripts\ADBulkImport\"
    $UserList = Import-Csv ($WorkingDirectory + "UserList.csv")
    $Computers = $UserList | Select-Object -ExpandProperty ComputerName

    function ChangeOwnerWork {
    param ([string]$ComputerName)

    $Users = gwmi win32_useraccount -ComputerName $Computer | foreach { $_.Name }

    foreach ($User in $Users) {

    if ($User -eq 'win7desk') {
    Write-Host "$User is not supposed to change!" -ForegroundColor Yellow
    } elseif ($User -eq 'Guest') {
    Write-Host "$User is not supposed to change!" -ForegroundColor Yellow
    } elseif ($User -eq 'localadmin') {
    Write-Host "$User is not supposed to change!" -ForegroundColor Yellow
    } else {

    Try
    {
    Write-host "Changing Owner on $User..." -ForegroundColor Cyan
    $OriginalUser = gwmi win32_UserAccount -ComputerName $Computer -Filter "Name='$User' AND LocalAccount=True" -ea Stop
    $NewUser = gwmi "win32_UserAccount WHERE Name='$User' AND Domain='Cul'" -ea Stop
    $Profile = gwmi win32_UserProfile -ComputerName $Computer -filter "SID='$($OriginalUser.SID)'" -ea Stop
    $Profile.ChangeOwner($NewUser.SID,0)
    Write-Host "ChangeOwner complete on $User!" -ForegroundColor Cyan
    }

    Catch
    {
    Write-Host "Logging Error.." -ForegroundColor Red
    $Computer + " " + "|" + " " + $User + " " + "|" + " " + $_ | Out-File c:\errors.txt -append
    }

    }

    }

    }

    function ChangeOwner {
    [CmdletBinding(SupportsShouldProcess=$True,
    ConfirmImpact='Medium')]
    param (
    [Parameter(Mandatory=$True,
    ValueFromPipeline=$True,
    ValueFromPipelineByPropertyName=$True)]
    [string[]]$ComputerName
    )

    BEGIN {
    del c:\errors.txt -ea SilentlyContinue
    }

    PROCESS {

    foreach ($Computer in $ComputerName) {

    if ($pscmdlet.ShouldProcess($Computer))
    {

    if (Test-Connection -ComputerName $Computer -Count 1 -Quiet)
    {

    ChangeOwnerWork -ComputerName $Computer

    }

    else
    {

    Write-Host "$Computer is offline!" -ForegroundColor Red

    }

    }

    }

    }

    END {
    Write-host "Operation complete!" -ForegroundColor Green
    }

    }
    ChangeOwner -ComputerName $Computers

You must be logged in to reply to this topic.