4

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?

3
  • What is the user's current folder versus their old folder name? They'll need administrative privileges unless you are specifying their SID in the command. Commented Mar 28, 2018 at 15:40
  • So the old folder name would be their username ie "charlie". The new folder name is charlie.domain. So to redo the permissions they do need admin privelege, which is my problem. To automate the whole thing through scripting, I need to use environment variables in the script to point to the correct folder and create a shortcut etc. Problem is, running the script with admin privileges causes the environment variables to resolve to the admin account, for example, $home will resolve to C:\Users\Administrator instead of C:\Users\charlie. And $env:USERNAME will resolve to Aministrator. Commented Mar 28, 2018 at 21:52
  • @MagicMatt I have somewhat misunderstood the context. I have improved my answer in PowerShell. See if that will help you. Commented Mar 29, 2018 at 7:28

2 Answers 2

2

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
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks, this looks like exactly what I'm looking for, I'll get a chance to test in the next week or two. I'll let you know how I go.
Thankyou!! That worked a charm! Exactly what I was looking for. I had to make one minor adjustment on your query session filter, as the '>' would change places when executed under SYSTEM account during scheduled task. Heres the change I made: $m = query session | Select-String -Pattern "console\s*(\S*)\s"
-1

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()

6 Comments

Thanks tukan for the reply and solution. The problem here then would be that the user themselves doesnt have the required permission to make the changes to the folder. The only people with permission to change the permissions are the Local Administrators group and Domain Admins. Does this method somehow bypass that?
@MagciMatt no this script is not bypassing this limitation. Could you list your exetion policy? Get-ExecutionPolicy -List
@MagicMatt you could also have an "emergency" situation and make the users temporary local admins.
Why are you using the Process class instead of just using Start-Process.. and passing the credentials makes no sense, nor does the ICACLS business considering it's the user's desktop and they don't have access to the other folder.
@TheIncorrigible1 you were partially right. If it is on the user's deskotp different approach is needed. I'm using the the System.Diagnostics.Process due to the (domain) security context change. If you can do it Start-Process please show me your code.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.