Udostępnij przez


Rozwiązywanie problemów z odwołaniami COM

COM to technologia systemu Windows służąca do definiowania i obsługi obiektów i typów, które mogą być używane przez różne aplikacje klienckie na platformie Windows. Zobacz Model obiektów składników (COM).

Możesz odwołać się do składnika COM w projekcie platformy .NET, w takim przypadku musi on być projekowany w zestawie zarządzanym, nazywanym podstawowym zestawem międzyoperacyjnym lub PIA. Zgromadzenie międzyoperacyjne zawiera typy zarządzane, które odpowiadają typom obiektów COM (reprezentowanym przez interfejsy opisane w bibliotekach typów) i przesyła wywołania API do modelu COM. Aby uzyskać ogólne informacje o Interop COM, zobacz COM Interop.

Można odwoływać się do składników COM w projektach .NET Framework lub w projektach .NET Core (w tym .NET 5 lub nowszych). Program Visual Studio udostępnia sposoby dodawania odwołań do obiektów COM. Na przykład składnik COM, który jest kontrolką interfejsu użytkownika systemu Windows (kontrolką ActiveX) może być wyświetlany w Przyborniku, a po przeciągnięciu i upuszczaniu go do formularza systemu Windows lub formularza Windows Presentation Foundation (WPF) jest dodawany jako COMReference w pliku projektu.

Odwołania COM można również dodać bezpośrednio w Eksploratorze rozwiązań. Kliknij prawym przyciskiem myszy pozycję Zależności, a następnie wybierz pozycję Dodaj odwołanie COM.

Program MSBuild może tworzyć zespoły opakowujące dla odwołań COM. Podczas kompilacji ResolveComReference zadanie jest uruchamiane i używa rejestru systemowego do lokalizowania wszystkich przywoływanych obiektów COM, generuje opakowania przez wywołanie tlbimp.exe, i zapisuje je na dysku w folderze projektu.

Następnie w tym artykule przedstawiono różne sposoby odwoływania się do składników COM oraz niektóre z możliwych błędów, które mogą wystąpić podczas korzystania z każdej metody.

COMReference

Typ COMReference elementu odwołuje się do składnika COM przy użyciu rejestru systemowego. Identyfikator GUID i wersja to klucze podstawowe używane do lokalizowania składnika.

  <ItemGroup>
    <COMReference Include="MyComLibrary">
      <Guid>{01234567-89AB-CDEF-0123-456789ABCDEF}</Guid>
      <VersionMajor>1</VersionMajor>
      <VersionMinor>0</VersionMinor>
      <Lcid>0</Lcid>
      <WrapperTool>tlbimp</WrapperTool>
    </COMReference>
  </ItemGroup>

</Project>

Ponieważ używany jest rejestr systemowy, składniki muszą być zarejestrowane na maszynie kompilacji. Działa to najlepiej, jeśli kompilujesz tylko z programu Visual Studio na komputerze lokalnym, na którym kontrolujesz zainstalowane elementy i możesz mieć uprawnienia administratora do zapisu w rejestrze. Jednak w przypadku kompilacji na serwerze lub w kontenerze, takim jak w scenariuszach ciągłej integracji/ciągłego wdrażania, należy upewnić się, że odpowiednie produkty są zainstalowane na serwerze kompilacji i zmiany na serwerze, takie jak instalowanie nowej wersji pakietu Office lub odinstalowywanie pakietu oprogramowania, powodują ryzyko przerwania kompilacji. Co gorsza, nie przerywanie kompilacji, ale odwoływanie się do innej wersji tego samego składnika niż ta, dla której został napisany kod.

Innym problemem jest składnik COM uzyskany z rejestru może mieć niewielkie różnice w składniku, dla którego został napisany kod. Zależy to od wydawcy składnika i tego, czy zainstalowano jakiekolwiek aktualizacje, które go zmodyfikowały, bez zmieniania numerów wersji. Ten typ niezgodności nie spowoduje wystąpienia błędu kompilacji, ale może spowodować wystąpienie błędu w czasie wykonywania, jeśli zmiany były wystarczająco znaczące, aby przerwać działanie aplikacji.

Ogólne informacje o tym, jak składniki COM są reprezentowane w rejestrze, można znaleźć w temacie Rejestrowanie aplikacji COM.

COMFileReference

Typ COMFileReference elementu odwołuje się do składników COM według ścieżki pliku. Rejestr nie jest używany w czasie kompilacji. Jest to ważna alternatywa, COMReference jeśli nie chcesz, aby proces kompilacji był zależny od rejestru systemowego. Jeśli używasz programu COMFileReference, nie musisz martwić się o sposób rejestrowania składników COM wymaganych przez aplikację, dopóki aplikacja nie zostanie zainstalowana i uruchomiona na komputerze użytkownika, co jest dużą korzyścią, ponieważ proces kompilacji może działać bez podniesionych uprawnień wymaganych do zapisu w rejestrze.

<ItemGroup>
  <COMFileReference Include="Controls\MyCom32.dll" />
</ItemGroup>

Aby uniknąć całkowitego zapisywania w rejestrze, należy użyć modelu COM bez rejestru z manifestem.

Nadal może występować problem ze składnikiem, który różni się od tego, z którym pracowałeś podczas kodowania, jeśli ścieżka, do której się odwołujesz, nie jest pod twoją kontrolą. Jeśli pakiet oprogramowania aktualizuje składnik na maszynie kompilacji, bez aktualizowania informacji o wersji, może się okazać, że ładujesz inny składnik z potencjalną niezgodnością. Aby tego uniknąć, można użyć buforowanej, znanej wersji plików binarnych COM i odwołać się tylko do nich.

Reference

Jest to zalecany sposób odwoływania się do składników COM w nowszych wersjach platformy .NET. Zestawy opakowujące są wstępnie generowane, a nie budowane w każdej sesji kompilacji, a rezultaty są bezpośrednio używane jako zarządzane zestawy.

Czasami zestawy otok (PIA) są dystrybuowane przez dostawcę składników COM. Jeśli tak jest, możesz odwoływać się bezpośrednio do nich jako zarządzane zestawy. Nie różni się to od odwoływania się do żadnego innego zestawu .NET, z tą różnicą, że w czasie wykonywania istnieje zależność od instalowanego i zarejestrowanego składnika COM.

Aby samodzielnie utworzyć zestawy otoki dla składników COM, których chcesz użyć, użyj tlbimp.exe lub aximp.exe dla kontrolek ActiveX.

Korzystając z tej metody, można uniknąć wymagania podwyższonego poziomu uprawnień do zapisu w rejestrze systemowym w czasie kompilacji. Jeśli generujesz własne zestawy okrywek i przechowujesz je w miejscu, które kontrolujesz, na przykład w pakiecie NuGet lub w folderze dostępnym dla rozwiązania, możesz zabezpieczyć się przed zmianami, które wykraczają poza twoją kontrolę.

Bitness

Jeśli projekt odwołuje się do 32-bitowych składników COM, musisz skompilować przy użyciu programu MSBuild.exe lub Visual Studio, a nie dotnet build. Dzieje się tak, ponieważ dotnet build uruchamia 64-bitową wersję programu MSBuild, która nie jest w stanie pracować ze składnikami COM 32-bitowych.

Składniki COM były kiedyś kompilowane do 32-bitowych plików binarnych. Później, kiedy wprowadzono 64-bitową technologię, można było skompilować składnik COM zarówno do 32-bitowych, jak i 64-bitowych plików binarnych. Ten sam składnik jest często dostępny zarówno w 32-bitowych, jak i 64-bitowych plikach binarnych. W takich przypadkach identyfikator GUID lub CLSID, który identyfikuje unikatowy składnik, jest taki sam zarówno dla 32-bitowych, jak i 64-bitowych plików binarnych, ale sam rejestr jest podzielony na sekcje 32-bitowe i 64-bitowe.

Błędy mogą wystąpić, jeśli projekty nie są prawidłowo skonfigurowane dla odwołania się do poprawnej architektury bitowej potrzebnego składnika COM. Jeśli składnik COM jest dostępny tylko jako 32-bitowy plik binarny, aplikacja może jej używać tylko wtedy, gdy działa jako proces 32-bitowy. Jeśli zestaw .NET został skompilowany jako zestaw 32-bitowy, może odwoływać się do 32-bitowych składników COM. Jeśli jest on zbudowany jako zestaw 64-bitowy, może odwoływać się do 64-bitowych składników COM. Jeśli jednak zestaw jest zbudowany jako Any CPU, należy zachować ostrożność podczas odwoływania się do składników COM, które nie mają odpowiednika Any CPU. Może być lepiej stworzyć aplikację zarówno w wersjach 32-bitowych, jak i 64-bitowych, które odwołują się do odpowiednich składników COM, przy założeniu, że składniki COM są dostępne w obu wersjach bitowych.

Istnieje inna właściwość kompilacji Prefer32bit (również zaznaczenie w programie Visual Studio), która powoduje, że asemblaż skompilowany jako Any CPU zawsze działa jako 32-bitowy na 64-bitowej maszynie. Będzie to działać z 32-bitowymi składnikami COM, ale może to być mylące dla każdego, kto korzysta z projektu później.

Możesz używać atrybutów Condition na właściwości PlatformTarget do odwołania się do dwóch różnych form bitowości jednego składnika COM. Na przykład

<ItemGroup Condition="'$(PlatformTarget)' == 'x86'">
  <COMFileReference Include="Controls\MyCom32.dll" />
</ItemGroup>
<ItemGroup Condition="'$(PlatformTarget)' == 'x64'">
  <COMFileReference Include="Controls\MyCom64.dll" />
</ItemGroup>

Podczas kompilacji dla architektury x86 odwołujesz się do 32-bitowej biblioteki DLL COM, ale podczas kompilacji dla wersji x64 odwołujesz się do wersji 64-bitowej.

Jak program MSBuild rozpoznaje odwołania COM

W tym miejscu opisano podstawowy algorytm, w tym sekwencję kroków rozwiązywania odwołania, uruchamianie plików wykonywalnych (na przykład tlbimp.exe) oraz wywołania interfejsu API systemu Windows.

W standardowym procesie ResolveComReference kompilacji zestawu .NET SDK zadanie jest wywoływane w typowych plikach docelowych w obiekcie docelowym o nazwie ResolveComReferences. Obiekt docelowy jest wywoływany raz na projekt i przetwarza wszystkie odwołania COM, zarówno COMReference, jak i COMFileReference. Aby uzyskać więcej informacji, zobacz zadanie ResolveComReference.

Zadanie przechodzi przez drzewo zależności, próbując rozwiązać wszystkie odwołania. Większość błędów z poszczególnymi odwołaniami nie jest śmiertelna; Program MSBuild nadal próbuje rozwiązać inne odwołania. Niektóre błędy są krytyczne, jeśli wpłyną one na wszystkie odwołania w równym stopniu.

Jeśli składnik COM znajduje się w rejestrze lub w systemie plików, program MSBuild zwykle próbuje ponownie użyć wcześniej utworzonych zestawów otok, i w razie potrzeby generuje otoki. W przypadku ustawień domyślnych zestawy otoki są generowane przez uruchomienie tlbimp.exe i umieszczenie ich w folderze w folderze projektu. Element tlbimp.exe jest zawarty w zestawie SDK .NET Framework.

Ustawiając właściwości, można dostosować argumenty i ustawienia podane do ResolveComReference zadania. Można skonfigurować, czy używać wcześniej utworzonych zestawów otok, które są albo wcześniej zbudowane, albo znajdują się w pamięci podręcznej (jeśli jest używana opcja pamięci podręcznej). Możesz dostosować folder wyjściowy, ustawiając opcję EmbedInteropTypes na True. Takie podejście osadza przewidywane typy w tworzonej bibliotece lub pliku wykonywalnym, a nie w oddzielnym zestawie otoki.

Narzędzia diagnostyczne

Aby zdiagnozować konkretny błąd kompilacji, należy wyświetlić szczegółowe dane wejściowe zadania, które zakończyło się niepowodzeniem ResolveComReference .

Szczegółowa diagnostyka

Możesz ustawić szczegółową diagnostykę przy użyciu -v:diag przełącznika w wierszu polecenia MSBuild lub w środowisku IDE programu Visual Studio.

W panelu Narzędzia>Opcje, rozwiń sekcję Wszystkie ustawienia>Projekty i rozwiązania>Kompilacja i uruchamianie, a następnie ustaw opcje szczegółowości kompilacji projektu MSBuild oraz szczegółowości pliku dziennika kompilacji MSBuild na Diagnostyczny.

W oknie dialogowym Opcje Narzędzi, rozwiń sekcję Projekty i rozwiązaniaKompilacja i uruchamianie, a następnie ustaw opcje szczegółowość danych wyjściowych kompilacji projektu MSBuild oraz szczegółowość pliku dziennika kompilacji MSBuild na Diagnostyka.

Wyświetlanie dzienników binarnych

Wygeneruj dziennik binarny (-bl przełącznik w wierszu polecenia MSBuild) i użyj przeglądarki dzienników ze strukturą, która udostępnia interfejs użytkownika, który znacznie ułatwia wyświetlanie szczegółowych kroków w kompilacji, wartości parametrów wejściowych zadania itd.

Oto widok obiektu docelowego w podglądzie dzienników ResolveComReferences strukturalnych. Możesz sprawdzić parametry i dane wyjściowe, które reprezentują rozpoznane ścieżki referencyjne i zestawy opakowań. W tym przykładzie lokalizacja zestawu powłoki jest rozwijana, aby pokazać lokalizację i nazwę pliku wygenerowanego zestawu powłoki.

Zrzut ekranu przeglądarki strukturalnych dzienników MSBuild, patrząc na cel ResolveComReferences.

Po zidentyfikowaniu nazwy składnika, identyfikatora GUID i wersji, która wywołała błąd, możesz przejrzeć wszystkie właściwości i elementy dostarczone do ResolveComReference zadania i zebrać informacje o tym składniku z rejestru systemowego. Możesz użyć edytora regedit.exerejestru , ale edytowanie rejestru wymaga uprawnień administratora.

RegEdit

Zapoznaj się z lokalizacjami rejestru składników COM, zarówno 32-bitowymi, jak i 64-bitowymi lokalizacjami rejestru. Identyfikatory GUID, które identyfikują typ klasy COM, nazywane są identyfikatorami klasy (CLSID) i są przechowywane w rejestrze pod kluczem CLSID. Na 64-bitowej maszynie komponenty 64-bitowe są rejestrowane pod HKEY_LOCAL_MACHINE\Software\Classes\CLSID\, a komponenty 32-bitowe pod HKEY_LOCAL_MACHINE\Software\WOW6432Node\Classes\CLSID\. Na maszynie 32-bitowej składniki 32-bitowe są rejestrowane w obszarze HKEY_LOCAL_MACHINE\Software\Classes\CLSID\. Składnik zazwyczaj można znaleźć, wyszukując jego nazwę lub identyfikator GUID w edytorze rejestru. Jeśli rejestracja składnika znajduje się w gałęzi rejestru, tak jak w przypadku składników programu Visual Studio, może być konieczne zlokalizowanie i otwarcie gałęzi. Zobacz Edytowanie rejestru dla wystąpienia programu Visual Studio.

OleView

Być może bardziej preferujesz użyć oleview.exe do zbadania pojedynczego typu COM oraz aby uzyskać informacje, takie jak biblioteka typów i jakie implementuje interfejsy. Obiekt OLEView nie wymaga uprawnień administratora i jest łatwiejszy w użyciu niż regedit.exe.

Procmon

Process Monitor procmon służy do monitorowania aplikacji korzystających z modelu COM w czasie wykonywania oraz do monitorowania zmian rejestru.

Typowe problemy

W tej sekcji opisano typowe problemy, które mogą wystąpić podczas korzystania z odwołań COM.

Problemy z rejestracją

Czy składnik jest zarejestrowany na maszynie kompilacji? Jeśli jeden z własnych składników nie jest zarejestrowany, można go zarejestrować ręcznie przy użyciu narzędzia wiersza polecenia . regsvr32.exe (To polecenie wymaga uprawnień z podwyższonym poziomem uprawnień na maszynie). Jeśli składniki są częścią pakietu oprogramowania, takiego jak pakiet Office, upewnij się, że zainstalowano odpowiednią wersję produktu, która dystrybuuje i rejestruje składnik. Spróbuj naprawić lub ponownie zainstalować produkt lub pakiet oprogramowania.

Potwierdź właściwości obiektu COMReference. Czy nazwa, identyfikator GUID i wersje są poprawne, tak samo jak w rejestrze? Sprawdź pisownię, błędy pisowni, niezgodność wersji lub inne niespójności.

Rozważ, czy składnik jest składnikiem 32-bitowym lub 64-bitowym, jeśli obie wersje są dostępne. Jeśli kierujesz się na ARM64, zobacz Kompilowanie plików binarnych Arm64X.

W programie COMFileReferenceodwołujesz się do składnika COM według jego lokalizacji pliku. Sprawdź ścieżkę do pliku i upewnij się, że jest ona poprawna, uwzględniając bieżący katalog roboczy, jeśli jest to ścieżka względna.

Problemy z biblioteką typów

Biblioteka typów jest wymagana do wygenerowania zestawu międzyoperacyjnego. Biblioteki typów można osadzać w plikach binarnych, takich jak biblioteka DLL, lub mogą znajdować się w osobnym pliku , pliku TLB (.tlb rozszerzenie).

Jeśli nie możesz znaleźć biblioteki typów dla składnika COM, często można je wygenerować. Zwykle nie trzeba generować biblioteki typów. Należy go zainstalować za pomocą składnika dystrybuowanego przez dostawcę składników. Typowe rozwiązania obejmują instalowanie, uaktualnianie lub ponowne instalowanie pakietu oprogramowania.

Istnieją sposoby generowania biblioteki typów na podstawie pliku binarnego COM w rzadkich przypadkach, w których jest to konieczne. Na przykład możesz otworzyć plik binarny w edytorze zasobów programu Visual Studio lub edytorze zasobów innej firmy, zlokalizować zasób biblioteki typów, wyeksportować go i użyć polecenia Zapisz plik jako , aby zapisać go jako plik tekstowy z tlb rozszerzeniem .

Nie można skanować zależności

MSB3304 występuje, jeśli wystąpił problem podczas skanowania zależności odwołania. Zadanie ResolveComReference próbuje przejść cały graf zależności, więc jakiekolwiek problemy z identyfikacją zależności powodują ten błąd. Podany komunikat o błędzie zależy od konkretnego problemu. Jeśli błąd pochodzi z tlbimp.exe, możesz również spróbować uruchomić tlbimp.exe w wierszu polecenia, aby uzyskać więcej szczegółów na temat problemu.

Problemy z generowaniem asembli opakowań

Program MSBuild próbuje znaleźć istniejące zestawy otoki w pamięci podręcznej z poprzedniego uruchomienia, jeśli ta opcja została określona, lub ponownie użyć wcześniej wygenerowanych zestawów otoki. W razie potrzeby generuje powłokę. Narzędzie tlbimp.exe służy do tworzenia zestawów opakowań. Zostanie utworzony folder zawierający zestawy warstwy. Domyślnie folder jest tworzony w folderze projektu, ale jest on ustawiany przez WrapperAssemblyLocation parametr ResolveComReference zadania. Jeśli ten proces zakończy się niepowodzeniem, zostanie podany błąd MSB3290 lub MSB3283 wraz z informacjami o błędzie z systemu operacyjnego. Zobacz sugerowane wskazówki dotyczące rozwiązywania tych konkretnych błędów.

Nieprawidłowa składnia COMReference lub COMFileReference

Jeśli program MSBuild nie może przekonwertować metadanych z pliku projektu, zostanie wyświetlony błąd MSB3095. Jeśli tak się dzieje, sprawdź pisownię lub inne błędy w odwołaniach COM (lub wszelkie właściwości używane w odwołaniach COM) w pliku projektu. Sprawdź podelementy COMReference elementu względem oczekiwanych metadanych zgodnie z opisem w artykule MSBuild typowe elementy projektu pod kątem błędów składniowych lub brakujących metadanych.

Błędy IO pliku

Zadanie ResolveComReference odczytuje i zapisuje w systemie plików, co oznacza, że może zakończyć się niepowodzeniem z powodu błędu IO systemu, który jest przechwycony przez program MSBuild i zgłaszany jako ogólny kod błędu MSBuild. Poszukaj szczegółów błędu w komunikatach z systemu operacyjnego. Sprawdź pisownię i poprawność wszystkich ścieżek oraz ścieżki skonstruowane we właściwościach programu MSBuild, sprawdź właściwości, aby upewnić się, że zostały zdefiniowane i mają oczekiwane wartości.

Warnings

Niektóre problemy z rozwiązywaniem odwołania COM są zgłaszane jako ostrzeżenia. Może pojawić się MSB3305, które jest generowane, gdy wywołanie funkcji bazowej zgłasza kwestię niekrytyczną, taką jak potencjalna kwestia konwersji typu. Takie ostrzeżenia można pominąć, ustawiając właściwość ResolveComReferenceSilent MSBuild na true. Nie zalecamy trwałego używania tego ustawienia, ale może być przydatne, jeśli rozumiesz problem i chcesz tymczasowo pominąć powiadomienie. Możesz również użyć standardowych technik, aby pominąć ostrzeżenia. Zobacz Pomijanie ostrzeżeń dotyczących kompilacji.

Natywne wywołania systemu Windows

Element ResolveComReference może wywoływać niektóre funkcje interfejsu API systemu Windows. Błędy z tych wywołań interfejsu API są przekazywane do danych wyjściowych kompilacji. Są one wymienione tutaj dla odniesienia.

Nazwa funkcji Description
FreeLibrary Zwalnia załadowany moduł biblioteki dynamicznej (DLL).
GetModuleFileName Pobiera w pełni kwalifikowaną ścieżkę pliku zawierającego określony moduł.
LoadLibrary Ładuje określony moduł do przestrzeni adresowej procesu wywołującego.
LoadRegTypeLib Używa informacji rejestru do ładowania biblioteki typów.
QueryPathOfRegTypeLib Pobiera ścieżkę zarejestrowanej biblioteki typów.