Powershell and registry key changing challenge - powershell

I make changes under hklm with a line like this:
Set-Location HKLM:\software\afilefolder\afilefolder
and it works. I also need to make a change to a current user key, I am told to do this by making a change to hkey_users, but i have about 5 machines that would run this script and based on what machine it is, i need to make a change to my location, because hkey_users has an sid as the next file folder and it changes for each user. so based on the user, i grab the sid, I have all of them. and i set my location like this:
$test = "hkey_users\" + $hkeypath + "\filefolder\filefolder"
Set-Location $test
I cannot put the concatenation in the Set-Location line, powershell no likey, but when I do it this way, it says the following path cannot be found: C:\windows\system32\HKEY_USERS\correctsid\filefolder\filefolder
why does it look in the system32 folder? how do i make changes to hkey_user. please advise

You can set the location just fine, with the string concatenation, just put the whole thing in the double quotes. You'll want to reference that it's in the registry just to be safe, try this out:
Set-Location "registry::hkey_users\$hkeypath\filefolder\filefolder"
That worked for me (well, I set my SID to $mysid and then did a Set-Location "registry::hk_users\$mysid\software" and that got me to my software key in the registry, under my SID).

Related

Force Powershell to create AD user folder when setting HomeDirectory value

During the New-ADUser command: -HomeDirectory = '\sharedrive\folder$%username%'
When this value is set in Powershell, the value appears as \\sharedrive\usersfolder$\%username% under the Home Directory.
Result:
However, if I manually enter that same string into the Active Directory Users and Computers menu and then hit apply, it autofills to the person's username where %username% exists and creates a folder on that share drive with proper permissions, shown below:
How can I get Powershell to autofill this username and create the folder? Just writing the string out with the user's name does not work.
I think there are a couple of problems here. PowerShell doesn't know how to interpret your input string '\sharedrive\folder$%username%'
For one, it is a literal string - so even if PowerShell knew that $%username% meant "convert this value to the username environment variable" it would still interpret it as the literal characters entered in the string. What you're appearing to try and do is string interpolation which requires that you use double quotes ".
Second, the %username% portion is not the way that you use environment variables in PowerShell. There are a few ways to get this value. $env:USERNAME should work on windows, so would [Environment]::username.
So you would want to do something like this "\sharedrive\folder$([Environment]::username)"
for a user 'someuser' this would return "\sharedrive\foldersomeuser"
You're confusing both environment variables AND how these values are set in ADUC and when using Powershell cmdlets.
%username% is a Windows environment variable which can be translated, thus when you hit the "Apply" button the ADUC console translates the username from the account you're creating, then in the background goes and creates that folder using the credentials of whoever is running ADUC, then (if you hit the "Yes" button) also repermissions it to give that user Full Control.
Once again its the ADUC which creates the folder for you, it doesn't happen just because you set those properties on the account object. If you want Powershell to do this then you need to carry out the folder creation and permissioning yourself, either manually or via more Powershell scripting.
Try something like this:
$NewUser = Read-Host "please enter a username"
New-ADUser -Name "$NewUser" -HomeDirectory "\sharedrive\folder\$NewUser"
Btw Efie is absolutely right about how environment variables are being passed, but the other thing is that those variables he mentioned will be the variables of whomever is running the script, not the user you are creating.

Powershell: Cannot read a specific Registry-Value

I am struggling to read this REG-value via Powershell 5:
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\SWD\DAFWSDProvider\urn:uuid:cfe92100-67c4-11d4-a45f-0026abfabc42/uri:urn:uuid:cfe92100-67c4-11d4-a45f-0026abfabc42/01]
"Driver"="{6bdd1fc6-810f-11d0-bec7-08002be2092f}\\0000"
Even the autocomplete-function in Powershell showing me the REG-path to that key is not working properly.
Why is it failing? How can I get this value?
This is the code which is surprisingly NOT working as expected:
$sub = 'urn:uuid:cfe92100-67c4-11d4-a45f-0026abfabc42/uri:urn:uuid:cfe92100-67c4-11d4-a45f-0026abfabc42/01'
get-Item -literalPath "HKLM:\SYSTEM\CurrentControlSet\Enum\SWD\DAFWSDProvider\$sub"
Here a screenshot of the subkey that I cannot read:
I could now drill it down to this situation:
subkey 'urn:uuid:cfe92100-67c4-11d4-a45f-0026abfabc42' -> OK
subkey 'uuid:cfe92100-67c4-11d4-a45f-0026abfabc42/u' -> OK
subkey 'urn:uuid:cfe92100-67c4-11d4-a45f-0026abfabc42/u' -> fail!
subkey 'urn:uuid:cfe92100-67c4-11d4-a45f-0026abfabc42/u' under HKLM:\Software -> OK
Using Sysinternals Process Explorer, I've discovered what happens.
PowerShell replaces the forward slashes in the path unconditionally with backslashes, even when you use -LiteralPath.
That's clearly a bug.
To work around it, you can use the PSPath of the registry key, apparently PowerShell leaves those alone. For the local registry, the PSPath always starts like this:
Microsoft.PowerShell.Core\Registry::
and after that goes on with the regular key name as it would appear in RegEdit.
$path = "Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\SWD\DAFWSDProvider\urn:uuid:e3248000-80ce-11db-8000-30055c83410f/uri:e3248000-80ce-11db-8000-30055c83410f/PrinterService"
Get-Item $path
PSPaths are an integral part of anything that Powershell treats as one of its drives. You can select them, or access the .PSPath property:
$path = "Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\SWD\DAFWSDProvider"
Get-ChildItem $path | Select -ExpandProperty PSPath
(Get-Item C:\).PSPath
At the end it turns out, that I had to use a different Syntax for the REG-Path to make the call work - very strange!
See this code:
$prefix1 = "Registry::HKEY_LOCAL_MACHINE"
$prefix2 = "HKLM:"
$subDir = "urn:uuid:cfe92100-67c4-11d4-a45f-0026abfabc42/uri:urn:uuid:cfe92100-67c4-11d4-a45f-0026abfabc42/01"
get-item "$prefix1\SYSTEM\CurrentControlSet\Enum\SWD\DAFWSDProvider\$subDir"
get-item "$prefix2\SYSTEM\CurrentControlSet\Enum\SWD\DAFWSDProvider\$subDir"
The first "get-item" call using prefix1 is working fine while the second one is not returning anything back.
Lession learned: Better use the longer REG-Prefix like in the original PSPATH to avoid any unexpected side-effects.
From Microsoft's PowerShell documentation, you can decide if you would like to view the entries as a list or to retrieve a single registry key.
https://learn.microsoft.com/en-us/powershell/scripting/samples/working-with-registry-entries?view=powershell-7.1

Start process using wildcard for drive letter

I have a file which will always be located on a users desktop, however, depending on how the machine was set up, the desktop could be located on the C drive or D drive.
Below is what I have tried to use. On it's own, (Get-Location).Drive.Name will return the C drive on my machine. However, if I combine it into the full line of code to start the program, it does not work.
What am I doing wrong?
$userName = [Environment]::UserName
Start-Process ((Get-Location).Drive.Name)\Users\$($userName)\Desktop\VIPHorizon\Service_Desk.url
While the other answer is correct that you are missing a colon, simply adding that is not sufficient.
If you try running it with the colon, you will get another error like so:
Unexpected token ':\Users' in expression or statement.
In order to fix this, you need to wrap the whole thing in quote marks.
"((get-location).Drive.Name):\Users\$($userName)\Desktop\VIPHorizon\Service_Desk.url"
Then you will find that the ((get-location).Drive.Name) is written directly into the string, instead of being replaced. which can be fixed by prefixing the call with a dollar sign like you have already done for userName.
"$((get-location).Drive.Name):\Users\$($userName)\Desktop\VIPHorizon\Service_Desk.url"
You need to put a colon ( : ) right after your drive letter:
$userName = [Environment]::UserName
Start-Process ((get-location).Drive.Name):\Users\$($userName)\Desktop\VIPHorizon\Service_Desk.url
The proper way to get current users Desktop even if relocated is:
[Environment]::GetFolderPath('Desktop')
So use:
Start-Process (Join-Path [Environment]::GetFolderPath('Desktop') "VIPHorizon\Service_Desk.url")
To eumerate all special folders and current settings:
$SpecialFolders = [Environment+SpecialFolder]::GetNames([Environment+SpecialFolder])|Sort
ForEach ($SpecialFolder in $SpecialFolders) {
[PSCustomObject]#{
SpecialFolderName = $SpecialFolder
SpecialFolderLocation = ([Environment]::GetFolderPath($SpecialFolder))
}
}
The global Powershell variable $HOME will give you the home location for the active user.
Start-Process $HOME\Desktop\VIPHorizon\Service_Desk.url

What exactly does the Resolve-Path cmdlet do?

I've started working with Powershell lately on my Windows 10 system. I've created a profile file, and I wanted to put in a variable which links to a folder in my documents section. However, I didn't want to hard-code the path because I knew I'd need to go in and re-write it if my profile name got changed in a hard drive transfer like it did the last time I sent it in for repairs. So my first thought was to put in something like this:
$Var = $(~\Documents\Folder)
But that spat back an error. Then I learned of the Resolve-Path Cmdlet, which appeared at a glance to be what I needed. However, when I did this:
$Var = $(Resolve-Path ~\Documents\Folder)
... I got this:
>$Var
Path
----
C:\Users\Username\Documents\Folder
>
Which seemed like a problem. However, when I tried to cd $Var, it worked successfully, which confused me greatly. I figured that the extraneous Path header in the result would cause an error.
What exactly does Resolve-Path do, and why does it still get interpreted correctly when passed into cd? And additionally, is there any way to make Resolve-Path not include the extraneous information and return only the expanded path?
The reason you are seeing the header Path is because Resolve-Path is returning an object of type System.Management.Automation.PathInfo and when this is not captured into a variable it is outputted as a string to the console in a readable format IE:
ObjProperty1 ObjProperty2 ObjProperty3 ...
--------- --------- --------- ...
Value1 Value2 Value3 ...
This object works with cd as PowerShell is smart enough to parse the object ($var) before cd is run. PowerShell will return the value of the path property to cd meaning cd will see a string "C:\Users\Username\Documents\Folder" and not the object headers.
If you want to just return the path without the header use the Select cmdlet's -ExpandProperty parameter:
$var = Resolve-Path '~\Documents\Folder' | select -ExpandProperty Path
If you would like more information on Resolve-Path MSDN is a good place to start (link).
Easy Example for a Resolve-Path job,
Let's say you don't know the office version in your computer and want to get the correct path, Resolve-Path can help...
$TestPath = 'C:\Program Files (x86)\Microsoft Office\*\Winword.exe'
$Path = (Resolve-Path $TestPath).Path
Resolve-Path is a good way to find a nested file or folder with wildcards in the middle of the folder path (not just in the path's Leaf).
Best use case I've seen is, when a restore request comes into the SD and the claim is that an entire folder disappeared. Someone probably moved the folder into (under) an adjacent folder in their GUI. Easily find that folder like this:
PS> Resolve-Path 'folderOldLocation\*\folderName'
PS> Resolve-Path 'folderOldLocation\*\*\folderName'
PS> # Going deeper is unlikely to find it
PS> # and will take much longer to return
It's a very quick way to check for a quick fix to an otherwise time-consuming restore request.

Insert Username in to file path Powershell

We are in the process of trying to tidy up our users home directories and speed up some office 2007 performance by moving all their templates in to a new directory on their user drive (U:). During my initial tests I can get the below script to work fine though it has the obvious problem of only working for my username. Is there a way to get it to take the currently logging in user? Before this would be handled by %username% and from a brief scan of the internet apparently:
$[Environment]::UserName
Should work. However I seem to be getting errors. Is there a better way to achieve the current logging in users name in to the file path?
if (!(Test-Path -path '\\SERVER\PATH\TO FILES\$[Environment]::UserName\Normal\'))
{
New-Item '\\SERVER\PATH\TO FILES\$[Environment]::UserName\Normal\' -type directory
##Move-Item \\SERVER\PATH\TO FILES\$env:username\Normal.dot \\\SERVER\PATH\TO FILES\$env:username\Normal\
## Move-Item \\SERVER\PATH\TO FILES\$env:username\*.dotm \\SERVER\PATH\TO FILES\%username%\Normal\
}
else
{
"No work to do"
}
Two problems. If you want variable/expression substitution to take place in a string, you need to use quotation-marks, not apostrophes, to enclose the string. In this case, you also need to add some parenthesis to denote an expression within the string.
"\\SERVER\PATH\TO FILES\$([Environment]::UserName)\Normal\"