Creating Registry Keys with Powershell - powershell

I am trying to check if a key-structure exists in the registry using powershell. If the structure does not exist, I need to create it and then I need to create the keys in the ending folder. If I run the snippets individually to create the keys, they create just fine. But running the block itself (ensuring manually within the registry that the keys don't exist) it won't create the folder structure. Not sure what the issue is. Any help would be appreciate. The code is as follows:
$Registry_Paths = "hkcu:\Software\Microsoft\Office\14.0", "hkcu:\Software\Microsoft\Office\14.0\Groove", "hkcu:\Software\Microsoft\Office\14.0\Groove\Development"
foreach($Registry_Path in $Registry_Paths)
{
$Test_Path_Result = Test-Path -Path $Registry_Path
if($Test_Path_Result -eq $false)
{
$Registry_Key_Log += "Warning: No registry key path found at " + $Registry_Path +"`n"
$Registry_Key_Log += "Creating key now for " + $Registry_Path + "`n" + "`n"
if($Registry_Path -eq "hkcu:\Software\Microsoft\Office\14.0")
{
try{
New-Item -Path "HKCU:\Software\Microsoft\Office\14.0" -ItemType Key
}
catch
{
$Error_Log += "Warning: There was an error when attempting to create a new registry key, or key property for $Registry_Path"
$Error_Log += $_.exception.message
}
}
if($Registry_Path -eq "hcku:\Software\Microsoft\Office\14.0\Groove")
{
try{
New-Item -Path "HKCU:\Software\Microsoft\Office\14.0\Groove" -ItemType Key
}
catch
{
$Error_Log += "Warning: There was an error when attempting to create a new registry key, or key property for $Registry_Path"
$Error_Log += $_.exception.message
}
}
if($Registry_Path -eq "hcku:\Software\Microsoft\Office\14.0\Groove\Development")
{
try{
New-Item -Path "HKCU:\Software\Microsoft\Office\14.0\Groove\Development" -ItemType Key
New-ItemProperty -Path "hkcu:\Software\Microsoft\Office\14.0\Groove\Development" -Value 00000001 -PropertyType dword -Name "EnableReleaseBuildDebugOutput"
New-ItemProperty -Path "hkcu:\Software\Microsoft\Office\14.0\Groove\Development" -Value 1 -Name "TraceIdentityMessaging"
New-ItemProperty -Path "hkcu:\Software\Microsoft\Office\14.0\Groove\Development" -Value 00000001 -PropertyType dword -Name "TraceTelespaceFetch"
New-ItemProperty -Path "hkcu:\Software\Microsoft\Office\14.0\Groove\Development" -Value 1 -Name "TraceConnectSequence"
}
catch
{
$Error_Log += "Warning: There was an error when attempting to create a new registry key, or key property for $Registry_Path"
$Error_Log += $_.exception.message
}
}
}
}

Here is how I'd do it.
$Key = "HKEY_CURRENT_USER\TEST"
If ( -Not ( Test-Path "Registry::$Key")){New-Item -Path "Registry::$Key" -ItemType RegistryKey -Force}
Set-ItemProperty -path "Registry::$Key" -Name "Less" -Type "String" -Value "Less"

function New-RegKey
{
# Create subkey in specified registry hive/key.
param (
[string]$Key
)
# Check if key exists or not:
if ($reg.GetSubKeyNames() -notcontains $Key)
{
Try
{
# The key DOES NOT exist, so create it:
$Script:reg = $reg.CreateSubKey($Key)
Write-Host "Registry key ""$($Script:reg.Name)"" has been successfully created." -foregroundColor Green
}
Catch
{
Write-Host "ERROR:$((($ERROR[0].Exception).InnerException).Message)." -ForegroundColor Yellow
}
}
else
{
Write-Host "Registry key ""$Key"" already exists. Do not need to create." -ForegroundColor White
# Open the subkey in writable mode and update the $reg in script scope:
Try
{
$Script:reg = $reg.OpenSubKey($Key, $Writable)
}
Catch
{
Write-Host "ERROR:$((($ERROR[0].Exception).InnerException).Message)."
-ForegroundColor Yellow
}
}
}
function Set-RegValue
{
param (
[string]$RegName,
[string]$RegValue,
[string]$RegValueType
)
# Create or update the specified registry value (valueName and valueValue):
# First check to see if the value name exists or not in the current key:
if ($reg.GetValueNames() -notcontains $RegName) {
# Registry value does not exist, so create one and assign value:
Try
{
$reg.SetValue($RegName, $RegValue, $RegValueType)
Write-Host "Registry value name ""$RegName"" does not exist, so create it and assign value ""$RegValue"" with type: ""$RegValueType""."
}
Catch
{
Write-Host "ERROR: $((($ERROR[0].Exception).InnerException).Message)." -ForegroundColor Yellow
}
}
else
{
Try
{
Write-Host "Registry value name ""$RegName"" already exists, so update its value ""$RegValue"" with type: ""$RegValueType""."
$reg.SetValue($RegName, $RegValue, $RegValueType)
}
Catch
{
Write-Host "ERROR:$((($ERROR[0].Exception).InnerException).Message)." -ForegroundColor Yellow
}
}
}

I got it working. Turns out I had a typo (hkcu != hcku):
if($Registry_Path -eq "hkcu:\Software\Microsoft\Office\14.0")
if($Registry_Path -eq "hcku:\Software\Microsoft\Office\14.0\Groove")
Note the "HKCU" and "HCKU" above.

Related

Powershell - manage error when registry key not exist

I hope you're well.
Desciption
I requiere your help regarding the following code I use and who can generate an error when registry key do not exist.
In this example:
If the key Ins_ProductVersion exist in both registry path, the code show information expected.
However, if this key do not exist, I got an error exception + the text: - Product Version: Not found!
My goal , is to only get my message and not the error exception
I was thinking that -ErrorAction SilentlyContinue will manage this situation, but not in my case it not seems
foreach ($path in 'HKLM:HKEY_LOCAL_MACHINE\SOFTWARE\xxx\xxxx\xxxx\environment\', 'HKLM:HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\xxx\xxxx\xxxx\environment\') {
$hotfix = Get-ItemPropertyValue -Path $path -Name 'Ins_ProductVersion' -ErrorAction SilentlyContinue
# assuming you want to exit the loop at the first successfull 'hit'
if ($hotfix) { break }
}
if ($hotfix) {
write-host "- Product Version: $hotfix"
}
else {
write-host "- Product Version: Not found!"
}
Thanks for your helps and futur advices.
Regards,
Florian
-------------- new code version ---------------
Not working for now
Original key is : Version
Change this key like : Version1
Output can be found here :
code used
foreach ($path in 'HKLM:\SOFTWARE\Dropbox\Client', 'HKLM:\SOFTWARE\WOW6432Node\Dropbox\Client') {
$hotfix = Get-ItemPropertyValue -Path $path -Name 'Version' -ErrorAction SilentlyContinue
# assuming you want to exit the loop at the first successfull 'hit'
if ($hotfix) { break }
}
if ($hotfix) {
write-host "- Product version: $hotfix"
}
else {
Write-Host "- Product version : Not found"
}
========== SOLUTION ==========
Thanks for your help
foreach ($path in 'HKLM:\SOFTWARE\Dropbox\Client', 'HKLM:\SOFTWARE\WOW6432Node\Dropbox\Client') {
try {
$hotfix = Get-ItemPropertyValue -Path $path -Name 'Version' -ErrorAction Stop
# assuming you want to exit the loop at the first successfull 'hit'
if ($hotfix) { break }
}
catch {
Write-Warning $_.Exception.Message
}
}
if ($hotfix) {
write-host "- Product version: $hotfix"
}
else {
Write-Host "- Product version : Not found"
}
The reason you receive both an exception and your own message is because you have defined the registry paths wrong:
HKLM:HKEY_LOCAL_MACHINE\SOFTWARE\xxx\xxxx\xxxx\environment should be either
HKLM:\SOFTWARE\xxx\xxxx\xxxx\environment OR
Registry::HKEY_LOCAL_MACHINE\SOFTWARE\xxx\xxxx\xxxx\environment
In your code, you have now added the registry hive twice, where you only need the short OR long version here.
This works:
foreach ($path in 'HKLM:\SOFTWARE\xxx\xxxx\xxxx\environment\', 'HKLM:\SOFTWARE\WOW6432Node\xxx\xxxx\xxxx\environment\') {
$hotfix = Get-ItemPropertyValue -Path $path -Name 'Ins_ProductVersion' -ErrorAction SilentlyContinue
# assuming you want to exit the loop at the first successfull 'hit'
if ($hotfix) { break }
}
if ($hotfix) {
write-host "- Product Version: $hotfix"
}
else {
write-host "- Product Version: Not found!"
}
and so does this:
foreach ($path in 'Registry::HKEY_LOCAL_MACHINE\SOFTWARE\xxx\xxxx\xxxx\environment\', 'Registry::HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\xxx\xxxx\xxxx\environment\') {
$hotfix = Get-ItemPropertyValue -Path $path -Name 'Ins_ProductVersion' -ErrorAction SilentlyContinue
# assuming you want to exit the loop at the first successfull 'hit'
if ($hotfix) { break }
}
if ($hotfix) {
write-host "- Product Version: $hotfix"
}
else {
write-host "- Product Version: Not found!"
}
without the need to wrap it inside a try{..} catch{..}
Although I do not have any exception messages, and for me the -ErrorAction SilentlyContinue does exactly what is expected, you say you keep also receiving system Exception messages using the above..
In that case, you will need to add a try{..}catch{..} to figure out what exactly errors out like this:
foreach ($path in 'HKLM:\SOFTWARE\Dropbox\Client', 'HKLM:\SOFTWARE\WOW6432Node\Dropbox\Client') {
try {
$hotfix = Get-ItemPropertyValue -Path $path -Name 'Version' -ErrorAction Stop
# assuming you want to exit the loop at the first successfull 'hit'
if ($hotfix) { break }
}
catch {
Write-Warning $_.Exception.Message
}
}
if ($hotfix) {
write-host "- Product version: $hotfix"
}
else {
Write-Host "- Product version : Not found"
}
Now, exceptions will be written to the screen too like
WARNING: Cannot find path 'HKLM:\SOFTWARE\Dropbox\Client' because it does not exist.
WARNING: Cannot find path 'HKLM:\SOFTWARE\WOW6432Node\Dropbox\Client' because it does not exist.
- Product version : Not found
or
WARNING: Property Version does not exist at path HKEY_LOCAL_MACHINE\SOFTWARE\Dropbox\Client.
WARNING: Cannot find path 'HKLM:\SOFTWARE\WOW6432Node\Dropbox\Client' because it does not exist.
- Product version : Not found
Usually best to use error handling properly rather than try to disable it:
$Paths = 'HKLM:HKEY_LOCAL_MACHINE\SOFTWARE\xxx\xxxx\xxxx\environment\', 'HKLM:HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\xxx\xxxx\xxxx\environment\'
$Paths | ForEach-Object {
Try {
$CurPath = $_
$hotfix = Get-ItemPropertyValue -Path $CurPath -Name 'Ins_ProductVersion' -ErrorAction Stop
}
Catch {
$RegError = "Error obtaining reg key: $_"
}
If ($hotfix) {
[pscustomobject]#{RegPath=$_;Hotfix=$hotfix}
}
Else {
[pscustomobject]#{RegPath=$_;Hotfix=$RegError}
}
}
Or:
$Paths | ForEach-Object {
Try {
$CurPath = $_
$hotfix = Get-ItemPropertyValue -Path $CurPath -Name 'Ins_ProductVersion' -ErrorAction Stop
[pscustomobject]#{RegPath=$_;Hotfix=$hotfix}
}
Catch {
$RegError = "Error obtaining reg key: $_"
[pscustomobject]#{RegPath=$_;Hotfix=$RegError}
}
}

Enviroment Paths without overwriting String

I would like to ask question about how I should proceed or how I should fix the code.
My problem is that I need my code to write into the Path three different paths for Logstash, Kibana and ElasticSearch, but I have no idea how to do it. It returns always the same error about missing ")" error
Here's the whole code ¨
[CmdletBinding(SupportsShouldProcess=$true)]
param(
[string]$NewLocation.GetType($ElasticSearch)
[string]$ElasticSearch = "C:\Elastic_Test_Server\elasticsearch\bin"
[string]$Kibana = "C:\Elastic_Test_Server\kibana\bin"
[string]$Logstash = "C:\Elastic_Test_Server\logstash\bin"
)
Begin
{
#Je potřeba spustit jako Administrátor
$regPath = "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"
$hklm = [Microsoft.Win32.Registry]::LocalMachine
Function GetOldPath()
{
$regKey = $hklm.OpenSubKey($regPath, $FALSE)
$envpath = $regKey.GetValue("Path", "", [Microsoft.Win32.RegistryValueOptions]::DoNotExpandEnvironmentNames)
return $envPath
}
}
Process
{
# Win32API errory
$ERROR_SUCCESS = 0
$ERROR_DUP_NAME = 34
$ERROR_INVALID_DATA = 13
$NewLocation = $NewLocation.Trim();
If ($NewLocation -eq "" -or $NewLocation -eq $null)
{
Exit $ERROR_INVALID_DATA
}
[string]$oldPath = GetOldPath
Write-Verbose "Old Path: $oldPath"
# Zkontroluje zda cesta již existuje
$parts = $oldPath.split(";")
If ($parts -contains $NewLocation)
{
Write-Warning "The new location is already in the path"
Exit $ERROR_DUP_NAME
}
# Nová cesta
$newPath = $oldPath + ";" + $NewLocation
$newPath = $newPath -replace ";;",""
if ($pscmdlet.ShouldProcess("%Path%", "Add $NewLocation")){
# Přidá to přítomné session
$env:path += ";$NewLocation"
# Uloží do registru
$regKey = $hklm.OpenSubKey($regPath, $True)
$regKey.SetValue("Path", $newPath, [Microsoft.Win32.RegistryValueKind]::ExpandString)
Write-Output "The operation completed successfully."
}
Exit $ERROR_SUCCESS
}
Thank you for your help.
I really think you could simplify this a lot, unless I have misunderstood. Apologies, I am not currently on a Windows machine so can't test this.
function Add-ESPath {
# Create an array of the paths we wish to add.
$ElasticSearch = #(
"C:\Elastic_Test_Server\elasticsearch\bin",
"C:\Elastic_Test_Server\kibana\bin",
"C:\Elastic_Test_Server\logstash\bin"
)
# Collect the current PATH string and split it out in to an array
$CurrentPath = [System.Environment]::GetEnvironmentVariable("PATH")
$PathArray = $CurrentPath -split ";"
# Loop though the paths we wish to add.
foreach ($Item in $ElasticSearch) {
if ($PathArray -notcontains $Item) {
$PathArray += $Item
}
else {
Write-Output -Message "$Item is already a member of the path." # Use Write-Warning if you wish. I see it more as a notification here.
}
}
# Set the path.
$PathString = $PathArray -join ";"
Try {
[System.Environment]::SetEnvironmentVariable("PATH", $PathString)
exit 0
}
Catch {
Write-Warning -Message "There was an issue setting PATH on this machine. The path was:" # Use $env:COMPUTERNAME here perhaps instead of 'this machine'.
Write-Warning -Message $PathString
Write-Warning -Message $_.Exception.Message
exit 1
}
}
Add-ESPath
Perhaps you want to add some kind of log file rather than writing messages/warnings to the console. You can use Add-Content for this.
I long time ago i wrote some functions to add a path to system path + their is an check if the path is already inside the system path. And i also did an elevation check so when i use this function and i forgot to elevate my powershell that i get a warning. Its a different approach, I hope it will help you.
I only use the begin {} proccess{} statements for when i want to write a function that excepts pipeline inputs. So its if you want to write a function that will work as the following:
$paths = #("C:\Elastic_Test_Server\elasticsearch\bin", "C:\Elastic_Test_Server\kibana\bin")
$paths | my-append-these-to-system-path-function
Elevation check:
function G-AmIelevated($warningMessage){
if([bool](([System.Security.Principal.WindowsIdentity]::GetCurrent()).groups -match "S-1-5-32-544")){
return $true
}else{
write-host "not elevated $warningMessage" -ForegroundColor Red
return $false
}
}
append something to system path with check if its already inside system path:
function G-appendSystemEnvironmentPath($str){
if(test-path $str){
if(!((Get-Itemproperty -path 'hklm:\system\currentcontrolset\control\session manager\environment' -Name Path) -like "*$str*")){
write-host "`t $str exists...`n adding $str to environmentPath" -ForegroundColor Yellow
if(G-AmIelevated){
write-host `t old: (Get-Itemproperty -path 'hklm:\system\currentcontrolset\control\session manager\environment' -Name Path).Path
Set-ItemProperty -path 'hklm:\system\currentcontrolset\control\session manager\environment' `
-Name Path `
-Value "$((Get-Itemproperty -path 'hklm:\system\currentcontrolset\control\session manager\environment' -Name Path).Path);$str"
write-host `t new: (Get-Itemproperty -path 'hklm:\system\currentcontrolset\control\session manager\environment' -Name Path).Path
write-host `t restart the computer for the changes to take effect -ForegroundColor Red
write-host `t `$Env:Path is the merge of System Path and User Path This function set the system path
write-host `t $str appended to environmet variables. -ForegroundColor Green
}else{
write-host `t rerun ise in elevated mode -ForegroundColor Red
}
}else{
write-host "`t $str is in system environmenth path"
}
}else{
write-host `t $str does not exist
}
}
G-appendSystemEnvironmentPath -str "C:\Elastic_Test_Server\elasticsearch\bin"
G-appendSystemEnvironmentPath -str "C:\Elastic_Test_Server\kibana\bin"
G-appendSystemEnvironmentPath -str "C:\Elastic_Test_Server\logstash\bin"

Array member name to write-host

$mbservers = #("server1", "server2")
Foreach ($mbserver in $mbservers) {
#Check for reg key
Invoke-Command -Computername $mbserver -Credential $credsschedtask -ScriptBlock {
$regkey = "HKLM:\SYSTEM\CurrentControlSet\Control\Lsa\DisableLoopbackCheck"
$checkregkey = (Test-Path $regkey)
If ($checkregkey = "True") {
Write-Host "'DisableLoopbackCheck' key exists on $mbserver".
}
ElseIf ($checkregkey = "False") {
Write-Host "'DisableLoopbackCheck' key does not exist on $mbserver."
}
Else {
Write-Host "Unable to confirm if 'DisableLoopbackCheck' key exists on $mbserver."
}
}
}
I'm trying to workout the Write-Host variable so it display's server1 etc
(Write-Host "'DisableLoopbackCheck' key exists on $mbserver".)
Have tried the following in various ways:
For($i=0; $i -le $mbservers.getupperBound(0);$i++){
write-host $mbservers[$i]
write-host "line 2 :," $mbservers[$i]
I would be grateful for any help.
Your If and ElseIf comparisons don't function at the moment:
= is used for setting values, -eq is used for comparing them
Test-Path doesn't return a string "True", it returns a bool $True
As a bool only has two states $True or $False, you only need If/Else:
Foreach ($mbserver in $mbservers) {
#Check for reg key
Invoke-Command -Computername $mbserver -Credential $credsschedtask -ScriptBlock {
$checkregkey = Test-Path "HKLM:\SYSTEM\CurrentControlSet\Control\Lsa\DisableLoopbackCheck"
If ($checkregkey -eq $True) {
Write-Host "'DisableLoopbackCheck' key exists on $mbserver".
}
Else {
Write-Host "'DisableLoopbackCheck' key does not exist on $mbserver."
}
}
}

How to add a site to 'Local intranet' zone in internet options using a PowerShell script?

I would like to add \XX01234ABC01 to Local intranet zone using a PowerShell script and possibly take the site from the variable below.
$computername=$env:computername -replace ".....$","ABC01"
Any help would be much appreciated.
I hope this help you
$prefixIntranet = "www"
$LocalIntranetSite = "xxxx.com"
$UserRegPath = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings\ZoneMap\Domains"
$DWord = 1
try {
Write-Verbose "Creating a new key '$LocalIntranetSite' under $UserRegPath."
New-Item -Path "$UserRegPath" -ItemType File -Name "$LocalIntranetSite"
New-Item -Path "$UserRegPath\$LocalIntranetSite" -ItemType File -Name "$prefixIntranet"
Write-Verbose "Creating a Dword value named 'HTTP' and set the value to '$DWord' "
Set-ItemProperty -Path $UserRegPath\$LocalIntranetSite\$prefixIntranet -Name "http" -Value $DWord `
Write-Host "Successfully added '$prefixIntranet.$LocalIntranetSite' domain to Internet Explorer local intranet."
} Catch [System.Exception] {
Write-Warning "[CATCH] Errors found during attempt:`n$_" -BackgroundColor Red
}
I was looking to do something similar. This will do the job:
# Gets you PC Name like you had in your question
$LocalIntranetSite = $env:computername -replace ".....$","ABC01"
# Set your base registry location
$UserRegPath = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet
Settings\ZoneMap\Domains"
# Set your zone. 1 is intranet.
$DWord = 1
try {
Write-Debug "Creating a new key '$LocalIntranetSite' under $UserRegPath."
# Check to be sure the key isn't already listed before trying to add
if (-not (Test-Path -Path "$UserRegPath\$LocalIntranetSite")) {
# Add your site to the domains list in the registry
New-Item -Path "$UserRegPath" -ItemType File -Name "$LocalIntranetSite"
}
# Set a Dword property named '*' and with value '$DWord' on your '$LocalIntranetSite'.
# This is what adds your site to the Intranet Zone.
Set-ItemProperty -Path "$UserRegPath\$LocalIntranetSite" -Name "*" -Value $DWord
} Catch [System.Exception] {
Write-Warning "[CATCH] Errors found during attempt:`n$_"
}

How can I use PowerShell to make remote registry changes?

I have tested the following PowerShell registry settings and it sets them correctly.
Could someone show me the way to do this for a remote computer?
New-Item -itemType String HKLM:\SYSTEM\CurrentControlSet\Services\SNMP\Parameters\TrapConfiguration\Server0ps -Value "MY.DOMAIN.COM"
New-ItemProperty HKLM:\SYSTEM\CurrentControlSet\Services\SNMP\Parameters\PermittedManagers -Name 1 -Value "whatever"
Set-ItemProperty HKLM:\SYSTEM\CurrentControlSet\Services\SNMP\Parameters\ValidCommunities -Name "Hello" -Value 4
Set-ItemProperty HKLM:\SYSTEM\CurrentControlSet\Services\SNMP\Parameters\ValidCommunities -Name "There" -Value 8
Use this as example:
$reg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine', $computername )
$regKey= $reg.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run",$true)
$regKey.SetValue("New_Valuename_String","New_Valuedata",[Microsoft.Win32.RegistryValueKind]::String)
To create a new key you need use powershell remoting with invoke-command for new-item cmdlet.
You might want to check the PSRemoteRegistry PowerShell Module, and its version for PowerShell 3.0 (with x86.x64 support, http://psrr.codeplex.com/).
If you just want to delete a key
$exchangeServers = #("xxxxx");
$hive = [Microsoft.Win32.RegistryHive]::LocalMachine;
$key = "SYSTEM\CurrentControlSet\Control\Lsa";
foreach ($exchangeServer in $exchangeServers)
{
$regBaseKey = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey($hive, $exchangeServer.ToString());
$regKeys = $regBaseKey.OpenSubKey($key,$true);
$beforeVal = $regKeys.GetValue("DisableLoopbackCheck");
Write-Host $exchangeServer " - " $beforeVal;
$regKeys.DeleteValue("DisableLoopbackCheck"); # a try catch can be placed here if there is a concern the key won't exist
$keyNames = $regKeys.GetSubKeyNames();
$afterVal = $regKeys.GetValue("DisableLoopbackCheck");
if ($afterVal -eq $null)
{
Write-Host $exchangeServer " - deleted" -ForegroundColor DarkGreen;
}
else
{
Write-Host $exchangeServer " - " $afterVal -ForegroundColor Red;
}
Write-Host " ";
}