Windows/C++:如何使用未注册的 COM dll

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2466138/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 14:08:42  来源:igfitidea点击:

Windows/C++: how to use a COM dll which is not registered

c++windowsdll

提问by Albert

In our application, we need to use a COM dll (namely msdia100.dll) which was not registered in the system before.

在我们的应用程序中,我们需要使用之前未在系统中注册的 COM dll(即 msdia100.dll)。

Earler, we have just called the DLL by calling its DllRegisterServer via this code:

Earler,我们刚刚通过以下代码调用其 DllRegisterServer 来调用 DLL:

// Register DIA DLL required by Breakpad
std::string diaLibPath = "msdia100";    
HMODULE diaLib = LoadLibrary(diaLibPath.c_str());
if( diaLib == NULL )
{
    errors << "Cannot load DLL " << diaLibPath << endl;
    return;
}

typedef HRESULT ( __stdcall * regServer_t )(void);

regServer_t regServer = (regServer_t)GetProcAddress(diaLib, "DllRegisterServer");
if( regServer == NULL )
{
    errors << "Cannot get method DllRegisterServer from " << diaLibPath << endl;
    FreeLibrary(diaLib);
    return;
}
if( regServer() != S_OK )
{
    errors << "Cannot call DllRegisterServer from " << diaLibPath << endl;
}
FreeLibrary(diaLib);

This doesn't work anymore on Windows 7 (maybe also Vista, didn't tried) because to call this function, it needs Administrator privileges.

这在 Windows 7 上不再起作用(也许还有 Vista,没试过),因为要调用这个函数,它需要管理员权限。

All solutions to this problem I have found where about getting those Admin rights. That is no possible solution for us because our application must also work if the user is not able to get those Admin rights.

这个问题的所有解决方案我都找到了获得这些管理员权限的地方。这对我们来说是不可能的解决方案,因为如果用户无法获得这些管理员权限,我们的应用程序也必须工作。

It is also no solution for us to suddenly need an installer for our application which registeres this DLL.

对于我们来说,突然需要一个注册此 DLL 的应用程序的安装程序也不是解决方案。

So, what possibilities are there? How can I use this DLL without Admin rights? Do I have to recode COM which works without the need to register a DLL first?

那么,有哪些可能性呢?如何在没有管理员权限的情况下使用此 DLL?我是否必须重新编码无需先注册 DLL 即可工作的 COM?



The code where I uses this lib looks like this:

我使用这个库的代码如下所示:

CComPtr<IDiaDataSource> data_source;
if (FAILED(data_source.CoCreateInstance(CLSID_DiaSource))) {
  fprintf(stderr, "CoCreateInstance CLSID_DiaSource failed "
          "(msdia80.dll unregistered?)\n");
  return false;
}

(Btw., for those who are interested: That is part of Google Breakpad.)

(顺便说一句,对于那些感兴趣的人:那是 Google Breakpad 的一部分。)

回答by richb

A simple approach is to use LoadLibrary("msdia100.dll") to load the DLL directly. Then use GetProcAddress("DllGetClassObject"). You can then use IClassFactory to do the equivalent of CoCreateInstance.

一个简单的方法是使用 LoadLibrary("msdia100.dll") 直接加载 DLL。然后使用 GetProcAddress("DllGetClassObject")。然后,您可以使用 IClassFactory 来执行 CoCreateInstance 的等效操作。

So something like the following. (Disclaimer: I haven't compiled this...)

所以像下面这样。(免责声明:我还没有编译这个......)

HRESULT CoCreateDiaDataSource(CComPtr<IDiaDataSource>& data_source)
{
    HMODULE hmodule = LoadLibrary("MSDIA100");
    if (!hmodule)
        return HRESULT_FROM_WIN32(GetLastError()); // library not found

    BOOL (WINAPI*DllGetClassObject)(REFCLSID,REFIID,LPVOID*) =
        (BOOL(WINAPI*)(REFCLSID,REFIID,LPVOID*))GetProcAddress(hmodule, "DllGetClassObject");

    if (!DllGetClassObject) 
        return HRESULT_FROM_WIN32(GetLastError());

    CComPtr<IClassFactory> pClassFactory;
    HRESULT hr = DllGetClassObject(CLSID_DiaSource, IID_IClassFactory, &pClassFactory);
    if (FAILED(hr))
        return hr;

    hr = pClassFactory->CreateInstance(NULL, IID_IDiaDataSource, (void**)&data_source);
    if (FAILED(hr))
        return hr;

    return S_OK;
}

Notes:

笔记:

  1. In the LoadLibrary call, you may have to supply a path. I don't know where MSDIA100.DLL normally lives.

  2. I don't know what MSDIA100.DLL does. Not all COM DLLs will work with this method, particularly if they rely on COM free threaded marshalling and horrible stuff like that. However, most COM DLLs are simple apartment threaded and work fine in my experience.

  1. 在 LoadLibrary 调用中,您可能必须提供路径。我不知道 MSDIA100.DLL 通常在哪里。

  2. 我不知道 MSDIA100.DLL 是做什么的。并非所有 COM DLL 都可以使用这种方法,特别是如果它们依赖于 COM 自由线程编组和诸如此类的可怕东西。但是,大多数 COM DLL 都是简单的单元线程,根据我的经验可以正常工作。

回答by Albert

I think you should try Registration free COM. See: http://msdn.microsoft.com/en-us/library/ms973913.aspx

我认为您应该尝试注册免费 COM。请参阅:http: //msdn.microsoft.com/en-us/library/ms973913.aspx

[edit] In addition, I found back a link to a discussion where it is claimed that just LoadLibrarywill do. Can't confirm that it works from my own experience however. See: http://www.eggheadcafe.com/forumarchives/win32programmerole/Dec2005/post25120399.asp

[编辑] 此外,我还找到了一个讨论的链接,据称该链接LoadLibrary会这样做。但是,无法根据我自己的经验确认它是否有效。参见:http: //www.eggheadcafe.com/forumarchives/win32programmerole/Dec2005/post25120399.asp