这是我第一次使用SafeHandle

我需要调用需要UIntPtr的P/Invoke方法。



此UIntPtr将继承自.NET的RegistryKey类。我将使用上面的方法将RegistryKey类转换为IntPtr,以便可以使用上面的P/Invoke:

        private static IntPtr GetRegistryKeyHandle(RegistryKey rKey)
        {
            //Get the type of the RegistryKey
            Type registryKeyType = typeof(RegistryKey);

            //Get the FieldInfo of the 'hkey' member of RegistryKey
            System.Reflection.FieldInfo fieldInfo =
                registryKeyType.GetField("hkey", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);

            //Get the handle held by hkey
            if (fieldInfo != null)
            {
                SafeHandle handle = (SafeHandle)fieldInfo.GetValue(rKey);

                //Get the unsafe handle
                IntPtr dangerousHandle = handle.DangerousGetHandle();
                return dangerousHandle;
            }
}

问题:
  • 是否有更好的方式编写此代码而不使用“不安全”的句柄?
  • 为什么不安全的手柄会有危险?
  • 最佳答案

    实际上,您正在做的事情很危险。使用IntPtr时,您使用的RegistryKey对象可能会被垃圾收集并最终确定。这会使句柄值无效,这会使您的代码随机失败。好吧,好的,随机失败并不完全危险,但是如果您长时间握住手柄,它确实为手柄回收攻击打开了大门。随机故障模式应该足以激发您对此采取一些措施。

    使您的pinvoke声明如下所示:

    [DllImport("advapi32.dll", CharSet=CharSet.Auto)]
    internal static extern int RegOpenKeyEx(SafeRegistryHandle key, string subkey,
        int options, int sam, out SafeRegistryHandle result);
    

    因此,您可以始终使用安全句柄包装器类。相应地调整反射代码。

    10-08 16:22