Как использовать Регистрация бесплатных COM DLL в Dot Net - PullRequest
5 голосов
/ 09 февраля 2012

В одном из моих проектов у меня есть приложение c #, которое использует C ++ DLL.В настоящее время на клиентском ПК мы регистрируем C ++ DLLS в COM-компонентах реестра, чтобы использовать их в C #.

Я узнаю в NET, что есть решение Reg Free, доступное в Microsoft по ссылке http://msdn.microsoft.com/en-us/library/ms973913.aspx

Но после прочтения я не получил много подсказок, потому что моя архитектура приложения отличается от следующей:

  1. У меня 2 C ++ dll LET SAY CPForms.dll и Rules.dll.
  2. Rule.dll включен в CPForms.dll
  3. У меня есть 1 C # dll, скажем, ConsumeForm.dll, использующий CPForms.DLL
  4. У меня есть другой C # Exe, которыйиспользуя ConsumeForm.dll

Мой клиент открывает только C # Exe, который, в свою очередь, вызывает ConsumeForm.dll, которая в дальнейшем вызывает CPForms.dll, которая показывает форму C ++ (UI), при нажатии кнопки есть кнопка проверки.нажмите эту кнопку внутри, используя C ++ Rules.dll.В настоящее время я регистрирую обе библиотеки C ++ в реестре.

Теперь клиент хочет, чтобы Rule.dll упоминался как установка RegFree, поскольку Rule.dll часто меняется, и клиент не хочет отменять регистрацию и регистрироваться снова и снова.используя учетную запись администратора.

Кроме того, с клиентом все в порядке с регистрацией CPForms.dll.

Мой вопрос: как мы можем сгенерировать файл манифеста?И как это будет работать в моем сценарии?

Ответы [ 2 ]

9 голосов
/ 10 февраля 2012

Примечание: Рассмотрите возможность использования манифеста, как в ответе здесь, для лучшего решения:

Как это сделать без манифеста

Реестр COM - это служба , которая необязательна для сервера inproc.

Еще раз: Вам не нужно регистрировать объект для его создания. Если он не зарегистрирован, (и не в манифесте) вы не можете создать его с помощью CoCreateInstance, поскольку реестр (или манифест) - это то, что CoCreateInstance сообщает, какую DLL загрузить.

Однако вы можете создать его с помощью LoadLibrary, GetProcAddress, DllGetClassObject и IClassFactory::CreateInstance.

(Обратите внимание, что вы не получите никаких сервисов COM + и не сможете таким образом создавать объекты вне процесса или объекты, чья модель потоков не совместима с создаваемым потоком. Если вы не попросите COM сделать это для тебя эти вещи становятся твоей проблемой).

Служба, предоставляемая CoCreateInstance, заключается в том, чтобы найти правильную DLL для вызова LoadLibrary и просто вызвать другие функции для вас. (И проверка совместимости моделей потоков, создание в соответствующем потоке и использование CoMarshalInterthreadInterfaceInStream / CoUnmarshalInterfaceAndReleaseStream для маршалинга интерфейса, если они не являются. Это звучит как большая работа, но если у вас есть только один STA therad, вы можете в значительной степени игнорировать все вопросы.)

Нечто подобное должно сработать:

// Really you should break this up int GetClassFactoryFromDLL, then reuse the class factory.
// But this is all from memory...
// Load CLSID_MyID, from DLL pszMyDllPath
typedef HRESULT __stdcall (*_PFNDLLGETCLASSOBJECT)(
  __in   REFCLSID rclsid,
  __in   REFIID riid,
  __out  LPVOID *ppv
) PFNDLLGETCLASSOBJECT;

HRESULT CreateInstanceFromDll(LPCTSTR pszMyDllPath, CLSID clsidMyClass, IUknown** ppunkRet)
{
    // Handle bad callers
    *ppunkRet = NULL;
    HANDLE hDLL = LoadLibrary(pszMyDllPath);
    if(hDLL == NULL)
    {
        // Failed to load
        return HRESULT_FROM_NTSTATUS(GetLastError());
    }
    PFNDLLGETCLASSOBJECT pfnDllGetClassObject = GetProcAddress(hDLL);
    if(pfnDllGetClassObject == NULL)
    {
        // Not a COM dll
        HRESULT hrRet = HRESULT_FROM_NTSTATUS(GetLastError());
        FreeLibrary(hDLL);hDLL = NULL;
        return hrRet;
    }
    IClassFactory* pClassFactory = NULL;
    HRESULT hr = pfnDllGetClassObject(clsidMyClass, IID_IClassFactory, &pClassFactory);
    if(FAILED(hr)){
        FreeLibrary(hDLL);hDLL = NULL;
        return hr;
    }
    hr = pClassFactory->CreateInstance(NULL, IID_IUnknown, &ppunkRet);
    pClassFactory->Release();
    if(FAILED(hr))
    {
        *ppunkRet = NULL;
        FreeLibrary(hDLL);
        return hr;
    }
    return hr;
}

Примечание: Это позволит вам создать объект. Однако, если вызываемый вами объект сам по себе зависит от регистрации, он не будет работать правильно.

В частности, многие реализации IDispatch полагаются на библиотеку типов. Если это относится к конкретному объекту, то GetIDsOfNames и GetTypeInfo завершатся ошибкой, и вы не сможете использовать методы с поздним связыванием с объектом. Это включает использование dynamic в C # и динамические языки, такие как Python.

Другие методы, такие как методы двойного интерфейса и интерфейсы, не наследуемые от IDispatch, могут хорошо работать, даже если методы IDispatch не работают.

Итог: чтобы без регистрации COM работал, объект, который создается, не должен полагаться на свою собственную регистрацию.

2 голосов
/ 21 ноября 2013

Для тех, кто будет переходить к этому вопросу в поисках Registration free COM dll in dot net, я смог использовать COM-объект AutoItX в Reg Free способом из C # в этом ответе https://stackoverflow.com/a/19996424/173073. Создание и использование других объектов Reg Free будетпохоже.

...