I am currently creating a powershell script in which the technicians can run to help apply various registry edits to create certain PCs which have automatic logins. However, whenever I run my script the powershell has no issue when changing values with pre-existing keys, yet it will not create keys when using the "new-item" command. I was wondering whether anyone would have any idea as to why this would not create the registry key given that I receive no errors when run.
Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" –Name AutoAdminLogon -Value 1
Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" -Name DefaultUserName -Value domain\TEST
Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" -Name DefaultPassword -Value TEST123
Test-Path –Path "HKLM:\SOFTWARE\Microsoft\WindowsNT\CurrentVersion\Winlogon\ForceAutoLogon"
if ( -Not (Test-Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon"))
{
New-Item -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" -Name ForceAutoLogon -Value 1
}
Test-Path is not designed for registy values. What you can do it use a Try/Catch block. You also need to Get/Set the itemPropery.
$Path = "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon"
Try {
Get-ItemProperty -Path $Path | Select-Object -ExpandProperty ForceAutoLogon -ErrorAction Stop | Out-Null
Set-ItemProperty -Path $Path -Name ForceAutoLogon -Value 1
} Catch {
New-ItemProperty -Path $Path -Name ForceAutoLogon -Value 1
}
If the Get-ItemProperty fails the the key must not exist. Then we can create it! If Get-ItemProperty succeeds then we can ensure the value is set properly. I might be using the registry keywords wrong but let the code speak for itself.
Related
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:
I am trying to make a reg key change based on the OS version.
The Key change pat works fine however the if function to work out if the device needs it or not I can not get to work. Any advice would be helpful. The powershell is below.
$verCheckOS = (Get-WmiObject win32_operatingsystem).version
if ($verCheckOS -lt 10.0.19043 -and $verCheckOS -gt 10.0.17134)
{
if (Test-Path HKLM:\SOFTWARE\Policies\Microsoft\AzureADAccount)
{
CD HKLM:\SOFTWARE\Policies\Microsoft
New-Item -Name AzureADAccount
New-ItemProperty -Path "AzureADAccount" -Name "AllowPasswordReset" -Value 1 -PropertyType DWord
}
}
Else
{
}
To make PowerShell compare version numbers properly you need to cast them to the proper type.
$verCheckOS = [version](Get-CimInstance -ClassName CIM_OperatingSystem).Version
if ($verCheckOS -lt [version]'10.0.19043' -and $verCheckOS -gt [version]'10.0.17134') {
if (-not (Test-Path HKLM:\SOFTWARE\Policies\Microsoft\AzureADAccount)) {
Push-Location 'HKLM:\SOFTWARE\Policies\Microsoft'
New-Item -Name 'AzureADAccount'
New-ItemProperty -Path 'AzureADAccount' -Name 'AllowPasswordReset' -Value 1 -PropertyType DWord
}
}
$verCheckOS = (Get-WmiObject win32_operatingsystem).version
if ($verCheckOS -lt "10.0.19043" -and $verCheckOS -gt "10.0.17134")
{
if (!(Test-Path "HKLM:\SOFTWARE\Policies\Microsoft\AzureADAccount"))
{
$null = New-Item -Name "AzureADAccount" -Path "HKLM:\SOFTWARE\Policies\Microsoft\"
$null = New-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\AzureADAccount" -Name "AllowPasswordReset" -Value 1 -PropertyType DWord
}
}
I am a bit confused by your code. You check if the full path to the AzureADAccount key exists and then if it does you proceed to try and create it? I think you meant if it does NOT exist then create it? I mean your code won't execute if it isn't there so the line to create it is just going to error out. So I changed it to run the block only if the path doesn't exist. If that's wrong then put the Test-Path line back the way you had it and remove the 'New-Item -Name "AzureADAccount"' line as its meaningless and keep the New-ItemProperty line.
Also just adding quotes around the numbers made the version check if statement work fine for me in my testing.
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...'
}
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
}
}
Creating a registry value, including the path up to it, and not erroring if the path already exists is easy using old-school reg.exe:
reg add HKCU\Software\Policies\Microsoft\Windows\EdgeUI /f /v DisableHelpSticker /t reg_sz /d 1
That's nice and concise. The shortest way I found to do it in pure PowerShell is two lines, or three if you don't want to repeat the path:
$regPath = 'HKCU:\Software\Policies\Microsoft\Windows\EdgeUI'
New-Item $regPath -Force | Out-Null
New-ItemProperty $regPath -Name DisableHelpSticker -Value 1 -Force | Out-Null
Is there an easier way using pure PowerShell? And without adding a utility function.
You can pipe the creation line to the New-ItemProperty line as follows, but be aware that the -Force flag on New-Item will delete any pre-existing contents of the key:
New-Item 'HKCU:\Software\Policies\Microsoft\Windows\EdgeUI' -Force | New-ItemProperty -Name DisableHelpSticker -Value 1 -Force | Out-Null
Another way of simplifying PS registry handling is calling the .Net function SetValue() directly:
[microsoft.win32.registry]::SetValue("HKEY_CURRENT_USER\Software\Test", "Test-String", "Testing")
[microsoft.win32.registry]::SetValue("HKEY_CURRENT_USER\Software\Test", "Test-DW", 0xff)
Why not just use the following:
New-ItemProperty -Path Registry::HKLM\SOFTWARE\Policies\Microsoft\Windows\EdgeUI -Name DisableHelpSticker -Value Contoso -Force | Out-Null
I am using this for some SCCM stuff and it doesn't overwrite my existing reg entries.
I didn't have any luck with #mschomm's answer for setting a DWORD value. Finally got this code to work for me:
$RegName = '2233969290'
$RegPath = 'HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Policies\Microsoft\FeatureManagement\Overrides\'
$RegData = 0
Write-Output "Setting Registry Key"
[microsoft.win32.registry]::SetValue($RegPath, $RegName, $RegData, [Microsoft.Win32.RegistryValueKind]::DWORD)
Here is another one-liner:
'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\NamingTemplates' | % { if (Test-Path $_) { Get-Item $_ } else { New-Item $_ } } | Set-ItemProperty -Name 'RenameNameTemplate' -Value (Get-Date -Format 'yyyy-MM-dd')
This sample sets the default name of a new explorer folder to the current date. I run this one in a scheduled task at 00:00h every day.