reg卸载和新密钥

时间:2014-08-22 01:37:57

标签: powershell registry

我可以运行这些命令,一切都按预期进行

reg load HKU\Kayla C:\Users\Kayla\ntuser.dat
New-Item -Force Registry::HKU\Kayla\Foo

但是在运行之后会导致错误

PS > reg unload HKU\Kayla
ERROR: Access is denied.

如果我手动打开注册表编辑器,我可以卸载配置单元,但我会 喜欢在可能的情况下从脚本中卸载。

更新:在阅读了Matt的回答之后,如果你运行一个命令,我发现它可以工作 在collect之前,例如

0
[gc]::collect()

似乎0充当"回收站"而collect就是 “永久删除”。

3 个答案:

答案 0 :(得分:3)

编辑2015-04-07:如果您正在托管PowerShell并在调试模式下运行,则可能需要在强制垃圾回收后等待挂起的终结器。更多信息如下。


问题是New-Item创建了一个注册表项的句柄并使其保持打开状态,如果GC调用全部在同一个脚本中运行,那么你必须手动关闭该句柄才能清除它。 。 (您可以使用Process Explorer的“查找 - >查找句柄或DLL ...”功能查看打开的句柄;在那里搜索您的密钥名称。)

幸运的是,New-Item的结果使您可以轻松访问该句柄:

$result = New-Item # ...
$result.Handle.Close()

现在您可以[gc]::Collect()清理句柄和reg unload

在以调试模式运行的自定义PowerShell主机中,由于differences in GC between Debug and Release modes,您可能必须通过调用[gc]::WaitForPendingFinalizers()来执行此操作,但请阅读the literature,因为这可能会导致死锁在一定条件下。在我的测试中,Release模式无需等待挂起的终结器即可运行。

SOME_USER的完整工作示例:

$path = "HKLM:\TEMP_hive\newkey" # Key we're going to create.
reg load HKLM\TEMP_hive C:\Users\SOME_USER\NTUSER.DAT
$result = New-Item -Path $path
$result.Handle.Close()
[gc]::Collect()
[gc]::WaitForPendingFinalizers() # Optional, and beware of deadlocks! Only seen this needed in Debug mode.
reg unload HKLM\TEMP_hive

请注意,您必须是管理员并且已经提升。

<强>详细信息:

在我的测试中,只要运行名为[gc]::Collect()的相同脚本,New-Item就无法清理打开的句柄。有趣的是,这意味着在像PowerShell ISE这样的交互式上下文中,如果控件返回到[gc]::Collect()之前的提示符,它具有相同的效果,并且句柄变为收集器的公平游戏,甚至没有关闭它。在PowerShell ISE中,运行:

$path = "HKLM:\TEMP_hive\differentnewkey" # Key we're going to create.
reg load HKLM\TEMP_hive C:\Users\SOME_USER\NTUSER.DAT
New-Item -Path $path

然后运行:

[gc]::Collect()
reg unload HKLM\TEMP_hive

reg unload也总是在这种情况下取​​得成功。

请注意,在最后一个示例中,我不再将New-Item的返回结果分配给变量,如$ result,因为如果你这样做,只要$ result在环境中,你仍然可以使用该句柄在您的提示下,reg unload将再次失败。试试吧:

$path = "HKLM:\TEMP_hive\thirdnewkey" # Key we're going to create.
reg load HKLM\TEMP_hive C:\Users\SOME_USER\NTUSER.DAT
$result = New-Item -Path $path

然后运行:

[gc]::Collect()
reg unload HKLM\TEMP_hive

在致电$result.Handle.Close()之前无效。

此外,尽管互联网上的帖子表明存在时间问题,但在那里睡一觉不应该改变任何东西(除非你在上面的自定义主机+调试情况中,在这种情况下我建议等待终结者) - 如果该句柄符合垃圾收集的条件,那就完全了。如果有人能够在更深层次上解释该句柄和垃圾收集器发生了什么,那将是非常感兴趣的。

答案 1 :(得分:1)

似乎可能存在对已加载的配置单元的开放引用。在卸载之前运行以下命令应该清理引用(如果有的话)

[gc]::collect()

可以找到更多信息here

  

这使用.NET中的GC类的静态方法Collect   用于强制垃圾收集器运行和删除它们   未使用的参考文献。

同时

这可能更像是一回事,但只是一种不同的方法。同样,仍然存在引用Get-ChildItem variable:显示$下的蜂巢的引用。运行其他命令来更改该变量的内容似乎也允许hive卸载。有关此问题的更多信息here。例如。

Get-ChildItem variable:

Name                           Value                                                     
----                           -----                                                     
$                              HKU\Kayla   

在实践中

虽然这可能对你不起作用,但我自己运行时提升了权限。

PS C:\Windows\system32> reg load HKU\Kayla C:\temp\file.dat
The operation completed successfully.
PS C:\Windows\system32> New-Item -Force Registry::HKU\Kayla\Foo

    Hive: HKU\Kayla

Name                           Property
----                           --------
Foo

PS C:\Windows\system32> reg unload HKU\Kayla
ERROR: Access is denied.
PS C:\Windows\system32> Get-ChildItem variable:

Name                           Value
----                           -----
$                              HKU\Kayla

PS C:\Windows\system32> Get-ChildItem variable:

Name                           Value
----                           -----
$                              variable:

PS C:\Windows\system32> reg unload HKU\Kayla
The operation completed successfully.

答案 2 :(得分:0)

要完全避免担心打开句柄,可以使用[Microsoft.Win32.Registry] :: SetValue,它将在设置值后关闭句柄。请参阅Microsoft documentation