Powershell registry access multiple options - powershell

To access or make changes to registry in a windows machine by powershell, I see two ways
cd HKLM:\ (or set-location -path
HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion)
Get-childitem
or
Get-Item -path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run
Get-ItemProperty , New-ItemProperty , Set-ItemProperty
When to use one over the other?

They are both necessary, because the property values aren't accessible on the Item objects (and you can't see the nested "child" container items with the ItemProperty commands).
My 2c: the registry provider was written by someone as a demo, and then shipped and now they're afraid to change it ... it's the only way to explain the whole "ItemProperty" thing.
Basically, when they mapped the registry to the PowerShell Provider semantics, instead of having "Container" and "Leaf" items, there are only containers, and each container has properties (and/or child containers).
So if you do Get-ChildItem HKCU:\SOFTWARE\Microsoft you get a response back listing the "Name" of each of the child containers (which the Registry Editory (Regedit.exe) would show as folders), and listing the values in them under the heading "Property" -- but that listing is purely in the display, and the Property field on the object you got back is actually just a string array listing the names of the properties so you know what you can do next:
If you want to actually read the values in a way that makes them accessible to your script, you need to use Get-ItemProperty
If you want to change the value, you need to use Set-ItemProperty
To create new ones, you need to use New-ItemProperty
In your example, for instance, you might see SecurityHealth:
But it's like the screenshot above, as a human, you can see the value, but your script can't read the value...
You have to use Get-ItemProperty -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run to get an object back that actually has the SecurityHealth property with the C:\WINDOWS\System32\SecurityHealthSystray.exe value...

Related

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

What is the purpose of putting Class after your variable like this ($_.Class)?

What is the purpose of this string? I am still new to PowerShell and have seen this come up quiet a bit.
$_.Class
Here is an example of how I have seen it used:
$R.AllElements|?{$_.Class -eq "table"}|select innerText
Does this meant that we are applying a class on the $R variable? Or is there a "Class" already for that variable that we are searching for the string "table"? I have looked around but cannot find any explanation.
Here's an example for you to understand the purpose of $_.xxxxx
$Obj = Get-Item -Path 'C:\Program Files'
This would put any information gathered by the Get-Item command and store it in $Obj. If you then show what's in the variable, it will look something like this
If you would then do $obj.xxx where xxx is one of the property names shown above, it will show you the values under that property like this
Another way to get the values of said properties is how you have shown in your post. If you pipe the variable into a where statement like below, it is especially helpful when trying to filter out some text inside a particular variable. This example is looking for the text prog in the Name property of all the items inside of $Obj2
I wish I had time to give more details, I hope this helps you some! PowerShell is one of the best tools for Automation and Administration in a Windows environment so keep on learnin!
Bonus: Here is a link to documentation on PowerShell's pipelines and how it works, I referred to it as 'pipe' in my wordage above

PowerShell Rename-Item is creating a copy of the file

My script is supposed to rename c:\myfolder\myfile.txt to myfile.bak
Rename-Item "c:\myfolder\myfile.txt" -NewName "myfile.bak"
However, it leaves myfile.txt in place and creates a new file called myfile.bak instead
Does anyone know why?
If its a hidden or read-only file, you have to add the -force parameter:
Forces the cmdlet to rename items that cannot otherwise be changed,
such as hidden or read-only files or read-only aliases or variables.
The cmdlet cannot change constant aliases or variables. Implementation
varies from provider to provider. For more information, see
about_Providers.

How to Remove the Hidden attribute from a text file

Powershell Version: 4.0
Operating System: Windows 7
"Error Report" | Set-Content $errorText
$getError = Get-Item $errorText
$getError.Attributes ="Hidden"
I've created an error log file which will remain hidden unless their is an error. How would I remove the hidden attribute so that I could see my file? In other words what is the equivalent of right clicking the file, selecting properties, and unchecking hidden attribute in powershell?
Attributes property is of type [System.IO.FileAttributes]. Looking at TechNet you can see the valid options for setting attributes on file. As per the comments one option you have is no remove all attributes from the file/folder.
Normal - The file is a standard file that has no special attributes. This attribute is valid only if it is used alone.
Be aware that this would potentially remove other attributes like read-only or system. In your case that might not be a concern but we need to be aware of the possibility.
The related second issue about using Get-Item on hidden files is solved by using the switch -Force and explained on TechNet as well.
Allows the cmdlet to get items that cannot otherwise be accessed, such as hidden items.
Knowing that we could do something like this:
$getError = Get-Item $errorText -Force
$getError.Attributes ="Normal"

Using Powershell to grab Registry Key data to build an If Else

I am trying to use Powershell to check a particular registry key we use on servers in HKLM\SOFTWARE to identify their status as an Alpha, Beta or General server. I am not seeing an easy way to do this. I took a look at the Get-ItemProperty cmdlet, but that doesn't allow me to actually select the exact key within SOFTWARE that has the data I need to build out an If Else loop that can output the server type.
In its simplest form, I would like to use this Powershell script to read that key (to see if Alpha, Beta, General) and then depending on which, output simply Alpha, Beta or General as a text file.
Have you tried Get-Item?
$keyInfo = Get-Item -Path $Key
#Where Key is something like hklm:\Software..
#This will give you all the subkeys to that key
$keyInfo.GetSubKeyNames()
#This will give you data stored in the values of the key.
$keyInfo.GetValue($ValueName, $null, [Microsoft.Win32.RegistryValueOptions]::DoNotExpandEnvironmentNames)