【发布时间】:2019-05-31 16:19:06
【问题描述】:
我正在尝试将我在 pinvoke 代码中使用的所有句柄替换为 SafeHandles 的实现
特别是我为这样的 SafeThreadHandle 创建了一个实现
internal class SafeThreadHandle : SafeHandleZeroOrMinusOneIsInvalid
{
internal SafeThreadHandle() : base(true) {}
protected override bool ReleaseHandle()
{
return CloseHandle(handle);
}
}
例如,这对大多数情况都很有效
[DllImport("kernel32.dll")]
internal static extern int ResumeThread(SafeThreadHandle threadHandle);
当我尝试使用 aSafeThreadHandle 作为以下两个 pinvoke 函数的参数时,该函数失败并设置 windows 错误 998,msdn 状态如下
ERROR_NOACCESS 998 (0x3E6) 对内存位置的访问无效。
[DllImport("kernel32.dll")]
internal static extern bool GetThreadContext(SafeThreadHandle threadHandle, ref Context64 context);
[DllImport("kernel32.dll")]
internal static extern bool SetThreadContext(SafeThreadHandle threadHandle, ref Context64 context);
奇怪的是,如果我将 SafeThreadHandle 替换为通过 threadHandle.GetDangerousHandle() 获得的线程句柄的 IntPtr(参数和参数),函数就会成功并按预期工作。
所以我想我的问题是为什么我不能将SafeHandle 的SafeThreadHandle 实现用作上述两个函数的参数,但我可以将它用于其他函数,例如ResumeThread
【问题讨论】:
-
什么时候调用 SetHandle? referencesource.microsoft.com/#system/compmod/microsoft/win32/…
-
我正在使用 OpenThread 获取句柄(它返回一个 SafeThreadHandle),我读到 Marshal 处理它,因此是无参数构造函数
-
我没有重现该问题。这可能是由于 Context64 参数定义和/或调用造成的。另外,如果您没有在 GetThreadContext 上定义 SetLastError,您如何判断错误。请在某处分享完整的 .zip 副本。
-
对不起,我从提供的示例中排除了 SetLastError,因为我在开始调试之前输入了它们,但我在我的真实代码中使用它。提供这个项目有点困难,因为它相当大。您可以分享您使用的代码吗?在比较两个来源后,我会发布回复,如果我有任何差异,请告诉您。