Get regkey based on search, then add new entry to that key - powershell

I am trying to search the HKLM hive for the key driverdesc that contains the value -like "*Ethernet*"
I can retrieve all the keys with driverdesc, however I cannot filter for the one containing Ethernet and then add the REG_DWORD 'PNPCapabilities' to that key.
Here's how I am searching the registry:
Get-ChildItem "HKLM:\SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002bE10318}" -Recurse -ErrorAction SilentlyContinue | foreach {$_.GetValue("Driverdesc")} | Out-String $Items
$items

You could use my function Search-Registry for this.
Search the registry like this:
Search-Registry -KeyPath 'HKLM:\SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002bE10318}' -Pattern "*Ethernet*" -SearchPropertyValue -Recurse
This will return an array of objects with the following properties (example):
ComputerName : YOURMACHINE
Hive : LocalMachine
HiveName : HKEY_LOCAL_MACHINE
HiveShortName : HKLM
Path : HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002bE10318}\0007
SubKey : SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002bE10318}\0007
ItemType : RegistryProperty
DataType : REG_SZ
ValueKind : String
PropertyName : DriverDesc
PropertyValue : Realtek RTL8168D/8111D Family PCI-E Gigabit Ethernet NIC (NDIS 6.20)
PropertyValueRaw : Realtek RTL8168D/8111D Family PCI-E Gigabit Ethernet NIC (NDIS 6.20)
Using these properties (most likely Path) it should be easy enough to add a new DWord value. So in your case:
$value = 1234
$items = Search-Registry -KeyPath 'HKLM:\SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002bE10318}' -Pattern "*Ethernet*" -SearchPropertyValue -Recurse -Verbose
$items | Where-Object { $_.PropertyName -eq 'DriverDesc' } | ForEach-Object {
# New-ItemProperty either wants the shortpath notation 'HKLM:\path'
# or uses the 'Registry::HKEY_LOCAL_MACHINE\path' notation
$path = $_.HiveShortName + ':\' + $_.SubKey
New-ItemProperty -Path $path -Name 'PNPCapabilities' -Value $value -PropertyType DWORD -Force| Out-Null
}

Related

How do I add a variable into a specific registry key path via Powershell?

I currently have a script which looks for a specific program to exist in Add/Remove programs and I would like to add the "Dell Command" into registry to confirm.
#Find the Dell Command Update in Add/Remove Programs
Get-ChildItem HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall |
% {Get-ItemProperty $_.PsPath} |
where {$_.Displayname -match "Dell Command"} |
sort Displayname | select DisplayName
If you would like to create a key based on the value returned from your search, you can do the following:
$dellCommand = (Get-ItemProperty -Path "HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\*" | Where-Object -Property "DisplayName" -Match "Dell Command").DisplayName
$regKeyPath = "HKLM:\SOFTWARE\$dellCommand"
if (-not (Test-Path -Path $regKeyPath)) {
Write-Output -InputObject "$regKeyPath doesn't exist. Creating key."
$newKey = New-Item -Path $regKeyPath -Force #Create the key if it doesn't exist.
#Add Property values to the key
#$newKey | New-ItemProperty -Name "blah" -Value "valuevalue" -PropertyType "type" -Force
}
else {
Write-Output -InputObject "Key already exists: [$dellCommand]."
}
Here, you can test to see if the key already exists and create it if it doesn't. Since New-Item produces an output of the object, you can use that to pipe into New-ItemProperty if needed to add properties to the key (demonstrated above).

Setting registry key value from powershell

When I try to set a registry key from a powershell script it overwrites another key :
For example :
$registryKey = "HKEY_LOCAL_MACHINE\SOFTWARE\Qualys\QualysAgent\ScanOnDemand\Vulnerability"
$valuedata = '1'
$valuename = "Scanondemand"
Set-ItemProperty -Path $registryKey -Name $ValueName -Value $ValueData
This sets registry key right. Then I change the valuename:
$valuename = 'ScanOnstartup'
Set-ItemProperty -Path $registryKey -Name $ValueName -Value $ValueData
On now the Scanonstartup is correct but the Scanondemand key is gone. It kind of renames the name instead of creating a new key.
You may be looking to replace your second add with:
New-ItemProperty
The problem is that you do not specify the PowerShell drive in the registry path.
You can either use the long form:
Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Qualys\QualysAgent\ScanOnDemand\Vulnerability
or make use of the fact that for HKEY_LOCAL_MACHINE PowerShell already has a drive set up by name HKLM:
HKLM:\SOFTWARE\Qualys\QualysAgent\ScanOnDemand\Vulnerability
Your code would then be
$registryKey = 'Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Qualys\QualysAgent\ScanOnDemand\Vulnerability'
# or: $registryKey = 'HKLM:\SOFTWARE\Qualys\QualysAgent\ScanOnDemand\Vulnerability'
$valuedata = '1'
$valuename = 'ScanOnDemand', 'ScanOnStartup'
# if the key does not already exist, create it first
if (!(Test-Path -Path $registryKey)) {
$null = New-Item -Path $registryKey
}
Set-ItemProperty -Path $registryKey -Name $ValueName[0] -Value $ValueData
Set-ItemProperty -Path $registryKey -Name $ValueName[1] -Value $ValueData
By using switch -Force to the New-Item cmdlet, you do not have to check if that key already exists because it will return either the existing key as object or the newly created one. Because we have no further use for that object as such, we ignore it with $null = New-Item ..
After running this (as Administrator), you have created this keys structure in the registry:
And in subkey Vulnerability you now have these two entries:

Delete registry string that contains specific value

I am trying to delete registry string that contains value “Palo Alto Networks”
Path: HKEY_USERS\S-1-5-21-484763869-1659004503-1644491937-15773\Software\Microsoft\Windows\CurrentVersion\UFH\SHC
String: 61
Value: C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Palo Alto Networks\GlobalProtect\GlobalProtect.lnk
C:\Program Files\Palo Alto Networks\GlobalProtect\PanGPA.exe
/noshrink
I want the script to delete string “61” if it detects value “Palo Alto Networks” in it.
This is the code that I think close to what I aim.
Get-ItemProperty -Path $SearchBase |
Where-Object {
$_.$RegKeyValueName -match $RegKeyValueDataPattern
} |
Remove-ItemProperty -Name $RegKeyValueName
However, $RegKeyValueName is random. It could be other than 61.
My aim is if $RegKeyValueDataPattern match, it will delete the $RegKeyValueName
OK I'm not completely sure what exactly you like to delete. It might help you for the next time when you take a look at the following Info: Structure of the Registry.
If you like to get the registry key values and you know the name you can use following syntax:
$SearchBase = 'REGISTRY::HKEY_USERS\S-1-5-21-484763869-1659004503-1644491937-15773\Software\Microsoft\Windows\CurrentVersion\UFH\SHC'
$RegKeyValueName = '61'
$RegKeyValueDataPattern = 'Palo Alto Networks'
Get-ItemProperty -Path $SearchBase
If you're looking for a specific value you can either specify the name ...
Get-ItemProperty -Path $SearchBase -Name $RegKeyValueName
... or filter the output with a Where-Object ...
Get-ItemProperty -Path $SearchBase |
Where-Object {
$_.$RegKeyValueName -match $RegKeyValueDataPattern
}
If you like to delete only the data of the value you can use Set-ItemProperty and provide an empty string ...
Get-ItemProperty -Path $SearchBase |
Where-Object {
$_.$RegKeyValueName -match $RegKeyValueDataPattern
} |
Set-ItemProperty -Name $RegKeyValueName -Value ''
.... or if you like to delete the complete value you can use Remove-ItemProperty ...
Get-ItemProperty -Path $SearchBase |
Where-Object {
$_.$RegKeyValueName -match $RegKeyValueDataPattern
} |
Remove-ItemProperty -Name $RegKeyValueName
.... and if you don't know the name of the value you like to delete you can use the following code scnippet:
Get-Item -Path $SearchBase |
Select-Object -ExpandProperty Property |
Where-Object {
(Get-ItemProperty -Path $SearchBase -Name $_ ) -match $RegKeyValueDataPattern
} |
ForEach-Object {
Remove-ItemProperty -Path $SearchBase -Name $_
}

Find Available Drive Letter and Change

I am trying to create a PowerShell script that will find an available drive letter, map a network drive, and then change to that mapped drive. I found the following which mapped \\server\share as the D: drive:
$Drive = New-PSDrive -Name $(for($j=67;gdr($d=[char]$J++)2>0){}$d) -PSProvider FileSystem -Root \\server\share\
I can manually enter D:, but how can I change this in a script? I was thinking along the lines of this:
$Drive = $Drive.Trim(":")
But the statement above throws the following error:
Method invocation failed because [System.Management.Automation.PSDriveInfo] does
not contain a method named 'Trim'.
At line:1 char:1
+ $Drive = $Drive.Trim(":")
+ ~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : MethodNotFound
You could check a list of potential drive letters against the list of currently assigned drive letters and use the first unused one:
$used = Get-PSDrive | Select-Object -Expand Name |
Where-Object { $_.Length -eq 1 }
$drive = 90..65 | ForEach-Object { [string][char]$_ } |
Where-Object { $used -notcontains $_ } |
Select-Object -First 1
New-PSDrive -Name $drive -PSProvider FileSystem -Root \\server\share
Set-Location "${drive}:"
or a random one from that list:
$used = Get-PSDrive | Select-Object -Expand Name |
Where-Object { $_.Length -eq 1 }
$unused = 90..65 | ForEach-Object { [string][char]$_ } |
Where-Object { $used -notcontains $_ }
$drive = $unused[(Get-Random -Minimum 0 -Maximum $unused.Count)]
New-PSDrive -Name $drive -PSProvider FileSystem -Root \\server\share
Set-Location "${drive}:"
The functions used in Ansgar's answer are likely returning the DVD/CD drive because it has no media in it. To get a free drive letter, that is likely* not the CD/DVD drive we search from i-z:
$dl=ls function:[i-z]: -n | ?{ !(test-path $_) } |select -last 1

Find and delete/change registry entry with powershell

I can get registry elements like this:
PS> $Registry_Key = "HKLM:\SOFTWARE\Wow6432Node\Lenovo\Access Connections\Locations\*\*\*"
PS> Get-ItemProperty -path $Registry_Key -name m_bSetBrowserPxySettings -ErrorAction SilentlyContinue
PSPath : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Lenovo\Access Connections\Locations\BMZ-GmbH\AdptList\Adpt00
PSParentPath : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Lenovo\Access Connections\Locations\BMZ-GmbH\AdptList
PSChildName : Adpt00
PSDrive : HKLM
PSProvider : Microsoft.PowerShell.Core\Registry
m_bSetBrowserPxySettings : 1
PSPath : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Lenovo\Access Connections\Locations\BMZ-GmbH\AdptList\Adpt01
PSParentPath : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Lenovo\Access Connections\Locations\BMZ-GmbH\AdptList
PSChildName : Adpt01
PSDrive : HKLM
PSProvider : Microsoft.PowerShell.Core\Registry
m_bSetBrowserPxySettings : 1
But now I want to delete m_bSetBrowserPxySettings completely, or change the value to "0" for every match in this search. Change or delete doesn't matter. What do I have to add to my script to achieve this?
You can do it as follows:
$Registry_Key = "HKLM:\SOFTWARE\Wow6432Node\Lenovo\Access Connections\Locations\*\*\*"
Get-ItemProperty -path $Registry_Key -name m_bSetBrowserPxySettings -ErrorAction SilentlyContinue | % { Set-ItemProperty -path $_.PSPath -name m_bSetBrowserPxySettings "0" }
You need pipe the Get-ItemProperty command to:
% { Set-ItemProperty -path $_.PSPath -name m_bSetBrowserPxySettings "0" }
% represents the ForEach-Object cmdlet. What it will do is iterate over each item in the collection you get out of the Get-ItemProperty command. $_ represents the object in the pipeline, so this will change to the new item on each iteration.
$_.PSPath is the path to the registry key of the item. You can see this printed in the table in your question. You can use this value to pass to Set-ItemProperty along with your name and then set the value to whatever you want.
If you wanted to remove the item altogether, pipe to the following instead:
% { Remove-ItemProperty -path $_.PSPath -name m_bSetBrowserPxySettings }
Rather than working with the path all the time you can just work on the item itself:
$Registry_Key = "HKLM:\SOFTWARE\Wow6432Node\Lenovo\Access Connections\Locations\*\*\*"
$item = Get-Item $Registry_Key
$item | Get-ItemProperty -name m_bSetBrowserPxySettings -ErrorAction SilentlyContinue
Then to set it to 0:
$item | Set-ItemProperty -name m_bSetBrowserPxySettings "0"
Or to delete it:
$item | Remove-ItemProperty -name m_bSetBrowserPxySettings