首页 文章

Powershell在注册表值上查找并替换?

提问于
浏览
2

'HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders' 中,我将一些路径设置为旧服务器 . 例如 . :

'My Pictures'设置为 '\\DeadServer\RedirectedFolders\%UserName%\My Documents\My Pictures'

我想用 "C:\Users" 替换 "\\DeadServer\RedirectedFolders"

怎么能在 powershell 中完成?


我尽力而为

Get-ItemProperty -path "Microsoft.PowerShell.Core\Registry::HKEY_USERS\*\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders" | ? {$_.PSObject.Properties -like "*DeadServer*"}

但是我觉得我对我想要改变的条目是一个'属性'而不是一个'Item'感到困惑,而且我不知道如何迭代像我做项目这样的属性 .


在你问之前,我没有服用 . 用户收到消息

\ DeadServer \ RedirectedFolders \%UserName%\ My Documents \ My Pictures`上的回收站已损坏 . 您要清空此驱动器的回收站吗?

在登录时保持文件夹重定向不被应用 .
这是我尝试手动强制更改回本地存储 .

3 回答

  • 1

    我想到了 . 花了我很长时间,但我写了一个相当不雅的剧本:

    Get-Item -ErrorAction SilentlyContinue -path  "Microsoft.PowerShell.Core\Registry::HKEY_USERS\*\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders" |
    foreach {
        Get-ItemProperty -Path "Microsoft.PowerShell.Core\Registry::$_" | 
        foreach {
            $CurrentUserShellFoldersPath = $_.PSPath
            $SID = $CurrentUserShellFoldersPath.Split('\')[2]
            $_.PSObject.Properties |
            foreach {
                if ($_.Value -like "*DeadServer*") {
                    write-host "Path:`t`t"$CurrentUserShellFoldersPath
                    write-host "SID:`t`t"$SID
                    write-host "Name:`t`t"$_.Name
                    write-host "Old Value:`t"$_.Value
                    $newValue = $_.Value
                    $newValue = $newValue -replace '\\\\DeadServer\\RedirectedFolders', "C:\Users"
                    $newValue = $newValue -replace "My Documents\\", ""
                    $newValue = $newValue -replace "My ", ""
                    Write-Host "New Value:`t"$newValue
                    Set-ItemProperty -Path $CurrentUserShellFoldersPath -Name $_.Name -Value $newValue
    
                    Write-host "================================================================"
                }
            }
        }
    }
    

    如果你们中的任何一个人,我会喜欢学习更快或更优雅的方法 .

  • 0

    对此并不满意,所以如果有人对此感到羞耻,我会感到高兴和悲伤 . 在验证它是否找到正确的密钥时,它经过了大部分测试 .

    If(!(Test-Path HKU:)){New-PSDrive -PSProvider Registry -Name HKU -Root HKEY_USERS}
    $registrySearchPath = "HKU:\*\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders"
    $pathToReplace = [regex]::Escape("C:\Users")
    $newPath = '%USERPROFILE%'
    Get-Item -path $registrySearchPath -ErrorAction SilentlyContinue | 
            Select-Object -ExpandProperty Name | 
            Where-Object{$_ -match "^HKEY_USERS\\S-1-5-21"} |
            ForEach-Object{
        $key = $_ -replace "^HKEY_USERS","HKU:"
        (Get-ItemProperty $key).psobject.Properties | Where-Object{$_.Value -match $pathToReplace} | 
                Select-Object Name,Value | ForEach-Object{
            Set-ItemProperty -Path $key -Name $_.Name -Value ($_.Value -replace $pathToReplace,$newPath) -WhatIf
        }
    }
    

    使用Psdrive映射HKU,因为它不是PowerShell中的默认驱动器 . 获取至少具有“\ Software \ Microsoft \ Windows \ CurrentVersion \ Explorer \ User Shell Folders”路径的所有密钥 . 通过仅查找具有“S-1-5-21”作为密钥一部分的帐户,省略默认密钥和任何其他区域设置帐户 . 然后,对于位于每个位置的每个注册表值,找到与您要查找的路径匹配的数据 .

    Set-ItemProperty -Path $key -Name $_.Name -Value ($_.Value -replace $pathToReplace,$newPath) -WhatIf
    

    在这里稍微关注最后一部分 . 使用匹配的所有值,我们用简单的 -replace 替换数据 . 我有一个 -WhatIf ,以确保你测试一些不好的事情 . 我建议评论该行并输出 $_.Value -replace $pathToReplace,$newPath 来验证它是否正在按照您的预期进行操作 .

    Make sure 您更改 $pathToReplace$newPath 的值然后测试两次,执行一次 .

  • 2

    这是一个易于使用的注册表替换功能,可以递归搜索路径 .

    # Replace all registry key values and/or registry key names under a given path.
    # Example Usage:
    #   RegistryValue-Replace "ExistingValue" "NewValue" 'HKEY_CURRENT_USER\Software\100000_DummyData'
    #   RegistryValue-Replace "ExistingValue" "NewValue" 'HKEY_USERS\*\Software\100000_DummyData' -ReplaceKeyNames $true -CaseSensitive $true
    #   RegistryValue-Replace 'C:\\Program Files\\Microsoft SQL Server' 'E:\Program Files\Microsoft SQL Server' 'HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SQL Server*' -LoggingOn $true
    
    function RegistryValue-Replace (
      [string]$OldValue = $(throw “OldValue (the current value) required.”),
      [string]$NewValue = $(throw “NewValue (the replacement value) required.”),
      [string]$RegkPath = $(throw “RegkPath (The full registry key path) required.”),
      [bool] $CaseSensitive = $false, # If true, search and replace is case sensitive
      [bool] $WholeWord = $false, # If true, searches for whole word within the value.
      [bool] $ExactMatch = $false,  # If true, the entire value must match OldValue, and partial replacements are NOT performed
      [bool] $ReplaceKeyNames = $false, # If true, replaces registry key names
      [bool] $ReplaceValues = $true,
      [bool] $LoggingOn = $false ) 
    {
        $PowershellRegPrefix = 'Microsoft.PowerShell.Core\Registry::'
        $MatchFor = if ($WholeWord -eq $true) {".*\b$OldValue\b.*"} else { ".*$OldValue.*" }
        if ($RegkPath -NotLike "$PowershellRegPrefix*") { $RegkPath = $PowershellRegPrefix + $RegkPath }
    
        @(Get-Item -ErrorAction SilentlyContinue -path  $RegkPath) +
        @(Get-ChildItem -Recurse $RegkPath -ErrorAction SilentlyContinue) |
        foreach {
            Get-ItemProperty -Path "$PowershellRegPrefix$_" | 
            foreach {
                $CurrentShellFoldersPath = $_.PSPath
                $SID = $CurrentShellFoldersPath.Split('\')[2]
                $_.PSObject.Properties |
                foreach {
                    if ($_.Name -cne "PSChildName" -and (($ExactMatch -eq $true -and $_.Value -clike $OldValue) -or ($ExactMatch -eq $false -and
                        (($CaseSensitive -eq $false -and $_.Value -match $MatchFor) -or ($CaseSensitive -eq $true -and $_.Value -cmatch $MatchFor))))) {
                        $Original = $_.Value
                        $Create_NewValue = $_.Value
                        $SubKeyName = $_.Name
                        if ($CaseSensitive -eq $true){ $Create_NewValue = $Create_NewValue -creplace $OldValue, $NewValue }
                        else                         { $Create_NewValue = $Create_NewValue -replace  $OldValue, $NewValue }
                        if ($_.Name -eq "PSPath" -and $_.Value -eq $CurrentShellFoldersPath) {
                            if ($ReplaceKeyNames -eq $true) {
                                Move-Item -Path $CurrentShellFoldersPath -Destination $Create_NewValue
                                if ($LoggingOn -eq $true){ Write-host "Renamed registry key '$CurrentShellFoldersPath' to '$Create_NewValue'" }
                            } else {
                                if ($LoggingOn -eq $true){ Write-host "....Skipping renaming key '$CurrentShellFoldersPath->$SubKeyName' due to input option!!!" } }
                        } else {
                            if ($ReplaceValues -eq $true) {
                                Set-ItemProperty -Path $CurrentShellFoldersPath -Name $_.Name -Value $Create_NewValue
                                if ($LoggingOn -eq $true){ Write-host "Renamed '$Original' to '$Create_NewValue' for registry key '$CurrentShellFoldersPath->$SubKeyName'" }
                            } else {
                                if ($LoggingOn -eq $true){ Write-host "....Skipping renaming value '$CurrentShellFoldersPath->$SubKeyName' due to input option!!!" } }
                        }
                    }
                }
            }
        }
    }
    

相关问题