c#→c++ / CLI→本机方法-需要safeproceshandle
本文关键字:需要 safeproceshandle 方法 CLI c++ 本机 | 更新日期: 2023-09-27 17:53:21
我的目标是。net 4.6.1,我有c#代码调用c++/CLI代码调用本地Win32方法EnumProcessModulesEx
,需要一个HANDLE作为其第一个输入参数:
// C#
System.Diagnostics.Process process = // ...
var allModuleNames = ProcessHelper.GetAllModuleNames(process);
// C++/CLI
#include <Psapi.h>
// ...
using namespace System;
using namespace System::Diagnostics;
// ...
array<String^>^ ProcessHelper::GetAllModuleNames(Process^ process)
{
// Should I use a SafeProcessHandle instead?
HANDLE processHandle = static_cast<HANDLE>(process->Handle.ToPointer());
BOOL result = EnumProcessModulesEx(processHandle, /*...*/);
// ...
}
我控制了c#和c++/CLI代码,我没有做任何p/Invoke。我的c++/CLI方法目前接受Process
参数,但它只使用Process.Handle
属性(并进行强制转换以获得必要的HANDLE值)。这安全吗,还是我需要一个SafeProcessHandle
?如果是这样,我如何将SafeProcessHandle
的值传递给EnumProcessModulesEx
?我必须呼叫SafeHandle.DangerousGetHandle
吗?
SafeHandle
的目的是确保当SafeHandle
结束时句柄将被释放,因此没有资源泄漏。换句话说,它允许GC管理句柄的生命周期,如果您忽略了手动释放的话。P/Invoke理解它,并确保它在WinAPI调用期间没有最终确定,即使你没有在其他任何地方保存对它的引用。
当你直接使用Win32 API时,你不能真正使用它,你必须调用DangerousGetHandle()
,它只是返回你已经拥有的原始句柄。
在您的例子中,句柄是由Process
类通过OpenProcess
WinAPI函数检索的。文档声明:
当您完成句柄时,请确保使用
CloseHandle
函数关闭它。
这意味着Process
类将释放它。它在Dispose
调用和Close
(Dispose
调用Close
)中都这样做。如果您不处理Process
对象,GC将为您关闭句柄。
因此,您所要做的就是确保GC在使用句柄时不会收集process
对象,否则句柄将无效。一个简单的方法就是调用:
System::GC::KeepAlive(process);
在之后的所有使用句柄的代码。当JIT看到这个函数调用时,它将确保process
引用至少在之前被标记为已使用 (JIT将向GC报告引用可达性)。
如果你不这样做,和如果你在代码中不使用process
对象,和如果发生GC, GC将注意到对象不可达并收集它(是的,即使你在代码中有一个引用它的局部变量-如果你不在剩余的代码块中访问它,将被收集,GC对此非常积极)。
查看我的答案在这里获得更多细节,尽管它是关于p/Invoke的使用。