是不是那个标题拗口?
我要解决的问题:
我需要对此注册表项执行多次搜索操作,然后在验证我正在使用脚本更改正确的值后更改特定值。
工作流程如下:
这最终需要对每个服务器的 16 个键进行 4 次操作,并且这是一个高延迟连接 - 感觉就像需要永远。我希望能够在获取完整密钥后进行本地搜索,这将允许我为第一步和最后一步分别建立一个远程连接,而第二步则根本没有连接- 将每台服务器的连接数从 64 个减少到 18 个。
什么样的作品:
我可以使用以下命令来获取我实际需要的所有信息:
REG QUERY \\server01\HKLM\Software\Wow6432Node\Vendor\App\DatabaseList /s
这将输出注册表项的所有信息。它是人类可读的,但作为我可以搜索的对象,它会更有用。显然我可以写一些东西来解析它,但我觉得必须有更好的方法。
另一种解决方案是使用 REG EXPORT,但它看起来只适用于本地计算机(例如使用 Invoke-Command)并且需要写入一个文件 - 这是可能的,但很难看。这至少会给我一个更结构化的文件来解析。
我尝试过的:
Get-ChildItem HKLM:\$registryKey
似乎给了我一切除了的价值观。如果它们在那里,我不知道如何将它们从物体中拉出来。我发现的所有示例似乎都使用 Get-ItemProperty
在单独的命令中获取实际值。
Get-ItemProperty
看起来它可以为我获取值,但我需要拥有正在查询的特定密钥(当然,直到我搜索它之前我才拥有。)
似乎有很多解决方案 - 问题是所有解决方案似乎都假设网络访问是零成本的,但这里的情况并非如此。
我真正想要的:
发出单个网络请求的单个命令,该请求返回一个结构化对象,其中包含上面 REG QUERY 命令中包含的所有信息。剩下的我可以弄清楚。
请注意,我在这里尝试尽可能减少网络请求的数量。我已经有了一个使用 REG QUERY 执行第一部分中列出的工作流程的解决方案。解析这些请求的代码完全是黑客行为,我想要更多 Powershell 原生的代码。然而,黑客工作,所以如果我不能从中获得性能改进,那么以不同的方式重新实现它就没有价值(在这种情况下)。
其他注意事项:如果一切都可以在本地运行,我仅限于 Powershell 5,如果我在远程计算机上调用命令,则仅限 Powershell 2(不要问,哈哈)。如果 Powershell 7 解决方案对于运行 Powershell 2 的计算机来说完全可行,我将采用 Powershell 7 解决方案。
发送脚本在远程计算机上运行,而不是从本地计算机运行。
$credential = Get-Credential
$registryKey = "HKLM:\software\microsoft\windows\currentversion\themes"
$computers = 'web02','dhcp01','mail01'
$result = Invoke-Command -ComputerName $computers -Credential $credential -ScriptBlock {
$keys = Get-ChildItem -Recurse -Path $using:registryKey
foreach($key in $keys) {
$obj = [pscustomobject]@{
Name = $key.Name
Properties = @{}
}
foreach($property in $key.Property) {
$obj.Properties[$property] = $key.GetValue($property)
}
Write-Output $obj
}
}
foreach($entry in $result) {
Write-Verbose -Verbose ("{0} -- {1}" -f $entry.PSComputerName, $entry.Name)
foreach($key in $entry.Properties.Keys) {
Write-Verbose -Verbose ("- $key == {0}" -f $entry.Properties[$key])
}
}