Search code examples
powershellregistryupdates

PowerShell Update Registry Value Based on Capital Letter Criteria


Thanks to @mklement0 I have the ability to recurse through a registry key to find the value of a registry string value where the letters https contain capital letters before the : symbol.

Taking it another step I would now like the ability or option to change the letters https to all lowercase if found to contain any variation of capital letters.

I believe I need to somehow use Set-Itemproperty to accomplish this. The pain point for me is, it required the -path parameter. This is where I'm getting stumped.

Here is the code that mklement0 gave me to find the value if it contains any capital letters

Get-ChildItem -Path 'HKLM:\Software\MySoftwareKey' -Recurse -ErrorAction SilentlyContinue |
  Get-ItemProperty Web -ErrorAction SilentlyContinue | 
    Select-Object -ExpandProperty Web |
      Where-Object { ($_ -split ':')[0] -cmatch '\p{Lu}' }

I would like to have any https that contain capital letters changed to all lowercase so that the Web registry string value only would always begin with https before the :.


Solution

  • In this scenario it is ultimately easier to work directly with Microsoft.Win32.RegistryKey, the .NET type that Get-ChildItem returns for registry paths:

    Note: Since you're targeting HKLM:, i.e. the HKEY_LOCAL_MACHINE registry hive, you must run the following code with elevation (as an administrator).

    Get-ChildItem -Path 'HKLM:\Software\MySoftwareKey' -Recurse -ea SilentlyContinue |
      ForEach-Object {
        if ($url = $_.GetValue('Web')) {
          $protocol, $rest = $url -split ':', 2
          if ($protocol -cmatch '\p{Lu}') {
            $_ | Set-ItemProperty -Name 'Web' -Value ($protocol.ToLower() + ':' + $rest)
          }
        }
      }
    
    • if ($url = $_.GetValue('Web')) checks for a (nonempty) Web value and assigns it to $url

    • $protocol, $rest = $url -split ':', 2 splits the URL into the part before the : (the protocol name, such as https) and the rest (2 is the maximum number of tokens to create).

    • As in the command in your question, $protocol -cmatch '\p{Lu}' looks case-sensitively (-cmatch) for any uppercase letter (\pL{u}).

    • $_ | Set-ItemProperty -Name Web -Value ($protocol.ToLower() + ':' + $rest) rewrites the value with the protocol name converted to all-lowercase.

      • Note: It is tempting to try $_.SetValue('Web', $protocol.ToLower() + ':' + $rest) instead, but the Microsoft.Win32.RegistryKey instances returned by Get-ChildItem reflected in $_ are read-only, so that trying to call .SetValue() invariably fails, even if your user account has sufficient privileges in principle.