Hoe de runtime assembly's zoekt
Notitie
Dit artikel is specifiek voor .NET Framework. Dit geldt niet voor nieuwere implementaties van .NET, waaronder .NET 6 en nieuwere versies.
Als u uw .NET Framework-toepassing wilt implementeren, moet u begrijpen hoe de algemene taalruntime de assembly's vindt en verbindt die deel uitmaken van uw toepassing. De runtime probeert standaard verbinding te maken met de exacte versie van een assembly waarmee de toepassing is gebouwd. Dit standaardgedrag kan worden overschreven door configuratiebestandsinstellingen.
De algemene taalruntime voert een aantal stappen uit bij het zoeken naar een assembly en het oplossen van een assembly-verwijzing. Elke stap wordt uitgelegd in de volgende secties. De term testen wordt vaak gebruikt bij het beschrijven van hoe de runtime assembly's zoekt; het verwijst naar de set heuristieken die worden gebruikt om de assembly te vinden op basis van de naam en cultuur.
Notitie
U kunt bindingsinformatie in het logboekbestand weergeven met behulp van de Assembly Binding Log Viewer (Fuslogvw.exe), die is opgenomen in de Windows SDK.
De binding starten
Het proces van het zoeken en binden aan een assembly begint wanneer de runtime een verwijzing naar een andere assembly probeert op te lossen. Deze verwijzing kan statisch of dynamisch zijn. De compiler registreert statische verwijzingen in de metagegevens van het assemblymanifest tijdens de build. Dynamische verwijzingen worden snel samengesteld als gevolg van het aanroepen van verschillende methoden, zoals Assembly.Load.
De voorkeurswijze om naar een assembly te verwijzen, is door een volledige verwijzing te gebruiken, waaronder de assemblynaam, versie, cultuur en openbare-sleuteltoken (indien aanwezig). De runtime gebruikt deze informatie om de assembly te vinden, volgens de stappen die verderop in deze sectie worden beschreven. De runtime maakt gebruik van hetzelfde oplossingsproces, ongeacht of de verwijzing voor een statische of dynamische assembly is.
U kunt ook een dynamische verwijzing naar een assembly maken door de aanroepmethode alleen gedeeltelijke informatie over de assembly op te geven, zoals het opgeven van alleen de assemblynaam. In dit geval wordt alleen de toepassingsmap gezocht naar de assembly en wordt er geen andere controle uitgevoerd. U maakt een gedeeltelijke verwijzing met behulp van een van de verschillende methoden voor het laden van assembly's zoals Assembly.Load of AppDomain.Load.
Ten slotte kunt u een dynamische verwijzing maken met behulp van een methode, zoals Assembly.Load en slechts gedeeltelijke informatie opgeven. Vervolgens kwalificeren u de verwijzing met behulp van het <element qualifyAssembly> in het configuratiebestand van de toepassing. Met dit element kunt u de volledige referentiegegevens (naam, versie, cultuur en, indien van toepassing, het openbare-sleuteltoken) opgeven in uw toepassingsconfiguratiebestand in plaats van in uw code. U gebruikt deze techniek als u een verwijzing naar een assembly buiten de toepassingsmap volledig wilt kwalificeren of als u wilt verwijzen naar een assembly in de algemene assemblycache, maar u het gemak van het opgeven van de volledige verwijzing in het configuratiebestand in plaats van in uw code.
Notitie
Dit type gedeeltelijke verwijzing mag niet worden gebruikt met assembly's die worden gedeeld tussen verschillende toepassingen. Omdat configuratie-instellingen per toepassing en niet per assembly worden toegepast, vereist een gedeelde assembly met dit type gedeeltelijke verwijzing dat elke toepassing met behulp van de gedeelde assembly de in aanmerking komende informatie in het configuratiebestand heeft.
De runtime gebruikt de volgende stappen om een assembly-verwijzing op te lossen:
Bepaalt de juiste assemblyversie door de toepasselijke configuratiebestanden te onderzoeken, waaronder het configuratiebestand van de toepassing, het uitgeversbeleidsbestand en het configuratiebestand van de computer. Als het configuratiebestand zich op een externe computer bevindt, moet de runtime eerst het configuratiebestand van de toepassing zoeken en downloaden.
Controleert of de assemblynaam is gebonden aan eerder en, indien dat het het volgende is, de eerder geladen assembly gebruikt. Als een vorige aanvraag voor het laden van de assembly is mislukt, wordt de aanvraag onmiddellijk mislukt zonder de assembly te laden.
Notitie
De caching van assemblybindingsfouten is nieuw in .NET Framework versie 2.0.
Controleert de algemene assemblycache. Als de assembly daar wordt gevonden, gebruikt de runtime deze assembly.
Test voor de assembly met behulp van de volgende stappen:
Als het configuratie- en uitgeversbeleid geen invloed heeft op de oorspronkelijke verwijzing en als de bindingsaanvraag is gemaakt met behulp van de Assembly.LoadFrom methode, controleert de runtime op locatiehints.
Als er een codebase wordt gevonden in de configuratiebestanden, controleert de runtime alleen deze locatie. Als deze test mislukt, bepaalt de runtime dat de bindingsaanvraag is mislukt en er geen andere tests worden uitgevoerd.
Tests voor de assembly met behulp van de heuristiek die in het testgedeelte worden beschreven. Als de assembly niet wordt gevonden na het testen, vraagt de runtime windows Installer om de assembly op te geven. Dit fungeert als een functie op aanvraag.
Notitie
Er is geen versiecontrole voor assembly's zonder sterke namen, noch controleert de runtime de globale assemblycache voor assembly's zonder sterke namen.
Stap 1: De configuratiebestanden controleren
Het gedrag van assemblybindingen kan op verschillende niveaus worden geconfigureerd op basis van drie XML-bestanden:
Toepassingsconfiguratiebestand.
Publisher-beleidsbestand.
Computerconfiguratiebestand.
Deze bestanden volgen dezelfde syntaxis en bieden informatie zoals bindingsomleidingen, de locatie van code en bindingsmodi voor bepaalde assembly's. Elk configuratiebestand kan een <assemblyBinding-element> bevatten waarmee het bindingsproces wordt omgeleid. De onderliggende elementen van het assemblyBinding-element> bevatten het< afhankelijkeAssembly-element>.< De onderliggende elementen van het element dependentAssembly> bevatten het <element assemblyIdentity>, het <element bindingRedirect> en het< codeBase-element>.<
Notitie
Configuratie-informatie vindt u in de drie configuratiebestanden; niet alle elementen zijn geldig in alle configuratiebestanden. Bindingsmodus en gegevens over privépaden kunnen zich bijvoorbeeld alleen in het configuratiebestand van de toepassing bevinden. Zie Apps configureren met behulp van configuratiebestanden voor een volledige lijst van de informatie die in elk bestand is opgenomen.
Toepassingsconfiguratiebestand
Eerst controleert de algemene taalruntime het toepassingsconfiguratiebestand op informatie die de versiegegevens overschrijft die zijn opgeslagen in het manifest van de aanroepende assembly. Het toepassingsconfiguratiebestand kan worden geïmplementeerd met een toepassing, maar is niet vereist voor het uitvoeren van de toepassing. Meestal is het ophalen van dit bestand vrijwel onmiddellijk, maar in situaties waarin de toepassingsbasis zich op een externe computer bevindt, zoals in een webscenario, moet het configuratiebestand worden gedownload.
Voor uitvoerbare clientbestanden bevindt het configuratiebestand van de toepassing zich in dezelfde map als het uitvoerbare bestand van de toepassing en heeft dezelfde basisnaam als het uitvoerbare bestand met de extensie .config. Het configuratiebestand voor C:\Program Files\Myapp\Myapp.exe is bijvoorbeeld C:\Program Files\Myapp\Myapp.exe.config. In een browserscenario moet het HTML-bestand het <koppelingselement> gebruiken om expliciet naar het configuratiebestand te verwijzen.
De volgende code bevat een eenvoudig voorbeeld van een toepassingsconfiguratiebestand. In dit voorbeeld wordt een TextWriterTraceListener aan de Listeners verzameling toegevoegd om foutopsporingsgegevens voor het opnemen van fouten in een bestand in te schakelen.
<configuration>
<system.diagnostics>
<trace useGlobalLock="false" autoflush="true" indentsize="0">
<listeners>
<add name="myListener" type="System.Diagnostics.TextWriterTraceListener, system version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" initializeData="c:\myListener.log" />
</listeners>
</trace>
</system.diagnostics>
</configuration>
Uitgeversbeleidsbestand
Ten tweede onderzoekt de runtime het uitgeversbeleidsbestand, indien aanwezig. Publisher-beleidsbestanden worden door een onderdeeluitgever gedistribueerd als een oplossing of update naar een gedeeld onderdeel. Deze bestanden bevatten compatibiliteitsgegevens die zijn uitgegeven door de uitgever van het gedeelde onderdeel waarmee een assemblyverwijzing naar een nieuwe versie wordt geleid. In tegenstelling tot toepassings- en machineconfiguratiebestanden zijn beleidsbestanden van uitgevers opgenomen in hun eigen assembly die moet worden geïnstalleerd in de globale assemblycache.
Hier volgt een voorbeeld van een configuratiebestand voor Publisher Policy:
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="asm6" publicKeyToken="c0305c36380ba429" />
<bindingRedirect oldVersion="3.0.0.0" newVersion="2.0.0.0"/>
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
Als u een assembly wilt maken, kunt u het hulpprogramma Al.exe (Assembly Linker) gebruiken met een opdracht zoals:
Al.exe /link:asm6.exe.config /out:policy.3.0.asm6.dll /keyfile: compatkey.dat /v:3.0.0.0
compatkey.dat
is een sleutelbestand met een sterke naam. Met deze opdracht maakt u een sterk benoemde assembly die u in de globale assemblycache kunt plaatsen.
Notitie
Publisher-beleid is van invloed op alle toepassingen die gebruikmaken van een gedeeld onderdeel.
Het configuratiebestand voor uitgeversbeleid overschrijft versiegegevens die afkomstig zijn van de toepassing (dat wil gezegd, uit het assemblymanifest of uit het configuratiebestand van de toepassing). Als het configuratiebestand van de toepassing geen instructie bevat om de versie die is opgegeven in het assemblymanifest om te leiden, overschrijft het uitgeversbeleidsbestand de versie die is opgegeven in het assemblymanifest. Als er echter een omleidingsinstructie in het configuratiebestand van de toepassing staat, overschrijft het uitgeversbeleid die versie in plaats van de versie die is opgegeven in het manifest.
Een uitgeversbeleidsbestand wordt gebruikt wanneer een gedeeld onderdeel wordt bijgewerkt en de nieuwe versie van het gedeelde onderdeel moet worden opgehaald door alle toepassingen die dat onderdeel gebruiken. De instellingen in het uitgeversbeleidsbestand overschrijven instellingen in het toepassingsconfiguratiebestand, tenzij het configuratiebestand van de toepassing veilige modus afdwingt.
Veilige modus
Publisher-beleidsbestanden worden meestal expliciet geïnstalleerd als onderdeel van een servicepack- of programma-update. Als er een probleem is met het bijgewerkte gedeelde onderdeel, kunt u de onderdrukkingen in het uitgeversbeleidsbestand negeren met behulp van de veilige modus. De veilige modus wordt bepaald door de <publisherPolicy apply="ja|nee"/>-element, alleen in het toepassingsconfiguratiebestand. Hiermee geeft u op of de configuratiegegevens van het uitgeversbeleid moeten worden verwijderd uit het bindingsproces.
De veilige modus kan worden ingesteld voor de hele toepassing of voor geselecteerde assembly's. Dat wil gezegd, u kunt het beleid uitschakelen voor alle assembly's waaruit de toepassing bestaat, of het inschakelen voor sommige assembly's, maar niet voor andere assembly's. Als u selectief uitgeverbeleid wilt toepassen op assembly's waaruit een toepassing bestaat, stelt u publisherPolicy apply=no/> in en geeft u op welke assembly's u wilt toepassen met behulp van het< afhankelijkeAssembly-element>.< Als u uitgeversbeleid wilt toepassen op alle assembly's waaruit de toepassing bestaat, stelt u <publisherPolicy apply=no/> zonder afhankelijke assembly-elementen in. Zie Apps configureren met behulp van Configuratiebestanden voor meer informatie over configuratie.
Machineconfiguratiebestand
Ten derde onderzoekt de runtime het configuratiebestand van de machine. Dit bestand, genaamd Machine.config, bevindt zich op de lokale computer in de submap Configuratie van de hoofdmap waarop de runtime is geïnstalleerd. Dit bestand kan door beheerders worden gebruikt om bindingsbeperkingen voor assembly's op te geven die lokaal zijn voor die computer. De instellingen in het configuratiebestand van de machine hebben voorrang op alle andere configuratie-instellingen; Dit betekent echter niet dat alle configuratie-instellingen in dit bestand moeten worden geplaatst. De versie die wordt bepaald door het beheerdersbeleidsbestand is definitief en kan niet worden overschreven. Onderdrukkingen die zijn opgegeven in het bestand Machine.config zijn van invloed op alle toepassingen. Zie Apps configureren met behulp van configuratiebestanden voor meer informatie over configuratiebestanden.
Stap 2: Controleren op eerder gebruikte assembly's
Als de aangevraagde assembly ook is aangevraagd in eerdere aanroepen, gebruikt de algemene taalruntime de assembly die al is geladen. Dit kan gevolgen hebben bij het benoemen van assembly's waaruit een toepassing bestaat. Zie Assembly-namen voor meer informatie over naamgevingsassembly's.
Als een eerdere aanvraag voor de assembly is mislukt, worden volgende aanvragen voor de assembly onmiddellijk mislukt zonder de assembly te laden. Vanaf .NET Framework versie 2.0 worden assemblybindingsfouten in de cache opgeslagen en worden de gegevens in de cache gebruikt om te bepalen of de assembly moet worden geladen.
Notitie
Als u wilt terugkeren naar het gedrag van .NET Framework-versies 1.0 en 1.1, waarbij bindingsfouten niet in de cache zijn opgeslagen, neemt u het <element disableCachingBindingFailures> op in uw configuratiebestand.
Stap 3: de algemene assemblycache controleren
Voor sterk benoemde assembly's gaat het bindingsproces verder door te kijken in de globale assemblycache. In de globale assemblycache worden assembly's opgeslagen die door verschillende toepassingen op een computer kunnen worden gebruikt. Alle assembly's in de globale assemblycache moeten sterke namen hebben.
Stap 4: de assembly zoeken via codebases of testen
Nadat de juiste assemblyversie is bepaald met behulp van de informatie in de referentie van de aanroepende assembly en in de configuratiebestanden, en nadat deze de algemene assemblycache heeft ingecheckt (alleen voor sterk benoemde assembly's), probeert de algemene taalruntime de assembly te vinden. Het proces voor het zoeken naar een assembly omvat de volgende stappen:
Als een <codeBase-element> wordt gevonden in het configuratiebestand van de toepassing, controleert de runtime de opgegeven locatie. Als er een overeenkomst wordt gevonden, wordt die assembly gebruikt en wordt er geen testen uitgevoerd. Als de assembly daar niet wordt gevonden, mislukt de bindingsaanvraag.
De runtime test vervolgens voor de assembly waarnaar wordt verwezen met behulp van de regels die verderop in deze sectie zijn opgegeven.
Notitie
Als u meerdere versies van een assembly in een map hebt en u naar een bepaalde versie van die assembly wilt verwijzen, moet u het <codeBase-element> gebruiken in plaats van het privatePath
kenmerk van het< testelement>. Als u het <testelement> gebruikt, stopt de runtime met het testen van de eerste keer dat er een assembly wordt gevonden die overeenkomt met de eenvoudige assemblynaam waarnaar wordt verwezen, ongeacht of het een juiste overeenkomst is of niet. Als het een juiste overeenkomst is, wordt die assembly gebruikt. Als het geen juiste overeenkomst is, stopt testen en binden mislukt.
De assembly zoeken via Codebases
Codebase-informatie kan worden verstrekt met behulp van een <codeBase-element> in een configuratiebestand. Deze codebase wordt altijd gecontroleerd voordat de runtime probeert te testen op de assembly waarnaar wordt verwezen. Als een uitgeversbeleidsbestand met de definitieve versieomleiding ook een codeBase-element> bevat, is dat <codeBase-element> het element dat wordt gebruikt.< Als uw toepassingsconfiguratiebestand bijvoorbeeld een codeBase-element> opgeeft en een uitgeversbeleidsbestand dat de toepassingsgegevens overschrijft, ook een <codeBase-element specificeert, wordt het <codeBase-element>> in het uitgeversbeleidsbestand gebruikt.<
Als er geen overeenkomst wordt gevonden op de locatie die is opgegeven door het <codeBase-element> , mislukt de bindingsaanvraag en worden er geen verdere stappen uitgevoerd. Als de runtime bepaalt dat een assembly overeenkomt met de criteria van de aanroepende assembly, wordt die assembly gebruikt. Wanneer het bestand dat is opgegeven door het opgegeven <codeBase-element> wordt geladen, controleert de runtime of de naam, versie, cultuur en openbare sleutel overeenkomen met de verwijzing van de aanroepende assembly.
Notitie
Naar assembly's buiten de hoofdmap van de toepassing moeten sterke namen bestaan en moeten worden geïnstalleerd in de globale assemblycache of worden opgegeven met behulp van het codeBase-element>.<
De assembly zoeken via probing
Als het toepassingsconfiguratiebestand geen <codeBase-element> bevat, wordt de runtime voor de assembly uitgevoerd met behulp van vier criteria:
Toepassingsbasis, de hoofdlocatie waar de toepassing wordt uitgevoerd.
Cultuur, het cultuurkenmerk van de assembly waarnaar wordt verwezen.
Naam, de naam van de assembly waarnaar wordt verwezen.
Het
privatePath
kenmerk van het <testelement> , de door de gebruiker gedefinieerde lijst met submappen onder de hoofdlocatie. Deze locatie kan worden opgegeven in het toepassingsconfiguratiebestand en in beheerde code met behulp van de AppDomainSetup.PrivateBinPath eigenschap voor een toepassingsdomein. Wanneer deze is opgegeven in beheerde code, wordt de beheerde codeprivatePath
eerst gecontroleerd, gevolgd door het pad dat is opgegeven in het configuratiebestand van de toepassing.
De toepassingsbasis- en cultuurmappen testen
De runtime begint altijd met het testen van de basis van de toepassing. Dit kan een URL zijn of de hoofdmap van de toepassing op een computer. Als de assembly waarnaar wordt verwezen niet wordt gevonden in de toepassingsbasis en er geen cultuurgegevens worden opgegeven, zoekt de runtime naar submappen met de assemblynaam. De mappen die zijn uitgevoerd, zijn onder andere:
[toepassingsbasis] / [assemblynaam].dll
[toepassingsbasis] / [assemblynaam] / [assemblynaam].dll
Als cultuurinformatie is opgegeven voor de assembly waarnaar wordt verwezen, worden alleen de volgende mappen gecontroleerd:
[toepassingsbasis] / [cultuur] / [assemblynaam].dll
[toepassingsbasis] / [cultuur] / [assemblynaam] / [assemblynaam].dll
Testen met het kenmerk privatePath
Naast de submappen van de cultuur en de submappen die zijn genoemd voor de assembly waarnaar wordt verwezen, test de runtime ook mappen die zijn opgegeven met behulp van het privatePath
kenmerk van het <testelement> . De mappen die zijn opgegeven met behulp van het privatePath
kenmerk, moeten submappen van de hoofdmap van de toepassing zijn. De onderzochte mappen variëren, afhankelijk van of cultuurinformatie is opgenomen in de assemblyaanvraag waarnaar wordt verwezen.
De runtime stopt met het testen van de eerste keer dat er een assembly wordt gevonden die overeenkomt met de naam van de eenvoudige assembly waarnaar wordt verwezen, ongeacht of deze een juiste overeenkomst is of niet. Als het een juiste overeenkomst is, wordt die assembly gebruikt. Als het geen juiste overeenkomst is, stopt testen en binden mislukt.
Als cultuur is opgenomen, worden de volgende mappen uitgevoerd:
[toepassingsbasis] / [binpath] / [cultuur] / [assemblynaam].dll
[toepassingsbasis] / [binpath] / [cultuur] / [assemblynaam] / [assemblynaam].dll
Als er geen cultuurinformatie is opgenomen, worden de volgende mappen uitgevoerd:
[toepassingsbasis] / [binpath] / [assemblynaam].dll
[toepassingsbasis] / [binpath] / [assemblynaam] / [assemblynaam].dll
Voorbeelden van testen
Gegeven de volgende informatie:
Naam van assembly waarnaar wordt verwezen: myAssembly
Hoofdmap van toepassing:
http://www.code.microsoft.com
<Het testelement> in het configuratiebestand geeft het volgende op: bin
Cultuur: de
De runtime test de volgende URL's:
http://www.code.microsoft.com/de/myAssembly.dll
http://www.code.microsoft.com/de/myAssembly/myAssembly.dll
http://www.code.microsoft.com/bin/de/myAssembly.dll
http://www.code.microsoft.com/bin/de/myAssembly/myAssembly.dll
Meerdere assembly's met dezelfde naam
In het volgende voorbeeld ziet u hoe u meerdere assembly's met dezelfde naam configureert.
<dependentAssembly>
<assemblyIdentity name="Server" publicKeyToken="c0305c36380ba429" />
<codeBase version="1.0.0.0" href="v1/Server.dll" />
<codeBase version="2.0.0.0" href="v2/Server.dll" />
</dependentAssembly>
Andere locaties die zijn getest
Assemblylocatie kan ook worden bepaald met behulp van de huidige bindingscontext. Dit gebeurt meestal wanneer de Assembly.LoadFrom methode wordt gebruikt en in COM-interoperabiliteitsscenario's. Als een assembly de LoadFrom methode gebruikt om naar een andere assembly te verwijzen, wordt de locatie van de aanroepende assembly beschouwd als een hint over waar de assembly waarnaar wordt verwezen, moet worden gevonden. Als er een overeenkomst wordt gevonden, wordt die assembly geladen. Als er geen overeenkomst wordt gevonden, gaat de runtime verder met de zoeksemantiek en voert vervolgens een query uit op Windows Installer om de assembly te leveren. Als er geen assembly is opgegeven die overeenkomt met de bindingsaanvraag, wordt er een uitzondering gegenereerd. Deze uitzondering is een TypeLoadException beheerde code als er naar een type wordt verwezen of als er FileNotFoundException geen assembly is gevonden die wordt geladen.
Als Assembly1 bijvoorbeeld verwijst naar Assembly2 en Assembly1 is gedownload http://www.code.microsoft.com/utils
, wordt die locatie beschouwd als een hint over waar Assembly2.dll te vinden. De runtime test vervolgens op de assembly in http://www.code.microsoft.com/utils/Assembly2.dll
en http://www.code.microsoft.com/utils/Assembly2/Assembly2.dll
. Als Assembly2 niet op een van deze locaties wordt gevonden, voert de runtime een query uit op Windows Installer.