Reputation: 43
I accidentally deleted 180 users from my AD and they aren't recoverable. I have recreated the accounts in AD and what not. This creates a new profile on their laptops when they login because of the new SID. I'm trying to write a script that grants them access to their old profile folder and create a shortcut on their desktop that leads there.
I've got the script working fine with one problem. The environment variables that are used, end up referring back to the admin account that runs the script. The users themselves don't have permission to change security on their old folder. I need to try and have the environment variables refer to the user yet have the privilege of an admin account to rewrite the permissions.
Here is the script so far.. I'm deploying this with Task Scheduler at the moment, which is another can of worms in that I'm not entirely understanding of the credential side of things there. I mean ideally, the task would run as a domain admin, execute the script asap, and have the script resolve the environment variables to the logged on user.
$permission = ":(OI)(CI)M"
$sam = $env:USERNAME
$folderName = "C:\Users\$($sam)"
Invoke-Expression -Command ( 'ICACLS $folderName /grant:r $sam$($permission) /t' )
$WshShell = New-Object -comObject WScript.Shell
$Shortcut = $WshShell.CreateShortcut("$Home\Desktop\Profile Backup.lnk")
$Shortcut.TargetPath = $folderName
$Shortcut.Save()
Its the $env:USERNAME and $home variables that are giving me trouble..
Or is there another way I should be tackling this problem?
Upvotes: 4
Views: 1306
Reputation: 17347
Edit I have given it second thought over-night so I'll update the answer. You will be required to have domain admin password encrypted and then users will run the script.
It always sucks when something like this happens. I don't have a possibility to try this out, but I think the following approach would be feasible. The script asks user for password encrypts it and run the command as the user.
First phase would be to have a domain admin to encrypt his password to a file:
This is to be prepared by Domain Admin (distributed with the PS script) - I recommend changing password after the recovery is complete:
1) Read-Host -AsSecureString | ConvertFrom-SecureString | Out-File 'C:\<script_path>\admin_passwd.txt'
2) This is to be executed by user (you have to fill in the admin user id and have the password file distributed with the script). The script path can be obtained by (Get-Location).Path
. I'm not adding it into the source code so you can decide how to implement it:
$permission = ":(OI)(CI)M"
$admin= "<your_admin_userid>"
$sam = $env:USERNAME
$domain = $env:UserDomain
$folderName = "C:\Users\$($sam)"
# get domain admin password
$encrypted_passwd = get-content 'C:\<script_path>\admin_passwd.txt' | ConvertTo-securestring
# Setting process invocation parameters.
$process_start_info = New-Object -TypeName System.Diagnostics.ProcessStartInfo
$process_start_info.CreateNoWindow = $true
$process_start_info.UseShellExecute = $false
$process_start_info.RedirectStandardOutput = $true
$process_start_info.RedirectStandardError = $true
$process_start_info.UserName = $admin
$process_start_info.Domain = $domain
$process_start_info.Password = $encrypted_passwd
$process_start_info.Verb = 'runas'
$process_start_info.FileName = 'ICACLS'
$process_start_info.Arguments = "$folderName /grant:r $sam$($permission) /t"
# Creating process object.
$process = New-Object -TypeName System.Diagnostics.Process
$process.StartInfo = $process_start_info
# Start the process
[Void]$process.Start()
$process.WaitForExit()
# synchronous output - captures everything
$output = $process.StandardOutput.ReadToEnd()
$output += $process.StandardError.ReadToEnd()
Write-Output $output
$WshShell = New-Object -comObject WScript.Shell
$Shortcut = $WshShell.CreateShortcut("$Home\Desktop\Profile Backup.lnk")
$Shortcut.TargetPath = $folderName
$Shortcut.Save()
Upvotes: -1
Reputation: 1660
You could use query session
command to get the login name of the current logged on user. Then create NTAccount
object based on that to retrieve SID
and win32_userprofile
WMI object to find out the profile path. Like this:
$m = query session | Select-String -Pattern "\>console\s*(\S*)\s"
$sam = $m.Matches[0].Groups[1].value
$acc = New-Object System.Security.Principal.NTAccount($sam)
$sid = $acc.Translate([System.Security.Principal.SecurityIdentifier]).Value
$profile = Get-CimInstance -ClassName win32_userprofile -Filter "SID='$sid'"
$folderName = $profile.LocalPath
Upvotes: 2