How to Edit HKCU values with PowerShell - powershell

When I run the command to edit a registry value on HKCU with PowerShell, I have to run PS as an admin to have perms to edit the registry. Unfortunately, this changes HKCU to my admin account (as far as I can tell, at least), which keeps me from editing the user.
I need to automate this as we’re rolling out hundreds of machines. Am I missing something?

When running an elevated PowerShell, the user specific registry can be edited under HKEY_USERS\<Users SID>\.... For example:
Get-ItemProperty -Path "registry::hkey_users\$($strSID.Value)\Software\Policies\Microsoft\Windows\Control Panel\Desktop"

Related

Powershell $PROFILE variable pointing to wrong location. Where is $PROFILE variable it set?

After doing some changes to my machine, Powershell fails because the $PROFILE variable points to a different location than before, i.e. it is set to
C:\Powershell\Microsoft.PowerShell_profile.ps1
instead of
C:\Users\user\Documents\Powershell\Microsoft.PowerShell_profile.ps1
This causes problems like installed modules not found and more. So my question is how does Powershell set the value of $PROFILE? Can it be changed?
Solved. It turns out that before the problem occurred, $PROFILE had pointed to Documents folder in OneDrive, i.e.
C:\Users\user\OneDrive\Documents\PowerShell\Microsoft.PowerShell_profile.ps1
When I enabled Documents backup to OneDrive and relogged in the $PROFILE was back to the correct location. It seems that if Powershell doesn't find the profile location under Documents, or $HOME it defaults to the path C:\Powershell. However I am not sure - would be nice to have clear specification on this behaviour.
I came across this while searching for an answer.
To change where Powershell will look for the default profile you need to change a registry key.
Please note that the profile wil be found under a new directory WindowsPowerShell/Microsoft.PowerShell_profile.ps1.
Desired path: C:/Users/admin
Powershell profile: C:/Users/admin/WindowsPowerShell/Microsoft.PowerShell_profile.ps1
Manual way:
Open up the Registry Editor and navigate to:
Computer\HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders
Change the value of Personal to the directory of your choice.
Automated way with powershell:
Set-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders" -Name "Personal" -Value "DRIVEHERE"
Then you can test the value was set with:
Get-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders" -Name "Personal"

Is there a way to map a local drive in powershell when the script is set to "Run As Admin"?

This is a portion of my powershell script where I have to map a local folder to the S: Drive. I can't map New-PSDrive when my script 'Run as Admin'. If I do, it is not visible on 'My PC'. I have ran Get-PSDrive and it shows it is visible just not on 'MY PC'.
I have tried Net-Use within PS.
I have tried New-SMBmapping
New-SMBmapping -localpath 'S:' -remotepath '\\$comName\pos' -persistent $true
My script needs to Run As Admin for the rest of my script.
Currently this is the my script.
#Get Computer name
$comName = $computerNameCSV.ComputerName
#This will map folder to S drive
New-SmbShare -Name "SOP" -Path "C:\FolderShare" -FullAccess Everyone
New-PSDrive -Name "S" -Root "\\$comName\c$\FolderShare" -Persist -PSProvider "FileSystem"
Short answer:
You can't.
Long answer:
The reason is all about the User Context. When you open a normal PowerShell console, you run that console under your current user context. That is why, when you run the command to map the share in PowerShell, it shows up in your currently logged in user context.
When you launch PowerShell via Run As Admin, you create a new user context. Running commands to map the share creates the mappings inside that context, which is different than your currently logged in user context. I.e. conceptually think about Running as Admin is as if you physically logged into the machine as a different user.
One workaround would be to separate the script into two parts, the first one runs under the current user context and maps the drive, and a second one that can be launched with Admin privileges to do what is needed. e.g. Inside your script you launch the second script as admin with:
Start-Process powershell -Verb runAs AdminScript.ps1
The visibility of mapped drives between admin and non-admin contexts is restricted by design. You can disable this behaviour using Group Policy or the registry, as described here:
Mapped drives are not available from an elevated prompt when UAC is configured to "Prompt for credentials" in Windows

Working around the "You don't currently have permission to access this folder" issue for PowerShell

When navigating to C:\Users\%SomeUsername% as an administrator on a Windows 2008 R2 server I get the error You don't currently have permission to access this folder, Click Continue to permanently get access to this folder. Clicking Continue resolves this problem.
If I try the same by PowerShell (e.g. get-childitem 'C:\Users\' -Directory | get-childitem -Force; or some variant), any profiles to which I've not already granted myself access explicitly give the error Access to the path 'C:\Users\%SomeUsername%' is denied.; even with the Force switch included.
Is there a way to "click continue" via PowerShell; i.e. have the system give me access to anything which I don't strictly have access to, though as an administrator on the server can grant myself access to. Ideally this would be done as I access the files (e.g. by a switch on the Get-Item command) rather than having to code something to explicitly go through all files checking and amending permissions.
Make sure about start Powershell Run As Admin if you want always run it as administrator make shortcut from powershell.exe and follow this image :
My mistake; I hadn't been running the PowerShell session as administrator (i.e. UAC).
right click on powershell.exe
run as administrator

Deleting all locally stored user profiles on log off

I want to delete all locally stored user profiles on logoff using a Powershell script. I've the following script:
Set-ExecutionPolicyRemoteSigned[gc]::collect()
cmd /c start reg unload "HKCU"Remove-PSDrive HKCU import-module C:\Windows\System32\WindowsPowerShell\v1.0\Modules\ManageUserProfiles\ManageUserProfiles.PSM1
get-userprofile |where{ $_.SID -ne ("S-1-5-21-3071724114-2656578308-4228372245-500")} | remove-userprofile
I'm a complete newbie to powershell. So could someone tell me whether this script meets my needs and how does it run? And could you also explain what $_.SID -ne ("S-1-5-21-3071724114-2656578308-4228372245-500") means too. Thanks in advance.
I am not familiar with the module that you are running, and it looks like that should be 6 lines not 3 (insert break before [gc], before Remove-PSDrive, and before Import-Module).
Next, add a space between Set-ExecutionPolicy and RemoteSigned.
Now, the script appears to collect user profiles, pipes them through a Where statement that excludes the Administrator account from the list of profiles, and then removes all remaining profiles. Let's step through it...
Set-ExecutionPolicy RemoteSigned
This sets your execution policy. I'm going to assume this is to avoid issues with an unsigned module that you load in a couple steps.
[gc]::collect()
This forces the garbage collection to clean up memory and remove unused resources. This line can probably be skipped.
cmd /c start reg unload "HKCU"
This uses the reg.exe command line application to unload the HKEY_CURRENT_USER hive from within the current registry set. This would need to be done before deleting a profile since you can't delete files that are in use.
Remove-PSDrive HKCU
This does pretty much the same thing, but for PowerShell's registry provider. I'm guessing this is so that you don't get errors, or so that it doesn't try to reload the HKCU hive.
C:\Windows\System32\WindowsPowerShell\v1.0\Modules\ManageUserProfiles\ManageUserProfiles.PSM1
This loads the 'Manage User Profiles' module. I am not familiar with the module, but you would need to make sure that you have that module installed on the computer that this is running on, so if you are running this on all of your computers you need to install that module on all of your computers.
get-userprofile |where{ $_.SID -ne ("S-1-5-21-3071724114-2656578308-4228372245-500")} | remove-userprofile
This is a command from the module you just loaded. It will, I assume, get user profiles as some sort of custom object, and then it pipes to a Where statement that excludes the Administrator account by stating that it only allows profile objects that do not (-ne is the 'not equal' operator) have a SID property equal to "S-1-5-21-3071724114-2656578308-4228372245-500". So all user profiles except the admin account's profile are then piped to the Remove-UserProfile command, which we can probably assume deletes each profile that is piped to it.
Hopefully that explains what your script is doing.

Using $env:username in a logon script is not working

I have this setup with a GPO to run as a logon script, obviously to map a drive for clients.
net use H: \\server1\share\$env:username
Dead simple. If I put in a specific username in place of the variable then it works. Also, if I run this script directly on a client machine it works.
Do you get an error? Does it helps if you wrap the path in double quotes?
"\\server1\share\$env:username"
That should work with or without the quotation marks. Are the clients all Windows 7? I believe that Powershell logon/startup scripts don't work on earlier versions, even if you have Powershell installed, because it's an add-on rather than a native shell. If you're using downlevel clients, you can invoke the powershell script from a cmd batch file. But if you're going to do that, might as well skip Powershell and just run net use H:\\server1\share\%username% from your batch file.
Run this in a .bat file as a login script (use a FQDN for the server name):
net use H: \\server.example.com\share\%USERNAME%
If that not works, your GPO is just not yet applied. You can force that by running on the machine gpupdate /force.
For testing make sure that the GPO is applied to the right OU to the group "Authenticated Users" (computers are in the group too). And if that is not working, you can also "Enforce" the GPO. Don't forget to do a gpupdate /force after any change to the GPO or it settings.
You can also try a .js logon script like:
var WSH = new ActiveXObject("WScript.Shell");
// Map share
WSH.Run("net use H: \\\\server.example.com\\share");