Delen via


Problemen met COM-verwijzingen oplossen

COM is een Windows-technologie voor het definiëren en gebruiken van objecten en typen die kunnen worden gebruikt door diverse client-apps op het Windows-platform. Zie COM (Component Object Model).

Mogelijk verwijst u naar een COM-onderdeel in een .NET-project. In dat geval moet het worden ingepast in een beheerde assembly, ook wel een primaire interop-assembly genoemd. De interoperabiliteitsassembly bevat beheerde typen die overeenkomen met COM-objecttypen (zoals vertegenwoordigd door interfaces die worden beschreven in typebibliotheken) en API-aanroepen doorstuurt naar COM. Zie COM Interop voor algemene informatie over COM Interop.

U kunt verwijzen naar COM-onderdelen in .NET Framework-projecten of in .NET Core-projecten (inclusief .NET 5 of hoger). Visual Studio biedt manieren om verwijzingen toe te voegen aan COM-objecten. Een COM-onderdeel dat een Windows UI-besturingselement (een ActiveX-besturingselement) is, kan bijvoorbeeld worden weergegeven in de werkset en wanneer u het naar uw Windows-formulier of een WPF-formulier (Windows Presentation Foundation) sleept, wordt het toegevoegd als een COMReference in het projectbestand.

U kunt com-verwijzingen ook rechtstreeks toevoegen in Solution Explorer. Klik met de rechtermuisknop op Afhankelijkheden en selecteer COM-verwijzing toevoegen.

MSBuild kan de wrapper-assembly's maken voor COM-verwijzingen. Tijdens een build wordt de ResolveComReference taak uitgevoerd en wordt het systeemregister gebruikt om eventuele COM-objecten te vinden waarnaar wordt verwezen, wrappers te genereren door ze aan te roepen tlbimp.exeen naar de schijf onder de projectmap te schrijven.

Vervolgens ziet u in dit artikel verschillende manieren om te verwijzen naar COM-onderdelen en enkele van de mogelijke fouten die kunnen optreden bij het gebruik van elke methode.

COMReference

Het COMReference itemtype verwijst naar het COM-onderdeel met behulp van het systeemregister. De GUID en versie zijn de primaire sleutels die worden gebruikt om het onderdeel te vinden.

  <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>

Omdat het systeemregister wordt gebruikt, moeten onderdelen worden geregistreerd op de buildcomputer. Dit werkt het beste als u alleen bouwt vanuit Visual Studio op uw lokale computer waar u bepaalt wat er is geïnstalleerd en u mogelijk beheerdersrechten hebt om naar het register te schrijven. Wanneer u echter bouwt op een server of in een container, zoals in CI/CD-scenario's, moet u ervoor zorgen dat de juiste producten op de buildserver worden geïnstalleerd en dat wijzigingen in de server, zoals het installeren van een nieuwe versie van Office, of het verwijderen van een softwarepakket, het risico veroorzaken dat de build wordt onderbroken. Of erger, de build wordt niet onderbroken, maar verwijst naar een andere versie van hetzelfde onderdeel dan de versie waarvoor uw code is geschreven.

Het andere probleem is dat het COM-onderdeel dat u uit het register krijgt, mogelijk kleine verschillen heeft met het onderdeel waarvoor uw code is geschreven. Het is afhankelijk van de uitgever van het onderdeel en of er updates zijn geïnstalleerd die het hebben gewijzigd, zonder de versienummers te wijzigen. Dit type incompatibiliteit zou geen buildfout opleveren, maar kan tijdens runtime een fout opleveren als de wijzigingen significant genoeg waren om iets te verbreken waarvan uw app afhankelijk is.

Algemene informatie over de weergave van COM-onderdelen in het register vindt u in COM-toepassingen registreren.

COMFileReference

Het COMFileReference itemtype verwijst naar COM-onderdelen per bestandspad. Het register wordt niet gebruikt tijdens de build. Dit is een belangrijk alternatief als COMReference u niet wilt dat uw buildproces afhankelijk is van het systeemregister. Als u gebruikt COMFileReference, hoeft u zich geen zorgen te maken over het registreren van de COM-onderdelen die uw app nodig heeft totdat de toepassing is geïnstalleerd en uitgevoerd op de computer van de gebruiker. Dit is een groot voordeel omdat uw buildproces mogelijk wordt uitgevoerd zonder de verhoogde bevoegdheden die nodig zijn om naar het register te schrijven.

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

Als u het schrijven naar het register volledig wilt voorkomen, gebruikt u reg-free COM met een manifest.

Er kan nog steeds een probleem zijn met een onderdeel dat niet hetzelfde is als waarop u code hebt opgegeven, als het pad waarnaar wordt verwezen niet onder uw controle valt. Als een softwarepakket het onderdeel op de buildcomputer bijwerkt zonder de versiegegevens bij te werken, kan het zijn dat u een ander onderdeel laadt met een mogelijke incompatibiliteit. Om dit te voorkomen, kunt u een in de cache opgeslagen, bekende versie van de binaire COM-bestanden gebruiken en alleen hiernaar verwijzen.

Reference

Dit is de aanbevolen manier om te verwijzen naar COM-onderdelen met nieuwere versies van .NET. Wrapper-assemblies worden vooraf gegenereerd, in plaats van te worden gebouwd bij elke build-sessie, en de uitvoer wordt rechtstreeks als beheerde assemblies gerefereerd.

Soms worden wrapper-assembly's (PIA’s) gedistribueerd door de provider van de COM-onderdelen. Als dat het geval is, kunt u er rechtstreeks naar verwijzen als beheerde assemblies. Dit verschilt niet van het verwijzen naar andere .NET-assembly's, behalve dat er tijdens runtime een afhankelijkheid is van het COM-onderdeel dat wordt geïnstalleerd en geregistreerd.

Als u de wrapperassembly's zelf wilt maken voor COM-onderdelen die u wilt gebruiken, gebruikt tlbimp.exe of aximp.exe voor ActiveX-besturingselementen.

Met deze methode kunt u voorkomen dat verhoogde bevoegdheden nodig zijn om tijdens de build naar het systeemregister te schrijven. Als u uw eigen wrapperassembly's genereert en opslaat op een plaats die u beheert, mogelijk in een NuGet-pakket of in een map die toegankelijk is voor uw oplossing, kunt u worden geïsoleerd van wijzigingen die buiten uw controle vallen.

Bitness

Als uw project naar 32-bits COM-onderdelen verwijst, moet u bouwen met MSBuild.exe of Visual Studio, niet dotnet build. Dit komt omdat dotnet build de 64-bits versie van MSBuild wordt uitgevoerd, die niet geschikt is voor het werken met 32-bits COM-onderdelen.

COM-onderdelen werden vroeger allemaal gecompileerd tot 32-bits binaries. Later, toen 64-bits technologie werd geïntroduceerd, werd het mogelijk om een COM-onderdeel te compileren voor zowel 32-bits als 64-bits binaire bestanden. Hetzelfde onderdeel is vaak beschikbaar in zowel 32-bits als 64-bits binaire bestanden. De GUID of CLSID die dat unieke onderdeel identificeert, is hetzelfde voor zowel 32-bits als 64-bits binaire bestanden, maar het register is gesplitst in verschillende 32-bits en 64-bits secties.

Er kunnen fouten optreden als uw projecten niet goed zijn geconfigureerd om te verwijzen naar de juiste bitness van het COM-onderdeel dat u nodig hebt. Als uw COM-onderdeel alleen beschikbaar is als een 32-bits binair bestand, kan uw app dit alleen gebruiken als het wordt uitgevoerd als een 32-bits proces. Als uw .NET-assembly is gebouwd als een 32-bits assembly, kan deze verwijzen naar 32-bits COM-onderdelen. Als deze is gebouwd als een 64-bits assembly, kan deze verwijzen naar 64-bits COM-onderdelen. Hoewel uw assembly als Any CPU is gebouwd, moet u voorzichtig zijn met het verwijzen naar COM-componenten, die geen equivalent van Any CPU hebben. Het is misschien beter om uw toepassing te bouwen in zowel 32-bits als 64-bits formulieren, die verwijzen naar de juiste COM-onderdelen, ervan uitgaande dat de COM-onderdelen beschikbaar zijn in beide bitnessformulieren.

Er is een andere build-eigenschap Prefer32bit (ook een selectievakje in Visual Studio) waardoor een assembly die is gebouwd Any CPU als altijd als 32-bits op een 64-bits computer wordt uitgevoerd. Dit zou werken met 32-bits COM-onderdelen, maar het kan misleidend zijn voor iedereen die het project later gebruikt.

U kunt kenmerken in de Condition eigenschap gebruiken PlatformTarget om te verwijzen naar twee verschillende bitnessvormen van één COM-onderdeel. Bijvoorbeeld

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

Wanneer u bouwt voor x86, verwijst u naar de 32-bits COM-DLL, maar wanneer u bouwt voor x64, verwijst u naar de 64-bits versie.

Hoe MSBuild COM-verwijzingen oplost

Het basisalgoritmen worden hier beschreven, inclusief de reeks stappen voor het omzetten van een verwijzing, welke uitvoerbare bestanden worden uitgevoerd (bijvoorbeeld tlbimp.exe) en welke Windows API-aanroepen worden gebruikt.

In het standaard .NET SDK-build-proces wordt de ResolveComReference-taak aangeroepen in de gemeenschappelijke doelenbestanden in een doel met de naam ResolveComReferences. Het doel wordt eenmaal per project aangeroepen en verwerkt alle COM-verwijzingen, zowel COMReference als COMFileReference. Zie ResolveComReference-taak voor meer informatie.

De taak doorloopt de afhankelijkheidsboom en probeert alle verwijzingen op te lossen. De meeste fouten met afzonderlijke verwijzingen zijn niet dodelijk; MSBuild blijft proberen andere verwijzingen op te lossen. Sommige fouten zijn fataal, als ze alle verwijzingen evenzeer beïnvloeden.

Als het COM-onderdeel wordt gevonden in het register of in het bestandssysteem, probeert MSBuild doorgaans eerder gebouwde wrapperassembly's opnieuw te gebruiken, maar indien nodig worden de wrappers gegenereerd. Met standaardinstellingen worden de wrapper-assembly's gegenereerd door deze uit te voeren tlbimp.exe en in een map onder de projectmap te plaatsen. Deze tlbimp.exe is opgenomen in de .NET Framework SDK.

Door eigenschappen in te stellen, kunt u de argumenten en instellingen aanpassen die aan de ResolveComReference taak zijn opgegeven. U kunt configureren of u eerder gebouwde wrapperassembly's wilt gebruiken, of deze nu eerder zijn gebouwd of in de cache staan (als de cacheoptie wordt gebruikt). U kunt de uitvoermap aanpassen door de EmbedInteropTypes optie in te stellen op true. Met deze methode worden de geprojecteerde typen ingesloten in de bibliotheek of het uitvoerbare bestand dat wordt gemaakt, in plaats van in een afzonderlijke wrapper-assembly.

Diagnostische instrumenten

Als u de specifieke buildfout wilt diagnosticeren, moet u de gedetailleerde invoer voor de ResolveComReference taak zien die is mislukt.

Uitvoerige diagnostiek

U kunt uitgebreide diagnostiek instellen met behulp van de -v:diag schakeloptie op de MSBuild-opdrachtregel of in de Visual Studio IDE.

Vouw in het deelvenster Extra>opties de sectie Alle instellingen>Projecten en oplossingen>Bouwen en Uitvoeren uit en stel de verbaalheidsopties voor de build van het MSBuild-project en de verbaalheidsopties van het MSBuild-projectlogbestand in op Diagnostisch.

In het dialoogvenster Extra>Opties vouw je de sectie Projecten en Oplossingen>Bouwen en Uitvoeren uit, en stel je de opties voor de uitvoer-details van de build van het MSBuild-project en de logdetailniveau van het MSBuild-project-logbestand in op Diagnostic.

Binaire logboeken weergeven

Genereer een binair logboek (-bl schakel de MSBuild-opdrachtregel in) en gebruik de gestructureerde logboekviewer, die een gebruikersinterface biedt waarmee u de gedetailleerde stappen in de build, de waarden van taakinvoerparameters enzovoort veel gemakkelijker kunt zien.

Hier ziet u de weergave van het ResolveComReferences doel in de gestructureerde logviewer. U kunt de parameters en uitvoer controleren die de opgeloste referentiepaden en wrapper-assemblies vertegenwoordigen. In dit voorbeeld wordt de locatie van de wrapper-assembly uitgebreid om de locatie en bestandsnaam van de gegenereerde wrapper-assembly weer te geven.

Schermopname van de in MSBuild gestructureerde logboekviewer, die het ResolveComReferences-doel bekijkt.

Nadat u de naam, GUID en versie van het onderdeel hebt geïdentificeerd die een fout heeft veroorzaakt, kunt u alle eigenschappen en items bekijken die aan de ResolveComReference taak zijn verstrekt en informatie over dit onderdeel verzamelen uit het systeemregister. U kunt de registereditor regedit.exe gebruiken, maar voor het bewerken van het register zijn Administratorbevoegdheden vereist.

RegEdit

Raak vertrouwd met de registerlocaties voor COM-onderdelen, zowel 32-bits als 64-bits registerlocaties. GUID's die een COM-klassetype identificeren, worden klasse-id's (CLSID) genoemd en opgeslagen onder CLSID in het register. Op een 64-bits computer worden 64-bits onderdelen geregistreerd onder HKEY_LOCAL_MACHINE\Software\Classes\CLSID\, maar 32-bits onderdelen zijn geregistreerd onder HKEY_LOCAL_MACHINE\Software\WOW6432Node\Classes\CLSID\. Op een 32-bits computer worden 32-bits onderdelen geregistreerd onder HKEY_LOCAL_MACHINE\Software\Classes\CLSID\. Meestal vindt u de component door te zoeken naar zijn naam of GUID in de registereditor. Als de registratie van het onderdeel zich in een register-hive bevindt, zoals bij Visual Studio-onderdelen, moet u de hive mogelijk zoeken en openen. Zie Het register bewerken voor een Visual Studio-exemplaar.

OleView

U geeft mogelijk de voorkeur aan met oleview.exe een afzonderlijk COM-type te onderzoeken en om informatie op te halen, zoals de typebibliotheek en welke interfaces het implementeert. OLEView vereist geen beheerdersmachtigingen en is eenvoudiger te gebruiken dan regedit.exe.

Procmon

U kunt Procesmonitor procmon gebruiken om toepassingen te bewaken die COM tijdens runtime gebruiken en registerwijzigingen te controleren.

Algemene problemen

In deze sectie worden veelvoorkomende problemen beschreven die kunnen optreden bij het gebruik van COM-verwijzingen.

Registratieproblemen

Is het onderdeel geregistreerd op de build-machine? Als een van uw eigen onderdelen niet is geregistreerd, kan deze handmatig worden geregistreerd met behulp van een opdrachtregelprogramma. regsvr32.exe (Voor deze opdracht zijn verhoogde machtigingen vereist op de computer.) Als de onderdelen deel uitmaken van een softwarepakket, zoals Office, controleert u of de juiste versie van het product dat het onderdeel distribueert en registreert, is geïnstalleerd. Probeer het softwareproduct of pakket te herstellen of opnieuw te installeren.

Bevestig de eigenschappen van de COMReference. Zijn de naam, GUID en versies correct, hetzelfde als in het register? Controleer op typfouten, spelfouten, niet-overeenkomende versies of andere inconsistenties.

Overweeg of het onderdeel een 32-bits of een 64-bits onderdeel is, als beide versies beschikbaar zijn. Als u zich richt op ARM64, raadpleegt u Binaire bestanden voor Arm64X opbouwen.

Met COMFileReference verwijst u naar een COM-onderdeel op basis van de bestandslocatie. Controleer het pad naar het bestand en zorg ervoor dat het juist is, houd rekening met de huidige werkmap als het een relatief pad betreft.

Typebibliotheekproblemen

Er is een typebibliotheek vereist voor het genereren van een interop-assembly. Typebibliotheken kunnen worden ingesloten in een binair bestand, zoals een DLL, of in een afzonderlijk bestand, een TLB-bestand (.tlb extensie).

Als u geen typebibliotheek voor het COM-onderdeel kunt vinden, kunt u er vaak een genereren. Normaal gesproken hoeft u geen typebibliotheek te genereren. Het moet worden geïnstalleerd met het onderdeel, gedistribueerd door de onderdeelprovider. Veelvoorkomende oplossingen zijn onder andere het installeren, upgraden of opnieuw installeren van een softwarepakket.

Er zijn manieren om een typebibliotheek te genereren op basis van een COM-binair in het zeldzame geval dat er een nodig is. U kunt bijvoorbeeld het binaire bestand openen in de Visual Studio-resource-editor of een resource-editor van derden, de typebibliotheekresource zoeken, exporteren en opslaan als een tekstbestand gebruiken met de tlb extensie.

Kan afhankelijkheden niet scannen

MSB3304 treedt op als er problemen zijn met het scannen van de afhankelijkheden van de verwijzing. De ResolveComReference taak probeert de volledige afhankelijkheidsgrafiek te doorlopen, zodat problemen met het identificeren van de afhankelijkheden deze fout geven. Het opgegeven foutbericht is afhankelijk van het specifieke probleem. Als de fout afkomstig is van tlbimp.exe, kunt u ook proberen tlbimp.exe op de opdrachtregel uit te voeren voor meer informatie over het probleem.

Problemen met het genereren van ommantelingsassemblages

MSBuild probeert bestaande wrapper-assembly's te vinden in de cache van een vorige uitvoering, als deze optie is opgegeven of eerder gegenereerde wrappers opnieuw gebruiken. Indien nodig wordt de wrapper gegenereerd. Het hulpprogramma tlbimp.exe wordt gebruikt om wrapper-assembly's te bouwen. Er wordt een map gemaakt die de wrapper-assembly's bevat. De map wordt standaard gemaakt in de projectmap, maar deze wordt ingesteld door de WrapperAssemblyLocation parameter van de ResolveComReference taak. Als dit proces mislukt, wordt de fout MSB3290 of MSB3283 gegeven, samen met de foutinformatie van het besturingssysteem. Zie de voorgestelde tips voor probleemoplossing voor deze specifieke fouten.

Verkeerde COMReference- of COMFileReference-syntaxis

Als MSBuild de metagegevens niet kan converteren uit het projectbestand, krijgt u een foutmelding MSB3095. Als dit gebeurt, controleert u op typfouten of andere fouten in de COM-verwijzingen (of eventuele eigenschappen die in de COM-verwijzingen worden gebruikt) in het projectbestand. Controleer de subelementen van het COMReference element op basis van de verwachte metagegevens, zoals beschreven in algemene MSBuild-projectitems voor syntaxisfouten of ontbrekende metagegevens.

Fouten met bestands-IO

De ResolveComReference taak leest en schrijft op het bestandssysteem, wat betekent dat het kan mislukken met een systeem-I/O-fout, die door MSBuild worden opgevangen en gerapporteerd onder een algemene MSBuild-foutcode. Bekijk de foutdetails in de berichten van het besturingssysteem. Controleer de spelling en juistheid van alle paden en controleer de eigenschappen voor paden die zijn samengesteld uit MSBuild-eigenschappen om ervoor te zorgen dat ze zijn gedefinieerd en de verwachte waarden hebben.

Warnings

Sommige problemen met COM-referentieoplossing worden gerapporteerd als waarschuwingen. Mogelijk ziet u MSB3305, die wordt gegeven wanneer een onderliggende functie een niet-fataal probleem rapporteert, zoals een potentieel typeconversieprobleem. U kunt dergelijke waarschuwingen onderdrukken door de eigenschap ResolveComReferenceSilent MSBuild in te stellen op true. We raden u niet aan deze instelling permanent te gebruiken, maar het kan handig zijn als u het probleem begrijpt en de melding tijdelijk wilt onderdrukken. U kunt ook standaardtechnieken gebruiken om waarschuwingen te onderdrukken. Zie Waarschuwingen bij het bouwen onderdrukken.

Systeemeigen methode-aanroepen van Windows

De ResolveComReference functie kan bepaalde Windows API-functies aanroepen. Fouten van deze API-aanroepen worden doorgegeven aan de build-uitvoer. Deze worden hier ter referentie vermeld.

Functienaam Description
FreeLibrary Hiermee wordt de geladen DLL-module (Dynamic Link Library) vrijgemaakt.
GetModuleFileName Hiermee wordt het volledig gekwalificeerde pad opgehaald voor het bestand dat de opgegeven module bevat.
LoadLibrary Laadt de opgegeven module in de adresruimte van het aanroepende proces.
LoadRegTypeLib Maakt gebruik van registergegevens om een typebibliotheek te laden.
QueryPathOfRegTypeLib Hiermee haalt u het pad van een geregistreerde typebibliotheek op.