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

时间:2014-10-31 17:34:53

标签: powershell registry

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

'我的图片'设置为'\\DeadServer\RedirectedFolders\%UserName%\My Documents\My Pictures'

我想将"\\DeadServer\RedirectedFolders"替换为"C:\Users"

如何在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`上的回收站已损坏。您要清空此驱动器的回收站吗?

登录时

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

4 个答案:

答案 0 :(得分:2)

我明白了。花了我很长时间,但我写了一个相当不雅的剧本:

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 "================================================================"
            }
        }
    }
}

如果你们中的任何人有这种方法,我很想知道更快或更优雅的方法。

答案 1 :(得分:1)

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

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中的默认驱动器。获取至少具有&#34; \ Software \ Microsoft \ Windows \ CurrentVersion \ Explorer \ User Shell Folders&#34;的路径的所有密钥。通过仅查找&#34; S-1-5-21&#34;作为关键的一部分。然后,对于位于每个位置的每个注册表值,找到与您要查找的路径匹配的数据。

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

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

确保您更改$pathToReplace$newPath的值,然后测试两次,执行一次。

答案 2 :(得分:0)

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

# 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!!!" } }
                    }
                }
            }
        }
    }
}

答案 3 :(得分:0)

@David Maisonave 感谢您的代码。 我看到它替换了键(注册表文件夹)和值(注册数据),但我想念注册表名称替换