locked
How to rename multiple registry entries at once. RRS feed

  • Question

  • Hi all, 

    I just started trying to learn powershell and I thought I'll create a script to clean up office. 

    For folders I managed to write the code:

    Get-ChildItem -Path "C:\MSOCache\All Users" *0FF1CE*| Rename-Item -NewName {$_.Name + ".OLD"} -Force -ErrorAction 'silentlycontinue

    However, this does not work with Registry where I need to search with wildcard? Correct me if I'm wrong.

    $Path="HKLM:\SOFTWARE\Microsoft"
    Get-Item -Path $Path\Windows\CurrentVersion\Uninstall\*TEST* | Rename-Item -NewName TEST.OLD -Force

    Get-Item -Path $Path\Windows\CurrentVersion\Uninstall\*TEST*
    
    
        Hive: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall
    
    
    SKC  VC Name                           Property                                                                                                                                        
    ---  -- ----                           --------                                                                                                                                        
      0   0 xxxTESTzzz                     {}                                                                                                                                              
      0   0 zzzTESTzzz                     {}            

    So the Reg  keys are being found. If I run the code as above, it only changes one of the two.

    I also tried exactly as per Office folder. 

    $Path="HKLM:\SOFTWARE\Microsoft"
    Get-Item -Path $Path\Windows\CurrentVersion\Uninstall\*TEST* | Rename-Item -NewName {$_.Name + ".OLD"} -Force

    It just says that the key at the specified path does not exist. I assume that when I run the ps it searches for *TEST* folder and not for keys containing TEST in name. 

    What I want to achieve is exactly as per MSOCache, renaming xxxTESTxxx to xxxTESTxxx.OLD and zzzTESTzzz to zzzTESTzzz.OLD

    Greatly appreciating your help, also if possible with explanation.

    Thanks!

    Wednesday, August 8, 2018 5:30 PM

All replies

  • Try find and replace for multiple registry value change. https://community.spiceworks.com/topic/387573-powershell-registry-find-and-replace
    • Edited by Partha1012 Wednesday, August 8, 2018 5:43 PM
    Wednesday, August 8, 2018 5:42 PM
  • Thanks, that does not look however as a renaming convention by adding a suffix to the item name.
    Wednesday, August 8, 2018 9:46 PM
  • To use Rename-Item cmdlet, the issue is you need to use the PSDrive path (such as HKLM:\Software) and not the descriptive name stored in the object name field (such as HKEY_Local_Machine).

    You have the format correctly specified in $PATH, but the Get-Item object stores the name differently.  In my example I just rename "HKEY_LOCAL_MACHINE" back to "HKLM:" format.

    $Path="HKLM:\SOFTWARE\Microsoft"
    
    Get-Item -Path $Path\Windows\CurrentVersion\Uninstall\*TEST* | % {
    
    $UPD_PATH = $_.name.Replace('HKEY_LOCAL_MACHINE','HKLM:')
    $NEW_NAME = $_.PsChildName + 'old'
    
    Rename-Item -Path $UPD_PATH -NewName $NEW_NAME
    
    }



    Thursday, August 9, 2018 12:40 PM
  • Oh, I didn't know that Get-Item changes the registry path from PSDrive to "standard". 

    Thanks!.

    PS. can you please explain some of your code. 

    $_.name.Replace I assume is the same as in the MS artice: https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.management/rename-item?view=powershell-6

    Which means that $_.name -Replace could have also been used?

    $PSChildName represents the original name of the registry key I assume, which would be the case in any scenario.

    Oh, $ commands seem more complicated. Verb+Noun commands make more sense :D

    PS: What is % used for?
    • Edited by sahara101 Thursday, August 9, 2018 2:15 PM
    Thursday, August 9, 2018 1:35 PM
  • For the purposes of this script .Replace and -Replace would provide equivalent results - but they are different.

    .Replace is a simple string method

    (Get-Item -Path 'HKLM:\Software').name | Get-Member  ### Name property is a string

    -Replace is a much more powerful comparison operator: link

    PSChildName is a Property of the Get-Item object:

    (Get-Item -Path 'HKLM:\software') | select *


    Thursday, August 9, 2018 2:18 PM
  • I stumbled on my next issue, it is in for the same topic so I will ask here. 

    Now I want to search for *F01FEC*

    and rename exactly the same as before, but difference is they are in more folders and I want it to skip one of them.

    So if I: 

    Get-ChildItem -Path $Path\Windows\CurrentVersion\Installer\ -Include *F01FEC* -Recurse

    It finds data in HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UpgradeCodes

    HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Products

    and HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Components

    I want it to not scan the Components folder. 

    What I tried is set up an -exclude command for $Exclude="$Path\Windows\CurrentVersion\Installer\UserDat\S-1-5-18\Components"

    But it stills searches in that directory as well. 

    Also, seems that with -recurse Get-Item is not working, only Get-ChildItem.

    Thanks again for your patience. 

    Thursday, August 9, 2018 6:29 PM
  • You can try something like this:

    Get-ChildItem -path $path -recurse -include '*F01FEC*'  | ? {($_.pschildname -match '^F01FEC$') -and ($_.name -notmatch '^HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\S-1-5-18\\Components\\.*')} | select name

    I assume you only care to match the pschildname exactly as 'F01FEC'.  It's likely that string may partially match other key names.

    Get-ChildItem is finding all matches for "F01FEC" anywhere in the string, and then the where clause will filter on only the pschildnames that match "F01FEC" exactly and filter out any matches under the "components" key.

    Thursday, August 9, 2018 7:28 PM
  • I want to search it anywhere in the string - it is actually at the end of the string. Ex:

    Hive: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UpgradeCodes


    Name                           Property
    ----                           --------
    000021509B0000000100000000F01F 000021599B0090400100000000F01FEC :

    But I only want to search for it in PSChildName. components key has the F01FEC also in values and I want to skip that folder altogether.

    Starting your command does not do anything, probably because it searches for exactly F01FEC.

    Thanks again.

    Thursday, August 9, 2018 9:35 PM
  • Here is how to search for an item in the registry.

    Get-ChildItem HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall |
        Get-ItemProperty -Name DisplayName -ea 0| 
        Where-Object{$_.DisplayName -match '^office'} | 
        Select-Object DisplayName


    \_(ツ)_/

    Thursday, August 9, 2018 9:50 PM
  • Also note that you cannot rename a key or a value in the registry.  You can copy the contents to a new key or value and delete the original.

    The easiest way to keep a key that you want to remove or disable is to export the key to a file and delete it.  Once you find the key then use "reg export" to save it.  Then use the "DeleteSubKey" method of the parent key.

    $parent = Get-Item $key.PSParentPath
    # REG EXPORT keyname file.reg

    $parent.DeleteSubKey($key)


    \_(ツ)_/


    • Edited by jrv Thursday, August 9, 2018 10:00 PM
    Thursday, August 9, 2018 9:58 PM
  • Example of export:

    $keypath = $key.ToString()
    REG EXPORT $keypath 7zip.reg


    \_(ツ)_/

    Thursday, August 9, 2018 10:04 PM
  • I want to search it anywhere in the string - it is actually at the end of the string. Ex:


    Well saying "anywhere" and "at the end" are completely different things.  I'd be really careful about doing any mass replace on that string "anywhere" - it has the potential to match many keys including ones you did not intend to modify.

    Do you know the entire string?  Or are their multiple cases where "F01FEC" is at the very end?  You should limit your search to the most specific pattern.

    All you need to do is change the regex pattern such that "F01FEC" is at the very end.

    Get-ChildItem -path $path -recurse -include '*F01FEC*'  | ? {($_.pschildname -match '.*F01FEC$') -and ($_.name -notmatch '^HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\S-1-5-18\\Components\\.*')} | select name

    Friday, August 10, 2018 12:27 PM
  • To search the end of a string use  this:

    $string -match 'F01FEC$'

    The $ indicates that the characters are only matched at the end of the string.

    Once again - you cannot rename keys and values in the registry.


    \_(ツ)_/

    Friday, August 10, 2018 3:22 PM

  • Once again - you cannot rename keys and values in the registry.


    You can rename the keys.

    New-Item -Path 'HKCU:\Software\MyTestApp'
    Rename-Item -Path 'HKCU:\Software\MyTestApp' -NewName "MyNewTestApp"
    Get-Item -Path 'HKCU:\Software\MyNewTestApp'

    Friday, August 10, 2018 3:54 PM
  • I found a way to do it.  The newname argument only needs the basename.  A trick in powershell is that arguments that can be sent over the pipe can also take script blocks.

    $Path='HKLM:\SOFTWARE\Microsoft'

    Get-Item $Path\Windows\CurrentVersion\Uninstall\*TEST* |
      Rename-Item -newname { $_.pschildname + '.old' }

    Or ($ is regex for end of line)


    $Path
    ='HKLM:\SOFTWARE\Microsoft'

    Get-Item $Path\Windows\CurrentVersion\Uninstall\*TEST* |

      Rename-Item -newname { $_.pschildname -replace '$','.old' }

    • Edited by JS2010 Friday, August 10, 2018 6:51 PM
    Friday, August 10, 2018 5:51 PM
  • I want to search it anywhere in the string - it is actually at the end of the string. Ex:


    Well saying "anywhere" and "at the end" are completely different things.  I'd be really careful about doing any mass replace on that string "anywhere" - it has the potential to match many keys including ones you did not intend to modify.

    Do you know the entire string?  Or are their multiple cases where "F01FEC" is at the very end?  You should limit your search to the most specific pattern.

    All you need to do is change the regex pattern such that "F01FEC" is at the very end.

    Get-ChildItem -path $path -recurse -include '*F01FEC*'  | ? {($_.pschildname -match '.*F01FEC$') -and ($_.name -notmatch '^HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\S-1-5-18\\Components\\.*')} | select name

    @ALL Thank you for your consistent help.

    Keys are like this:

    HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UpgradeCodes\00005150250000000100000000F01FEC

    HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Products\00004109110000000000000000F01FEC

    HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Products\00005159250090400100000000F01FEC

    etc. 

    So yes, they are at the end. I would have assumed that it does not matter where in the key name my search "include" is located. 

    Monday, August 13, 2018 7:03 AM