2012-02-09 12 views
5

W jednym z moich projektów mam aplikację C#, która używa biblioteki DLL w C++. Obecnie na komputerze klienta rejestrujemy DLL C++ w komponentach COM w rejestrze, abyśmy użyli ich w języku C#.Jak korzystać z darmowej rejestracji Dll COM w kropce netto

Uczę się na internecie, że istnieje rozwiązanie Reg bezpłatny dostępna w firmie Microsoft w linku http://msdn.microsoft.com/en-us/library/ms973913.aspx

Ale po przeczytaniu nie dostać dużo pojęcia, bo moja architektura aplikacji różni się następująco

  1. I mam 2 biblioteki C++ LET SAY CPForms.dll i Rules.dll.
  2. Rule.dll to m.in. wewnątrz CPForms.dll
  3. I 1 C# dll powiedzmy ConsumeForm.dll który korzysta CPForms.DLL
  4. mam innego C# Exe który korzysta ConsumeForm.dll

Mój klient otwiera tylko C# Exe, który z kolei wywołuje ConsumeForm.dll, który wywołuje CPForms.dll, który pokazuje C++ formularza (UI), istnieje przycisk sprawdzania poprawności, gdy użytkownik kliknie ten przycisk wewnętrznie przy użyciu C++ Rules.dll. Obecnie rejestruję oba dll C++ w rejestrze.

Teraz klient chce, aby plik Rule.dll był nazywany instalacją RegFree, ponieważ Rule.dll często się zmienia, a klient nie chce wyrejestrowywać się i rejestrować ponownie za pomocą konta administratora.

Inne niż ten klient jest OK z rejestracją CPForms.dll.

Moje pytanie brzmi: jak możemy wygenerować plik manifestu? A jak to będzie działać w moim scenariuszu?

+0

Artykuł zawiera wiele szczegółów, czego więcej potrzebujesz? Co próbujesz? Jakie błędy dostałeś? – Polyfun

+0

Zgaduję, że powinieneś wiedzieć, czy plik manifestu jest dołączony do .exe lub jednej z bibliotek DLL - zgaduję, że .exe, ponieważ konfiguruje ten proces. Poza tym, czy składnia XML nie jest czysta? – Rup

+1

Czy to wymaga rejestracji? Tak długo, jak rules.dll jest instalowany w tym samym miejscu (co i tak wymagałoby uprawnień administratora, prawda?) I implementuje te same obiekty i interfejsy, z którymi zbudowany jest CPForms.dll, dlaczego musi być wyrejestrowywany i ponownie rejestrowany co czas? (Pytanie bez rejestracji jest interesujące samo w sobie.) – Rup

Odpowiedz

8

Uwaga: rozważyć stosowanie manifestu jako odpowiedź tutaj dla lepszego rozwiązania:

Jak to zrobić bez oczywistego

COM rejestru jest usługa która jest opti onal dla serwera inproc.

Jeszcze raz: Nie musisz rejestrować obiektu, aby go utworzyć. Jeśli nie jest zarejestrowany, (a nie w manifeście), nie można go utworzyć przy użyciu CoCreateInstance, ponieważ rejestr (lub manifest) jest tym, co mówi CoCreateInstance, którą bibliotekę DLL załadować.

Można jednak utworzyć go za pomocą LoadLibrary, GetProcAddress, DllGetClassObject i IClassFactory::CreateInstance.

(Uwaga: nie dostaniesz żadnych usług COM + i nie możesz tworzyć obiektów poza procesem w ten sposób lub obiektów, których model wątku nie jest kompatybilny z tworzonym wątkiem. Jeśli nie poprosisz o COM zrób to dla ciebie, te rzeczy stają się twoim problemem).

Usługa, którą zapewnia CoCreateInstance, polega na zlokalizowaniu poprawnej biblioteki DLL dla wywołania funkcji LoadLibrary i po prostu wywołaj inne funkcje. (Sprawdzenie, czy modele wątków są zgodne, tworzenie na odpowiednim węźle i używanie CoMarshalInterthreadInterfaceInStream/CoUnmarshalInterfaceAndReleaseStream do sterowania interfejsem, jeśli tak nie jest. To brzmi jak dużo pracy, ale jeśli masz tylko jednego terapeuta STA, możesz prawie zignorować wszystkie kwestie.)

coś jak to powinno załatwić sprawę:

// 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; 
} 

Uwaga: to pozwoli na utworzenie obiektu. Jednak jeśli obiekt, który wywołujesz, sam w sobie jest niezawodny, nie będzie działał poprawnie. W szczególności wiele implementacji polega na bibliotece typów. Jeśli tak jest w przypadku konkretnego obiektu, to nie powiedzie się GetIDsOfNames i GetTypeInfo i nie będzie można używać metod związanych z opóźnieniem z obiektem. Obejmuje to używanie dynamic w języku C# i języków dynamicznych, takich jak Python.

Inne metody, takie jak metody podwójnego interfejsu i interfejsy, które nie dziedziczą z IDispatch, mogą działać, nawet jeśli metody IDispatch tego nie robią. Podsumowując: Aby wolny od rejestracji COM działał, tworzony obiekt nie może opierać się na własnej rejestracji.

+0

Podążyłem za tym w mojej sprawie (AutoItX.dll). Obiekt rzeczywiście został stworzony. Ale nie mogę go wywołać nie poprzez interop lib, nie poprzez odbicie. Kiedy rejestruję bibliotekę C++, wszystko zaczyna działać. –

+0

@DzmitryLahoda, nie można zarejestrować pliku C++ * .lib. Zakładam, że masz na myśli, że zarejestrowałeś dll COM? Jak się zarejestrowałeś? – Ben

+0

Przepraszamy za wprowadzającą w błąd lib. Mówię o dll. Kiedy robię polecenie "regsvr32 AutoItX3.dll/u", nie mogę wywołać żadnej metody dla tworzonego obiektu. Nie nadaje się do użytku. Kiedy robię "regsvr32 AutoItX3.dll" wszystko działa. Ale w tym przypadku nie potrzebuję kodu pod warunkiem, że kod nie jest odpowiedzią "Jak korzystać z bezpłatnej rejestracji w katalogu COM w dot net" dla w pełni prawidłowego obiektu COM. –

2

Dla tych, którzy przeskoczą na to pytanie w poszukiwaniu Registration free COM dll in dot net, udało mi się użyć obiektu COM AutoItX w Reg Free sposób z C# w tej odpowiedzi https://stackoverflow.com/a/19996424/173073. Tworzenie i używanie innych obiektów Reg Free byłoby podobne.

Powiązane problemy