C# 注册表 ObjectDisposedException 案例
C# Registry ObjectDisposedException Cases
我正在用 C# 编写一个访问 Windows 注册表的应用程序。
我的高层次问题是:在使用 Registry.LocalMachine.OpenSubKey(key)
时是否有任何情况会导致抛出 ObjectDisposedException?
此代码在我的应用程序中只会 运行 在管理权限下,并且密钥是一个永远不会为 null 的常量。我的第一直觉是这个静态调用永远不会抛出 ObjectDisposedException,因为 MSDN 文档(linked here) 声明它只会在 RegistryKey 关闭时抛出,但我在 MSDN 中找不到是否可以通过静态调用 运行 进入关闭的 RegistryKey。
感谢您的帮助!
测试是这样的:
Registry.LocalMachine.Close();
Registry.LocalMachine.Dispose();
var hardwareKey = Registry.LocalMachine.OpenSubKey("HARDWARE");
Registry.LocalMachine
returns一个RegistryKey
。如果您实际上可以关闭 and/or 处理它,那么下一行应该抛出异常,但它不会。
如果您对另一个注册表项执行相同的操作 - 关闭它然后尝试打开一个子项,它将抛出 ObjectDisposedException
.
var hardwareKey = Registry.LocalMachine.OpenSubKey("HARDWARE");
hardwareKey.Close();
// throws the exception.
var descriptionKey = hardwareKey.OpenSubKey("DESCRIPTION");
为什么他们的行为不同?
根据 the source code,RegistryKey.Close
调用 Dispose
。但是 Registry.LocalMachine
返回的特定 RegistryKey
将永远不会被关闭。
这没有记录(源代码除外)所以是否依赖它取决于您。但是,如果您通过静态方法访问注册表项,那么您不应该 close/dispose 它是有道理的。
如果按照这个逻辑,系统键(包括HKEY_LOCAL_MACHINE
)除了HKEY_PERFORMANCE_DATA
外不会被处理掉。
[System.Security.SecuritySafeCritical] // auto-generated
private void Dispose(bool disposing)
{
if (hkey != null)
{
if (!IsSystemKey())
{
try
{
hkey.Dispose();
}
catch (IOException)
{
// we don't really care if the handle is invalid at this point
}
finally
{
hkey = null;
}
}
else if (disposing && IsPerfDataKey())
{
// System keys should never be closed. However, we want to call RegCloseKey
// on HKEY_PERFORMANCE_DATA when called from PerformanceCounter.CloseSharedResources
// (i.e. when disposing is true) so that we release the PERFLIB cache and cause it
// to be refreshed (by re-reading the registry) when accessed subsequently.
// This is the only way we can see the just installed perf counter.
// NOTE: since HKEY_PERFORMANCE_DATA is process wide, there is inherent ---- in closing
// the key asynchronously. While Vista is smart enough to rebuild the PERFLIB resources
// in this situation the down level OSes are not. We have a small window of ---- between
// the dispose below and usage elsewhere (other threads). This is By Design.
// This is less of an issue when OS > NT5 (i.e Vista & higher), we can close the perfkey
// (to release & refresh PERFLIB resources) and the OS will rebuild PERFLIB as necessary.
SafeRegistryHandle.RegCloseKey(RegistryKey.HKEY_PERFORMANCE_DATA);
}
}
}
我正在用 C# 编写一个访问 Windows 注册表的应用程序。
我的高层次问题是:在使用 Registry.LocalMachine.OpenSubKey(key)
时是否有任何情况会导致抛出 ObjectDisposedException?
此代码在我的应用程序中只会 运行 在管理权限下,并且密钥是一个永远不会为 null 的常量。我的第一直觉是这个静态调用永远不会抛出 ObjectDisposedException,因为 MSDN 文档(linked here) 声明它只会在 RegistryKey 关闭时抛出,但我在 MSDN 中找不到是否可以通过静态调用 运行 进入关闭的 RegistryKey。
感谢您的帮助!
测试是这样的:
Registry.LocalMachine.Close();
Registry.LocalMachine.Dispose();
var hardwareKey = Registry.LocalMachine.OpenSubKey("HARDWARE");
Registry.LocalMachine
returns一个RegistryKey
。如果您实际上可以关闭 and/or 处理它,那么下一行应该抛出异常,但它不会。
如果您对另一个注册表项执行相同的操作 - 关闭它然后尝试打开一个子项,它将抛出 ObjectDisposedException
.
var hardwareKey = Registry.LocalMachine.OpenSubKey("HARDWARE");
hardwareKey.Close();
// throws the exception.
var descriptionKey = hardwareKey.OpenSubKey("DESCRIPTION");
为什么他们的行为不同?
根据 the source code,RegistryKey.Close
调用 Dispose
。但是 Registry.LocalMachine
返回的特定 RegistryKey
将永远不会被关闭。
这没有记录(源代码除外)所以是否依赖它取决于您。但是,如果您通过静态方法访问注册表项,那么您不应该 close/dispose 它是有道理的。
如果按照这个逻辑,系统键(包括HKEY_LOCAL_MACHINE
)除了HKEY_PERFORMANCE_DATA
外不会被处理掉。
[System.Security.SecuritySafeCritical] // auto-generated
private void Dispose(bool disposing)
{
if (hkey != null)
{
if (!IsSystemKey())
{
try
{
hkey.Dispose();
}
catch (IOException)
{
// we don't really care if the handle is invalid at this point
}
finally
{
hkey = null;
}
}
else if (disposing && IsPerfDataKey())
{
// System keys should never be closed. However, we want to call RegCloseKey
// on HKEY_PERFORMANCE_DATA when called from PerformanceCounter.CloseSharedResources
// (i.e. when disposing is true) so that we release the PERFLIB cache and cause it
// to be refreshed (by re-reading the registry) when accessed subsequently.
// This is the only way we can see the just installed perf counter.
// NOTE: since HKEY_PERFORMANCE_DATA is process wide, there is inherent ---- in closing
// the key asynchronously. While Vista is smart enough to rebuild the PERFLIB resources
// in this situation the down level OSes are not. We have a small window of ---- between
// the dispose below and usage elsewhere (other threads). This is By Design.
// This is less of an issue when OS > NT5 (i.e Vista & higher), we can close the perfkey
// (to release & refresh PERFLIB resources) and the OS will rebuild PERFLIB as necessary.
SafeRegistryHandle.RegCloseKey(RegistryKey.HKEY_PERFORMANCE_DATA);
}
}
}