gpt4 book ai didi

c# - C# COM DLL 中的 ManagementObject 泄漏

转载 作者:塔克拉玛干 更新时间:2023-11-03 07:33:58 26 4
gpt4 key购买 nike

我有一个 C# COM DLL,它使用 System.Management 命名空间调用 WMI。 DLL 正在加载到 C++ 服务中。每次调用 WMI 类时,我都会看到巨大的内存泄漏。大约一个小时后,我使用了超过 1 GB 的内存。

如果我采用相同的 COM DLL 并使用 Reflection.LoadFrom 将其加载到 PowerShell 中,它不会泄漏内存。我已经像这样修改了 DLL,它不再泄漏(仍然使用 COM 加载到服务中):

public class MyComObject
{
public void CallCom()
{
CallSomeWMIStuff();
}
}

为此。这不再泄漏!

public class MyComObject
{
public void CallCom()
{
//CallSomeWMIStuff();
}
}

这是一些 WMI 代码的示例:

var scope = new ManagementScope( "root\\cimv2" );
scope.Connect();

using (var myservice = GetService("SomeService", scope))
{
//Some Stuff
}
...
ManagementObject GetService(string serviceName, MangementScope scope)
{
ManagementPath wmiPath = new ManagementPath( serviceName );

using (ManagementClass serviceClass = new ManagementClass( scope, wmiPath, null ))
{
using (ManagementObjectCollection services = serviceClass.GetInstances())
{
ManagementObject serviceObject = null;

// If this service class does not have an instance, create one.
if (services.Count == 0)
{
serviceObject = serviceClass.CreateInstance();
}
else
{
foreach (ManagementObject service in services)
{
serviceObject = service;
break;
}
}

return serviceObject;
}
}
}

编辑:C++ 片段:

NAMESPACE::ICSharpComPtr pCSharpCom = NULL;
HRESULT hr = pCSharpCom .CreateInstance(NAMESPACE::CLSID_CSharpCom);
if (FAILED(hr))
{
Log("Failed (hr=%08x)", hr);
return hr;
}

try
{
_bstr_t bstrData = pCSharpCom ->GetData();

strLine = (LPCTSTR)bstrData;
strMessage += strLine;
}
catch (_com_error& err)
{
_bstr_t desc = GetErrorMessage(err);
Log("Excepton %S", (const wchar_t*)desc);
return 0;
}

pCSharpCom ->Release();

有没有人见过这样的事情?我们发现 C++\CLI 存在类似问题,它直接加载不同的 WMI 相关 DLL。

最终,WMI 服务将不再响应,我也必须重新启动该服务。

编辑:

这与 COM 对象的单元状态有关。添加了 CoInitializeEx 而不是 CoInitialize。我将线程设置为 MTA。起初它看起来并没有起作用,直到我意识到第一次调用该方法时我们看到线程状态设置为 STA 而不是 MTA!随后的每个调用都是 MTA。如果我在线程为 STA 时调用 System.Management 类之前立即返回,我将不再泄漏内存!

知道为什么第一个是 STA 吗?

最佳答案

RCW 实现中没有 dispose,所以你只能任由 GC 释放你默认创建的 com 对象。但是,您可以尝试使用 Marshal.FinalReleaseComObject完成 COM 对象后,在 RCW 实例上。这将强制包装的 COM 对象上的引用计数为零,并且应该释放。但是,这也会使 RCW 实例无用,因此在调用它的地方要小心。

关于c# - C# COM DLL 中的 ManagementObject 泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8169878/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com