getting registry entry and then adding to it - powershell

I am trying to get a registry key value , ExtensionSettings, if there is something in the registry then save it. Then add a new entry to it . The two entries have to have a comma in-between values. I can not figure the code out . I am not sure what I am doing wrong or missing. Thank you so much for your help.
# Set variables to indicate value and key to set
$RegistryPath = 'HKLM:SOFTWARE\Policies\Google\Chrome'
$Name = 'ExtensionSettings'
$Value = '{"feolagkacappiaieohahjkeaikhjjcfa":{"toolbar_pin":"force_pinned"}}'
# Create the key if it does not exist
If (-NOT (Test-Path $RegistryPath)) {
New-Item -Path $RegistryPath -Force | Out-Null
}
#$OldValue = Get-ItemProperty -Path $RegistryPath -Name $Name
#$oldValue = $OldValue.ExtensionSettings
$OldValue = (Get-ItemProperty "HKLM:SOFTWARE\Policies\Google\Chrome").ExtensionSettings
#$NewValue = New-ItemProperty -Path $RegistryPath -Name $Name -Value $value
$UpdatedValue = $OldValue + "," + $NewValue
$NewValue = $NewValue.ExtensionSettings
New-ItemProperty -Path $RegistryPath -Name $Name -Value $UpdatedValue -PropertyType String -Force
Here is the error I get. I have updated the code with what I have tried . Nothing is written to the registry key. It goes show the comma but not the rest.
error I receive is
New-ItemProperty : The property already exists.
At line:15 char:13
+ $NewValue = New-ItemProperty -Path $RegistryPath -Name $Name -Value $ ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ResourceExists: (HKEY_LOCAL_MACH...s\Google\Chrome:String) [New-ItemProperty], IOException
+ FullyQualifiedErrorId : System.IO.IOException,Microsoft.PowerShell.Commands.NewItemPropertyCommand

The "Extension Settings" registry key is a JSON-formatted string, so you won't be able to simply concatenate on to the end of it. Here's a sample string that Google provides as an example . . . notice that the entire string is encapsulated in curly braces. In order to add an entry, you'd have to add it inside the outer set of curly braces.
{
"*": {
"installation_mode": "blocked"
},
"nckgahadagoaajjgafhacjanaoiihapd": {
"installation_mode": "force_installed",
"update_url":
"https://clients2.google.com/service/update2/crx"
},
"lpcaedmchfhocbbapmcbpinfpgnhiddi": {
"installation_mode": "normal_installed",
"update_url":
"https://clients2.google.com/service/update2/crx"
},
"gmbgaklkmjakoegficnlkhebmhkjfich": {
"installation_mode": "allowed"
}
}
Something like the following should work (note that the original $Value has been modified to remove the outer curly braces):
# Set variables to indicate value and key to set
$RegistryPath = 'HKLM:SOFTWARE\Policies\Google\Chrome'
$Key = 'ExtensionSettings'
$ValueAdd = '"feolagkacappiaieohahjkeaikhjjcfa":{"toolbar_pin":"force_pinned"}'
# Check for existing 'ExtensionSettings' key and modify/create
If ((Get-Item -Path $RegistryPath).GetValue($Key) -ne $null) {
# Copy existing value (without outer braces)
$string = (Get-ItemProperty "$RegistryPath").$Name
$ValueOld = $string.subString(1, ($string.Length)-2)
# Modify to add new value (and add outer braces)
$ValueNew = "{$ValueOld, $ValueAdd}"
New-ItemProperty -Path $RegistryPath -Name $Key -Value $ValueNew -PropertyType String -Force
} else {
# If it doesn't already exist, create it
$ValueNew = "{$ValueAdd}"
New-ItemProperty -Path $RegistryPath -Name $Key -Value $ValueNew -PropertyType String -Force
}

Related

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:

-PropertyType set as DWord but when Item is created it comes out as a string

My code:
try {
if(!(Test-Path -Path $registryPath -Value $Name)) {
New-ItemProperty -Name test -Path HKLM:\Software\WOW6432Node\Mozilla -PropertyType DWord -Value 2
}
}
catch {
Set-ItemProperty -Path $registryPath -Name $Name -Value $value
}
My Problem: the result comes out as string.
I have tried changing -PropertyType to -Type.
I have tried changing the capitilation of the word DWord.
Any help would be greatly appreciated.
As the docs say:
You also use Set-ItemProperty to create and change registry values and data. For example, you can add a new registry entry to a key and establish or change its value.
With Set-ItemProperty it is also possible to change the type of registry entry from say a REG_SZ (string) value to DWord, so basically all you need is:
$registryPath = 'HKLM:\Software\WOW6432Node\Mozilla'
$propName = 'test'
Set-ItemProperty -Path $registryPath -Name $propName -Value 2 -Type DWord
Of course, if you do not have permissions to create or alter something in the HKEY_LOCAL_MACHINE registry path, you will rceive an error.

Function to enable basic authentication via powershell

I have created a powershell script that enables basic authentication, I needed this to allow the winrm to work when running some of our older powershell scripts.
What I need to do now is be able to call this script as a function with either a true false argument. e.g. disable or enable basic authentication.
How can I wrap this code into a function so that I can call it from other powershell scripts?
SO if I send a command to this script e.g.
basicauth($true) - it will run the script as is
basicauth($false - would disable basic authentication
I can create the alternate if else statement for when the true of false is sent to this, but not sure how I can wrap the whole script into a function.
Apologies for the novice status with powershell, it took me awhile to get this script working the way it is.
param([switch]$Elevated)
# Get variables
$registryPath = "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WinRM\Client"
$key1 = "AllowDigest"
$key2 = "AllowUnencryptedTraffic"
$key3 = "AllowBasic"
$off = "00000000"
$on = "00000001"
# enables admin privileges
function Test-Admin {
$currentUser = New-Object Security.Principal.WindowsPrincipal $([Security.Principal.WindowsIdentity]::GetCurrent())
$currentUser.IsInRole([Security.Principal.WindowsBuiltinRole]::Administrator)
}
if ((Test-Admin) -eq $false) {
if ($elevated)
{
'tried to elevate, did not work, aborting...'
}
else {
Start-Process powershell.exe -Verb RunAs -ArgumentList ('-noprofile -file "{0}" -elevated' -f ($myinvocation.MyCommand.Definition))
}
exit
}
# checks if the registry path is available, before adding the registry key values
If (!(Test-Path $registryPath))
{
New-Item -Path $registryPath -Force | out-Null
New-ItemProperty -Path $registryPath -Name $key1 -Value $off -PropertyType DWORD -Force | Out-Null
New-ItemProperty -Path $registryPath -Name $key2 -Value $off -PropertyType DWORD -Force | Out-Null
New-ItemProperty -Path $registryPath -Name $key3 -Value $on -PropertyType DWORD -Force | Out-Null
#'registry key did not exist'
exit
}
Else
{
New-ItemProperty -Path $registryPath -Name $key1 -Value $off -PropertyType DWORD -Force | Out-Null
New-ItemProperty -Path $registryPath -Name $key2 -Value $off -PropertyType DWORD -Force | Out-Null
New-ItemProperty -Path $registryPath -Name $key3 -Value $on -PropertyType DWORD -Force | Out-Null
#'registry key exists'
exit
}
NOTE: Now I know that the Else statement should have the values as: Set-ItemProperty although if I change the code to have Set-ItemProperty the script no longer works, only way I have this working is to have it as: New-ItemProperty. Doesn't really make sense but it works.
Ideally it would be better to just update the current powershell scripts to use modern authentication, but there is 100's of them so not really a viable option for me.
Any assistance would be greatly appreciated.
If you wrap the entire function in an if statement like:
param([switch]$Elevated)
if($elevated) {
...script code here
}
Then you can call the function with that parameter like . "scriptname.ps1" -Elevated to execute what is inside the scriptblock. Instead just calling . "scriptname.ps1" without the -Elevated parameter will not do anything because you'll hit your if statement:
if ($elevated) {
and elevated doesn't exist which means nothing inside the scriptblock executes.
I don't see the purpose of doing this in your case because if you already have logic to decide whether or not to pass in true or false, why not just use that logic to decide whether or not to call the script at all? My guess is that you don't actually mean that you only want to execute the entire script if a user is 'elevated' but rather check if they can be elevated in the script and then do something else.
In that case you should take a look at Advanced PowerShell Functions. You could do something like this:
# Get variables
$registryPath = "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WinRM\Client"
$key1 = "AllowDigest"
$key2 = "AllowUnencryptedTraffic"
$key3 = "AllowBasic"
$off = "00000000"
$on = "00000001"
# enables admin privileges
function Test-Admin {
$currentUser = New-Object Security.Principal.WindowsPrincipal $([Security.Principal.WindowsIdentity]::GetCurrent())
$isAdmin = $currentUser.IsInRole([Security.Principal.WindowsBuiltinRole]::Administrator)
return $isAdmin
}
function Do-TheRestOfTheThings {
[CmdletBinding()]
param()
Get-Process powershell.exe -Verb RunAs -ArgumentList ('-noprofile -file "{0}" -elevated' -f ($myinvocation.MyCommand.Definition))
If (!(Test-Path $registryPath)) {
New-Item -Path $registryPath -Force | out-Null
New-ItemProperty -Path $registryPath -Name $key1 -Value $off -PropertyType DWORD -Force | Out-Null
New-ItemProperty -Path $registryPath -Name $key2 -Value $off -PropertyType DWORD -Force | Out-Null
New-ItemProperty -Path $registryPath -Name $key3 -Value $on -PropertyType DWORD -Force | Out-Null
#'registry key did not exist'
exit
}
Else {
New-ItemProperty -Path $registryPath -Name $key1 -Value $off -PropertyType DWORD -Force | Out-Null
New-ItemProperty -Path $registryPath -Name $key2 -Value $off -PropertyType DWORD -Force | Out-Null
New-ItemProperty -Path $registryPath -Name $key3 -Value $on -PropertyType DWORD -Force | Out-Null
#'registry key exists'
}
}
if(Test-Admin) {
Do-TheRestOfTheThings
}
else {
'tried to elevate, did not work, aborting...'
}

Registry value each time it runs

I started creating this script and I got stuck at one thing that I want to accomplish. This script runs fine. But what I really want to do is when this script is run more than once, I want to change the value to the number of times this script was use. How do I accomplish this?
$RegistryPath = "HKLM:\SOFTWARE\"
$NewRegKey = "SCCM"
$NewRegKeyPath = "HKLM:\SOFTWARE\SCCM"
$KeyName = "Attempts"
$Value = "1"
New-Item -Path $RegistryPath -Name $NewRegKey -Force
New-ItemProperty -Path $NewRegKeyPath -Name $KeyName -Value $Value -PropertyType DWORD -Force -ErrorAction SilentlyContinue | Out-Null
NEW script:
(Working)
#This is creating the SCCM Hive and add the key W10_IPU_Attempts
If (Get-ItemProperty -Path 'HKLM:\SOFTWARE\SCCM' -ErrorAction SilentlyContinue) {
} Else {
$RegistryPath = "HKLM:\SOFTWARE\"
$NewRegKey = "SCCM"
New-Item -Path $RegistryPath -Name $NewRegKey -Force
$NewRegKeyPath = "HKLM:\SOFTWARE\SCCM"
$KeyName = "W10_IPU_Attempts"
$Value = "0"
New-ItemProperty -Path $NewRegKeyPath -Name $KeyName -Value $Value -PropertyType DWORD -Force | Out-Null
}
#Set value in increment of 1 each time this script is ran!
$i=
$Value =(Get-Itemproperty 'HKLM:\SOFTWARE\SCCM').W10_IPU_Attempts
If ($i -eq $value){
$i++
Set-ItemProperty -Path 'HKLM:\SOFTWARE\SCCM' -Name W10_IPU_Attempts -Value $i
}
else {
$i++
Set-ItemProperty -Path 'HKLM:\SOFTWARE\SCCM' -Name W10_IPU_Attempts -Value $i
}
I suggest to use splatting with your bunch of parameters.
Otherwise do as suggested, (check) read current value set incremented value,
if not present, create the key
## Q:\Test\2019\05\17\SO_56190969.ps1
$RegistryPath = "HKLM:\SOFTWARE\"
$NewRegKey = "SCCM"
$NewRegKeyPath = "HKLM:\SOFTWARE\SCCM"
$KeyName = "Attempts"
if ($Value=[Int](Get-ItemPropertyValue $NewRegKeyPath -Name $KeyName -EA 0)){
Set-ItemProperty -Path $NewRegKeyPath -Name $KeyName -Value (++$Value) -Type DWord
} else {
New-Item -Path $RegistryPath -Name $NewRegKey -Force | Out-Null
$params = #{
Path = $NewRegKeyPath
Name = $KeyName
Value = 1
PropertyType= 'DWORD'
Force = $True
ErrorAction = 'SilentlyContinue'
}
New-ItemProperty #params | Out-Null
}
"Key : {0}`nKeyname: {1}`nValue : {2}" -f $NewRegKeyPath,$KeyName,
(Get-ItemPropertyValue $NewRegKeyPath -Name $KeyName)
#
Two sample runs:
> Q:\Test\2019\05\17\SO_56190969.ps1
Key : HKLM:\SOFTWARE\SCCM
Keyname: Attempts
Value : 1
> Q:\Test\2019\05\17\SO_56190969.ps1
Key : HKLM:\SOFTWARE\SCCM
Keyname: Attempts
Value : 2

Powershell: Can't update a registry path because it doesn't exist (but it actually exists)

We are running Coded UI tests on IE in Windows 8.1, and we're doing it through Visual Studio Team Services. As part of our build, we run a Powershell script that disables the popup manager. The code we use to disable it is this:
Remove-ItemProperty "HKCU:\Software\Microsoft\Internet Explorer\New Windows" -Name "PopupMgr"
New-ItemProperty "HKCU:\Software\Microsoft\Internet Explorer\New Windows" -Name "PopupMgr" -Value 00000000 -PropertyType "DWord"
When I create and deploy a build in Release Manager, running this generates the following error:
The running command stopped because the preference variable "ErrorActionPreference" or common parameter is set to Stop: Cannot find path 'HKCU:\Software\Microsoft\Internet Explorer\New Windows' because it does not exist.
(Emphasis mine)
I've logged onto the VM and looked at the registry, and HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\New Windows absolutely exists. The only thing I can think of is that its value isn't a DWORD but rather a string -- the PopupMgr key has a Data value of "yes" rather than 1 or 0. But that doesn't match the error message -- the error says it can't even find the path of the key, not that the value type is a mismatch. Plus, the code removes the existing key before inserting a new one, so I don't even know how it would notice the mismatch.
Even weirder, if I open Powershell inside the VM and run those exact two lines (I copied and pasted to avoid typos), they ran just fine.
This script worked on Windows 10 perfectly and has for a while, so I'm unsure what's going on here. The user is a member of the Administrators group, so I don't think it's a permissions issue.
Can anyone shed some light on this?
I think you are trying to add the Registry key Property Value
You need to test for the existence of the registry key. If the registry key does not exist, then you need to create the registry key, and then create the registry key property value.
You should create the path to the registry key, then specify the property name and the value you want to assign. This consists of three variables as shown here:
This should help you out:
$registryPath = "HKCU:\Software\Microsoft\Internet Explorer\New Windows"
$Name = "PopupMgr"
$value = "00000000"
IF(!(Test-Path $registryPath))
{
New-Item -Path $registryPath -Force | Out-Null
New-ItemProperty -Path $registryPath -Name $name -Value $value `
-PropertyType DWORD -Force | Out-Null}
ELSE {
New-ItemProperty -Path $registryPath -Name $name -Value $value `
-PropertyType DWORD -Force | Out-Null}
Hope it helps.
I had the same problem when renaming values, so I understood that for values you can (need / should) just define them, so I stopped trying to rename these values and started to define them :)
Just try to use Set-ItemProperty to change, set and reset values ...
Set-ItemProperty -Path "HKCU:\Software\Microsoft\Internet Explorer\New Windows" -Name PopupMgr -Value 00000000 -Type DWORD
Some further reading:
[√] MS-Doc's | set-itemproperty
[√] SS64.com | set-itemproperty
I wrapped Duttas answer in an easy to use function:
Set_Registry_key -key "HKLM:\FULL\PATH\pad\pat\KEYNAME" `
-type String `
-value 'value'
Function definition:
function Set_Registry_key{
# String REG_SZ; ExpandString: REG_EXPAND_SZ; Binary: REG_BINARY; DWord: REG_DWORD; MultiString: REG_MULTI_SZ; Qword: REG_QWORD; Unknown: REG_RESOURCE_LIST
Param(
[Parameter(Mandatory=$true)]
[string]
$key,
[ValidateSet('String', 'DWord', 'ExpandString', 'Binary', 'MultiString', 'Qword', 'Unknown')]
$type,
[Parameter(Mandatory=$true)]
$value
)
$registryPath = $key -replace "[^\\]*$", ""
$name = $key -replace ".*\\", ""
if(!(Test-Path $registryPath)){
New-Item -Path $registryPath -Force | Out-Null
New-ItemProperty -Path $registryPath -Name $name -Value $value -PropertyType $type -Force | Out-Null
}else {
New-ItemProperty -Path $registryPath -Name $name -Value $value -PropertyType $type -Force | Out-Null
}
}