Consolebroneditor: bronnen bewerken in EXE DLL-bestanden

Elke keer dat ik een nieuwe resource-dll moet bouwen, ga ik verwoed op zoek naar noodzakelijke informatie. Ben er moe van! Ik zet hier alles neer wat ik belangrijk vind.

Met de vriendelijke toestemming van Andrey Bushman dupliceer ik het bijna volledig. Ik zal de screenshots van Andrey (nou ja, alleen voor mezelf) aanvullen met screenshots van VS2015 CommunityEdition. Eigen opmerkingen Ik zal de toelichting cursief schrijven.
Het artikel is geschreven voor AutoCAD 2009, maar werkt prima in andere versies van AutoCAD.

Grafische afbeeldingen die in CUI-bestanden worden gebruikt, kunnen afkomstig zijn uit externe BMP-bestanden of uit het onbeheerde DLL-bronbestand waarin deze afbeeldingen zijn geplaatst. De tweede methode is handiger in gebruik. Hier bekijken we hoe u dergelijke DLL-bestanden kunt maken en hoe u ze in CUI-bestanden kunt gebruiken.

AutoCAD voor een lange tijd (sinds versie 2010) gebruikt het CUIX-formaat als gedeeltelijke bestanden menukaart, dat is regulier archief, waarvan de extensie is hernoemd van ZIP naar CUIX. Ons bedrijf gebruikt echter AutoCAD 2009 SP3, dat niet met CUIX kan werken, maar een ouder formaat gebruikt: CUI-bestanden, waarvan de inhoud wordt gepresenteerd in XML-formaat.

Bovendien zijn er vanaf versie 2015, als ik me niet vergis, twee ontwerpopties in AutoCAD geïntroduceerd: donker thema en een licht thema. Een pictogram maken dat op beide plaatsen zichtbaar is, is erg moeilijk. En het direct veranderen van de naam van de afbeelding is niet het beste beste oplossing. Meer details hieronder.

Een resource-DLL-bestand maken

In M.S. Visuele studio 2012 creëren nieuw project, gebaseerd op de sjabloon Leeg project en wijs deze de gewenste naam toe:

Nu in het raam Oplossingsverkenner druk klik met de rechtermuisknop muis op de projectnaam en in het contextmenu dat verschijnt, selecteert u het item Eigenschappen. Het toekennen van de vereiste waarden aan eigenschappen Doelextensie En Configuratietype:

Bovendien moet u in de projectinstellingen nog een optie wijzigen: Geen toegangspunt:

Nadat u de hierboven aangegeven wijzigingen heeft aangebracht, drukt u op de knop Toepassen En OK. Nu zijn de eigenschappen van ons nog lege project correct geconfigureerd. Op het tabblad Oplossingsverkenner, van contextmenu project, selecteert u het item Toevoegen -> Nieuw artikel... en selecteer in het dialoogvenster dat verschijnt de bronbestandsjabloon:

U kunt elke naam aan het bestand toewijzen, in ons voorbeeld laten we het staan resource.rc. Druk op de knop Toevoegen. Het bestand dat we hebben toegevoegd, bevat een lijst met afbeeldingen die zullen worden gebruikt in onze CUI(x)-bestanden.

Andrey raadt aan dat afbeeldingen die in de dll worden “gedreven” in de submap \images worden geplaatst. Een volkomen redelijke aanbeveling, hoewel niet kritisch. Een andere vraag is dat ik je ten zeerste aanbeveel om grondstoffen nog steeds zo te plaatsen dat ze kunnen worden ‘berekend’. relatief pad. Het helpt enorm als de ontwikkeling op meer dan één werkplek plaatsvindt.

Laten we als experiment toevoegen BMP-bestanden verschillende maten: 16x16, 24x24, 32x32, 48x48, 64x64 en 128x128. Knoppen op toolpaletten moeten 16x16 afbeeldingen bevatten, terwijl knoppen op lintpaletten groter zijn. In ons test-CUI-bestand zullen we hier en daar knoppen met de bovenstaande resoluties plaatsen om het resultaat van het gebruik van verschillende formaten te zien.

Verduidelijking: BMP moet gegarandeerd in VS worden geladen. Niet het beste voor GIMP-gebruikers beste nieuws: BMP moet worden gemaakt met een kleurdiepte van 24 bits en zonder compressie worden opgeslagen. Als u niet kunt opslaan zonder compressie, gebruik dan batch-conversie Met gebruik van FastStone Afbeeldingsviewer u kunt eenvoudig het gewenste resultaat bereiken.

Het zou mogelijk zijn om bestanden te kopiëren naar PNG-formaat AutoCAD 2009 kan echter geen afbeeldingen van dit formaat gebruiken in CUI-bestanden.

Verduidelijking: U kunt proberen geen *.bmp-, maar *.ico-bestanden te verbinden. Natuurlijk, sommigen extra werk, maar het is mogelijk.
In oudere versies moet u "transparantie" op de achtergrond garanderen RGB-kleur 192.192.192. Oudere versies van AutoCAD beschouwen het als transparant.
En hier is nog iets: AutoCAD2018 “begrijpt” bmp niet langer, en vereist alleen png

Nu terug naar onze IDE: schakel naar het tabblad Bronweergave.

Roep het item aan vanuit het contextmenu van het Resource.rc-element Bron toevoegen...

In het dialoogvenster Bron toevoegen op de lijst Brontype selecteer een element Bitmap, druk op de knop Importeren... en specificeer BMP-bestanden uit de submap \images die we eerder hebben gemaakt. We krijgen het volgende resultaat (het uiterlijk is absoluut hetzelfde voor zowel 2012 als 2015)

Nu voor elk element waarde van onroerend goed Identiteitskaart moet geïsoleerd worden dubbele aanhalingstekens zodat ze met succes kunnen worden gebruikt in onze CUI(x)-bestanden:

Dat is alles, laten we nu ons DLL-bestand compileren (F6-toets of via het menu Bouw -> Bouw oplossing) .

Einde citaat verdere acties Door met behulp van DLL's Als ik het nodig heb, schrijf ik het later op.

Nu iets uit mijn eigen (en niet alleen mijn eigen) ervaring.

Deze technologie werkt uitstekend bij het gebruik van gedeeltelijke aanpassingsbestanden. Als u zo'n dll probeert te bouwen voor een bedrijfsaanpassingsbestand, kunt u de bestaande dll niet vervangen: eerst moeten alle gebruikers AutoCAD uitschakelen.

De dll-naam moet overeenkomen met de cui(x)-bestandsnaam. Het is zeer raadzaam om de dll naast het cui(x)-bestand te plaatsen. Theoretisch kun je het gewoon op het ondersteuningspad gooien, maar persoonlijk heb ik nog nooit zoiets gedaan - dan word je het zoeken ernaar beu.

Wat betreft de thema's, zoals beloofd, gebaseerd op informatie op het ADN-CIS-forum en Autodesk-help:

  1. In versies van AutoCAD zonder thema werden bronnen gehaald uit een dll met dezelfde naam als het cui(x)-bestand.
  2. In versies van AutoCAD met thema's moet u voor elk thema een aparte DLL-bron maken: licht en donker. Overeenkomstig Bron-DLL gebruikt op basis van welk onderwerp in huidige moment toegepast op gebruikersinterface. De naamgevingsconventie voor DLL-bestanden vereist dat u dezelfde naam gebruikt als de naam van het aanpassingsbestand, maar u moet ook een achtervoegsel toevoegen "_licht" voor het DLL-bestand dat zal worden gebruikt als het lichte thema. Als u bijvoorbeeld een CUIx-bestand met de naam mijnmenu.cuix, zoekt AutoCAD naar een bronnenbibliotheekbestand mijnmenu_light.dll, als er een licht thema wordt gebruikt, en het bestand mijnmenu.dll, als een donker thema wordt gebruikt.

De volgorde van de bibliotheekcompilatie, rekening houdend met de ontwerpthema-optie, werd uitstekend beschreven door Dmitry Zagorulkin:

Ik heb het CUIX-bestand alleen gemaakt in versies 2014-2016, er waren geen problemen mee. Ook heb ik twee C++-projecten gemaakt met DLL's voor resourcepictogram - één voor het donkere schema, de tweede voor het lichte schema. In de projectinstellingen in de sectie "Build Events - Post Build Events" kunt u gebeurtenissen zo configureren dat de gemaakte dll-bestanden onmiddellijk worden gekopieerd naar vereiste mappen onder de juiste naam. In de map voor de 2014-versie - alleen de "light" dll zonder achtervoegsel, in de map voor versies 2015-2016 - "light" met het achtervoegsel "_light", "dark" - zonder achtervoegsel. Ik deed dit eerst, en daarna configureerde ik hetzelfde, maar dan in het WIX-installatieproject. Over het algemeen kunt u, hoe u het ook doet, het één keer configureren en dan hoeft u niet meer na te denken over waar en welke bestanden moeten worden gekopieerd en wat u een naam moet geven - alles gebeurt automatisch.
Hoe AutoCAD bepaalt welke DLL moet worden geladen:
- in versies tot en met 2014 wordt alleen de DLL met iconen waarvan de naam overeenkomt met de naam van het CIUX-bestand geladen. Er is bijvoorbeeld een bestand: "MyTools.cuix", pictogrammen voor dit bestand worden gezocht in het bestand "MyTools.dll".
- in versies 2015-2016 wordt voor het donkere schema een DLL geladen die overeenkomt met de naam CUIX, voor het lichte schema - de naam met het achtervoegsel "_light". Voorbeeld: "MyTools.cuix", iconen voor het donkere schema: "MyTools.dll", voor het lichte schema: "MyTools_light.dll".
Nog een niet voor de hand liggend punt. U kunt één ICO-bestand maken voor pictogrammen van 16x16 en 32x32. Om dit te doen, moet u twee overeenkomstige afbeeldingen in de ICO plaatsen. In de knopinstellingen is dezelfde afbeeldings-ID opgegeven voor de grote en kleine knoppen. AutoCAD kiest een pictogram afhankelijk van de grootte van de uitvoerafbeelding. Met deze techniek kunt u het aantal aanzienlijk verminderen ICO-bestanden in de C++-projectbronnen.

Over de kwestie van het gebruik van ico-bestanden. Alles is hier eenvoudig - lees het artikel Resource-dll gebruiken voor CUIx met transparante rasters. Eerlijk gezegd heb ik nog niet met zoiets gespeeld, maar ik zal Dima geloven.
===
Toegevoegd:
Citaat uit het artikel over het verbinden van ico-bestanden:

Voeg eenvoudigweg een nieuwe ico-bron toe met behulp van de Visual Studio-editor en bewerk de “ICO”-broneigenschappen in “RCDATA” zoals hieronder weergegeven:

Naast het opslaan van bronnen in een .EXE-bestand, kan een Delphi-ontwikkelaar ook een dynamische bibliotheek maken die alleen bronnen bevat. Laten we kijken hoe we dit kunnen doen.

Resources kunnen standaard of door de gebruiker gedefinieerd zijn. De gegevens in een standaardbron beschrijven het pictogram, de cursor, het menu, het dialoogvenster, de bitmap, het uitgebreide metabestand, het lettertype, de sneltoetstabel, tekenreeksen en de versie. Door gebruiker gedefinieerd de bron kan alle gegevens bevatten die nodig zijn voor de toepassing (andere.EXE, GIF, MP3, enz.).

Dynamische bibliotheken bevatten algemene code of bronnen die door meerdere applicaties kunnen worden gedeeld.

Een DLL maken met bronnen

Te doen DLL alleen met resources moet u een leeg project maken en compileren DLL, dat koppelingen naar het bronbestand bevat .RES, dat uw bronnen bevat.

Volg dan deze stappen:

  1. Creëren R.C. een bestand waarin de bronnen worden beschreven die u erin wilt plaatsen DLL. Zoals in het voorbeeld: ( adpdllbronnen- Naam R.C. bestand ASCII) - een ICON en één GIF toegevoegd aan R.C. bestand:
  2. adpdllresources.rc aboutlogo RCDATA aboutlogo.gif fabriek ICON FACTORY.ICO
  3. Compileren R.C. bestand binnen RES bestand met behulp van de resourcecompiler BRCC32
  4. Maak een leeg project DLL. Bewaar het als adpResources.dpr- na compilatie DLL zal een naam hebben adpResources.dll. Volledige code project DLL zal slechts vier regels in één bestand bevatten.
  5. bibliotheek adpResources; ($R adpdllresources.RES) begin einde.
  6. Stel uw DLL(zorg ervoor dat adpdllresources.res bevindt zich in dezelfde map als het project DLL

Zodra DLL met bronnen worden gemaakt, kunt u deze binnen uw eigen Delphi-applicaties. Houd er rekening mee dat deze bronnen zich binnenin bevinden DLL kan elke applicatie gebruiken (niet noodzakelijkerwijs Delphi).

Hoe bronnen van DLL's te gebruiken

Om bronnen te gebruiken van dynamische bibliotheek, gewoon downloaden DLL en de bronnen die u wilt gebruiken.

Volg deze stappen:

  1. Maak een nieuwe Delphi-project. Standaard voegt Delphi één formulier toe aan het project. Sla het project op
  2. Kopiëren DLL met middelen ( adpResources.dll naar de map waarin uw nieuwe aanvraag is opgeslagen
  3. Download de bron zoals hieronder...

Voorbeeld van hoe u een pictogram uploadt fabriek en schilder het op canvas Vorm1, Wanneer Knop 1: T-knop is ingedrukt).

Procedure TForm1.Button1Click(Afzender: TObject); const resICON = "fabriek"; var h:THandle;

Icoon: HIcon; begin h:= LoadLibrary("adpResources.DLL"); GIF probeer als h 0 en begin dan Icon:= LoadIcon(h, resICON); GIF TekenIcon(Canvas.Handvat, 10, 10, Pictogram); DLL end else begin ShowMessage("Bron-DLL laden mislukt!");

einde; eindelijk FreeLibrary(h);

einde; einde;


AutoCAD gebruikt het CUIX-formaat al lang als gedeeltelijke menubestanden, een regulier archief waarvan de extensie is hernoemd van ZIP naar CUIX. Ons bedrijf gebruikt echter AutoCAD 2009 SP3, dat niet met CUIX kan werken, maar een ouder formaat gebruikt: CUI-bestanden, waarvan de inhoud wordt gepresenteerd in XML-formaat.

Over versies van AutoCAD en MS Visual Studio (kleine uitweiding van het algemene onderwerp)

Om te schrijven gecontroleerd plug-in voor AutoCAD kunt u elke versie van MS Visual Studio gebruiken, die de mogelijkheid heeft om beheerde code te compileren voor de versie van het .NET-platform (2.0, 3.0, 3.5, 4.0, 4.5) die wordt gebruikt in de versie van AutoCAD die interesseert ons. De doelversie van .NET Framework wordt vermeld in configuratiebestand acad.exe.config en indien gewenst kunnen wij deze opnieuw toewijzen.

Voor schrijven oncontroleerbaar ARX ​​plug-ins voor AutoCAD 2009, u kunt ook elke versie van MS Visual Studio gebruiken, maar alleen op voorwaarde dat de computer dat heeft build tools-versie, wat vereist is voor uw versie van AutoCAD en deze tools zijn beschikbaar voor gebruik in uw IDE. Om bijvoorbeeld een ARX-plug-in voor AutoCAD 2009 te schrijven, hebt u de versie van de tools nodig die aanwezig zijn in MS Visual Studio 2005. In feite kunt u nieuwere versies van de opgegeven IDE gebruiken, op voorwaarde dat de projectinstellingen zijn opgegeven vereiste versie hulpmiddelen die moeten worden gebruikt bij het bouwen van het project:


Om de vervolgkeuzelijst Eigenschappen te openen Platformtoolset er was een reeks elementen waarmee je kon selecteren de vereiste versie tools, deze tools moeten vooraf zijn geïnstalleerd. Die. Alle versies van MS Visual Studio waarvan u de tools voor de constructie wilt gebruiken, moeten op uw computer zijn geïnstalleerd. In dit geval blijkt dat u feitelijk in een nieuwere IDE werkt, waarbij u gebruik maakt van de voordelen en gemakken ervan, en achter de schermen wordt de code samengesteld door de tools van de versie die u opgeeft in uw projectinstellingen.

Versies van MS Visual Studio moeten worden geïnstalleerd in opeenvolgende volgorde, beginnend bij meer oude versie en eindigend met een nieuwere om verschillende soorten conflicten te vermijden. Vergeet na het installeren van de volgende versie van de IDE niet de updatepakketten te installeren.

Standaard “ziet” en toont MS Visual Studio 2012 in de vervolgkeuzelijst Platform Toolset alleen tools uit VS 2012, 2010 en 2008. Om oudere versies van de IDE in de lijst weer te geven, moet u uitvoeren elk (die. een van) uit de volgende acties:

  • Installeer het MSI-pakket, met dank aan Owen Wengard.
  • Voer de handmatige configuratie uit zoals aangegeven.
Wanneer het er echter op aankomt DLL-creatie resource-bestand, dan is alles veel eenvoudiger: compileer het bestand één keer (met behulp van een willekeurige versie van de tools), met de Release Win32-configuratie, en gebruik het vervolgens op x86\x64-platforms (ik heb de x86 DLL gecompileerd en tegelijkertijd in Windows 7 x64 mijn CUI-bestand heeft er met succes afbeeldingen uit geëxtraheerd).
Een resource-DLL-bestand maken

Maak in MS Visual Studio 2012 een nieuw project op basis van de sjabloon Leeg project en wijs het de gewenste naam toe:


Allereerst installeren we meteen de configuratie in Release Win32:

Nu in het raam Oplossingsverkenner klik met de rechtermuisknop op de projectnaam en selecteer het item in het contextmenu dat verschijnt Eigenschappen. Het toekennen van de vereiste waarden aan eigenschappen Doelextensie En Configuratietype:



Ook al is het DLL-bestand gebouwd voor de CUI die in AutoCAD 2009 zal worden gebruikt, in de eigenschap Platformtoolset versie opgegeven v110, overeenkomend met Visual Studio 2012, niet v80(Visual Studio 2005-tools), die nodig zouden zijn om ARX-plug-ins voor deze versie van AutoCAD te compileren.


Bovendien moet u in de projectinstellingen nog een optie wijzigen: Geen toegangspunt:


Nadat u de hierboven aangegeven wijzigingen heeft aangebracht, drukt u op de knop Toepassen En OK. Nu zijn de eigenschappen van ons nog lege project correct geconfigureerd. Op het tabblad Oplossingsverkenner Selecteer het item in het projectcontextmenu Toevoegen -> Nieuw artikel... en in het dialoogvenster dat verschijnt, selecteert u de bronbestandsjabloon:



U kunt elke naam aan het bestand toewijzen, in ons voorbeeld laten we het staan resource.rc. Druk op de knop Toevoegen. Het bestand dat we hebben toegevoegd, bevat een lijst met afbeeldingen die in onze CUI-bestanden zullen worden gebruikt.

Nu zullen we in onze projectmap handmatig een submap aanmaken waarin we alle afbeeldingsbestanden zullen kopiëren die we aan het DLL-bestand willen toevoegen. De naam van de submap kan willekeurig zijn, laten we hem zo noemen afbeeldingen. Op het tabblad Oplossingsverkenner selecteer het item in het projectcontextmenu Open map in Verkenner:



Maak in het Explorer-venster dat wordt geopend een submap afbeeldingen en kopieer alle BMP-bestanden die we nodig hebben erin.

Laten we als experiment BMP-bestanden van verschillende formaten toevoegen: 16x16, 24x24, 32x32, 48x48, 64x64 en 128x128. Knoppen op toolpaletten moeten 16x16 afbeeldingen bevatten, terwijl knoppen op lintpaletten groter zijn. In ons test-CUI-bestand zullen we hier en daar knoppen met de bovenstaande resoluties plaatsen om het resultaat van het gebruik van verschillende formaten te zien.

Het zou mogelijk zijn om bestanden in PNG-formaat te kopiëren, maar AutoCAD 2009 kan geen afbeeldingen van dit formaat gebruiken in CUI-bestanden. Laten we nu teruggaan naar onze IDE: p ga naar het tabbladBronweergave.



Vanuit het contextmenu van een element resource.rc bel het artikel Bron toevoegen...


In het dialoogvenster Bron toevoegen op de lijst Brontype selecteer een element Bitmap, druk op de knop Importeren... en specificeer BMP-bestanden uit de submap die we eerder hebben gemaakt afbeeldingen. We krijgen het volgende resultaat:


Nu voor iedereen waarde van elementeigenschap Identiteitskaart moeten worden gescheiden door dubbele aanhalingstekens, zodat ze met succes kunnen worden gebruikt in onze CUI-bestanden:


Dat is alles, laten we nu ons DLL-bestand compileren:


Laten we eens kijken naar het rapport over de compilatieresultaten:


En hier is onze langverwachte DLL:

We kopiëren het resulterende DLL-bestand naar dezelfde map waar ons CUI-bestand is opgeslagen en geven ze dezelfde namen: test.cui En test.dll. Nu kunt u in het CUI-bestand ons DLL-bestand gebruiken als bron van BMP-pictogrammen, waarbij u opdrachten aan ons CUI-bestand toewijst (zie eigenschappen Kleine afbeelding En Grote afbeelding) en vervolgens de waarde van het onroerend goed Identiteitskaart, voorheen gescheiden door dubbele aanhalingstekens:


Pictogrammen gespecificeerd in de eigenschap Kleine afbeelding zal worden gebruikt op paletten Werkbalk, en die aangegeven voor Grote afbeelding - gebruikt bij Lintje.

Houd er rekening mee dat dit op ons paneel staat Een of andere werkbalk ze worden allemaal weergegeven BMP-afbeeldingen behalve de laatste - degene waarvan de afmetingen 128x128.

Een dll-bestand maken

Heel vaak zul je in je werk een dergelijke situatie tegenkomen.

Je staat voor een taak, je moet een programma schrijven " Super Kladblok" die alle functies moet behouden standaard notitieblok, maar hebben tegelijkertijd een aantal extra functies, waardoor de gebruiker bij het kiezen van een programma voor het werken met tekst de voorkeur zal geven aan uw programma. Om dit te doen, werd besloten om verschillende nieuwe functies toe te voegen, waarvan er één verantwoordelijk zal zijn voor het tellen en weergeven van het aantal woorden in de tekst.

Een paar weken later werd het programma geschreven en vervolgens op internet verschenen, gebruikers waardeerden het nieuw product en begon het te gebruiken. Het doel is bereikt.

De tijd verstrijkt en je krijgt een nieuwe taak: een programma schrijven " Superparser"Een van de functies van dit programma zal het tellen van woorden in de tekst zijn. Je begrijpt dat je opnieuw een methode zult moeten ontwikkelen die woorden telt. Maar tegelijkertijd herinner je je dat ze nog niet zo lang geleden een programma hebben ontwikkeld waarin deze functie. Om het wiel niet opnieuw uit te vinden, open je de broncode van het programma” Super notitieblok"; en kopieer de volledige methode naar de broncode van het nieuwe programma " Superparser". Geweldig, nu hoef je geen tijd meer te verspillen aan het opnieuw schrijven van deze methode, en kun je meer tijd besteden aan de rest van de programma-elementen. Probleem opgelost.

Maar wat als de methode voor het tellen van woorden niet door u is geschreven, maar door bijvoorbeeld een collega en u om de een of andere reden geen toegang hebt tot broncode programma's " Super notitieblok". Dat wil zeggen dat de eerste optie, het kopiëren van de methode van de bron, niet zal werken en deze methode Ik zal het zelf moeten schrijven, mmm, verdriet.

Maar dan belt je collega je op en zegt: Weet je, ik herinnerde me dat ik, toen ik deze methode aan het ontwikkelen was, dacht dat ik het misschien ergens anders zou moeten gebruiken, en om deze reden besloot ik het in een aparte assembly te plaatsen, in de vorm van een dynamisch bibliotheekbestand (dll). Kopieer dit bestand dll in uw project en sluit deze aan als een externe assembly, waarna u toegang krijgt tot mijn werkwijze en deze kunt gebruiken.

Geweldig! Je voert alle beschreven acties uit in het programma “ Superparser verschijnt gewenste methode, is het probleem opgelost en hoef je de code opnieuw niet met de hand te herschrijven.

Dit concludeert het gezegde en nu gaan we verder met een meer gedetailleerde studie.

Wat is DLL

DLL(dynamic-link bibliotheek) is een dynamische linkbibliotheek, of kortweg dynamische bibliotheek.

Zoals ik eerder schreef, kun je met dynamische bibliotheken eerder geschreven code hergebruiken, en ze zorgen ook voor een betere overdraagbaarheid van code. Het is voldoende om het bestand over te zetten naar een flashstation, of dll downloaden bestand van internet, voeg het vervolgens toe aan het huidige project en ontvang onmiddellijk een reeks verschillende extra functies voor uw toepassing. Het is ook de moeite waard om dat in één te weten dll-bestand Er kan een willekeurig aantal typen, leden en naamruimten worden opgeslagen.

Een dll-bestand maken

Laten we eerst het type nieuw selecteren de applicatie die wordt gemaakt, of beter gezegd: het project.

Kiezen Klassenbibliotheek, dat wil zeggen dat we een dynamisch bibliotheekbestand (dll) maken

U kunt ook opgeven voor welke versie van het Framework dit project wordt gemaakt.

Nadat Visual Studio het projectskelet heeft gemaakt, ziet u het volgende:

Dit is hoe het Solution Explorer-venster eruit zal zien

En dit is hoe het eruit zal zien werkgebied, waar u gewoonlijk programmacode schrijft

En dus wordt de naamruimte gegeven: Auto en klasse: Klasse1. Klasse1 is geen goede naam. Laten we onze code een beetje veranderen, Klasse1 vervangen door BMW, en een methode toevoegen die de naam van onze klasse afdrukt.

En dus is de code geschreven, en nu is het nodig om te compileren om de assembly te krijgen.
Als u nu op F5 of Ctrl+F5 probeert te drukken, ziet u dit venster


Deze fout geeft alleen aan dat er een dynamisch bibliotheekbestand is gemaakt ( dll), in plaats van een uitvoerbaar bestand (exe), dat niet kan worden uitgevoerd.

Om het project te compileren, drukt u op de F6-toets, waarna het bestand Car.dll in de map bin\Debug verschijnt.

Om te controleren of het bibliotheekbestand is aangemaakt, gebruikt u de knop Toon alle bestanden op het tabblad Solution Explorer

De assembly, in de vorm van een dynamisch bibliotheekbestand, is met succes gemaakt.

Laten we nu naar de map bin\Debug gaan, om snel naar de huidige projectmap te gaan, gebruik in dezelfde Solution Explorer het item Open map in Windows Verkenner

Kopieer het resulterende montagebestand (in ons geval het bestand Car.dll) naar een tijdelijke map. In feite is dit niet nodig, u kunt vertrekken dit bestand in deze map, maar laten we voor het gemak creëren nieuwe map en plaats het gemaakte bibliotheekbestand daar.

Vervolgens sluiten we het huidige project en maken we een nieuw project. Maar deze keer selecteren we het projecttype: consoletoepassing.

Laten we een nieuw project maken.

Er is een nieuw project aangemaakt. Laten we nu onze bibliotheek (Car.dll) verbinden met het huidige project

Dll aansluiten

Om dit op de map te doen Referenties, in het Solution Explorer-venster moet u met de rechtermuisknop klikken en Referentie toevoegen selecteren. Het volgende venster wordt geopend:

  1. Selecteer het tabblad Bladeren
  2. Geef de map op waarin het gemaakte bibliotheekbestand zich bevindt (in ons voorbeeld - Car.dll)
  3. Selecteer een bestand de benodigde bibliotheek en druk op de knop OK;
Als alles correct is gedaan, ziet u de volgende afbeelding

Het laat zien dat een link naar onze Car.dll-assembly, waarin onze IL-code is opgeslagen, met succes aan ons huidige project is toegevoegd. Ik hoop dat je je herinnert dat na het compileren alle code die je schrijft, wordt omgezet in tussencode in IL (CIL, MSIL - dit is hetzelfde). U kunt ook zien dat een kopie van onze bibliotheek in de map bin\Debug is geplaatst.

Als u plotseling bent vergeten welke naamruimte, typen of leden uw gemaakte bibliotheek bevat. U kunt altijd een Visual Studio-tool zoals Objectbrowser. Om dit te doen, gaat u naar het tabblad Solution Explorer, opent u de map Referenties en klikt u eenvoudig met de rechtermuisknop op de bibliotheek die u eerder hebt toegevoegd. In ons geval herinner ik u eraan: dit is het bestand (Car.dll) en selecteer Bekijken in de objectbrowser, een venster zoals dit zal verschijnen.

In het Object Browser-venster kunt u de inhoud van onze assembly bekijken.

De assembly is verbonden en nu kunt u met de inhoud ervan werken. Laten we vervolgens de optionele stap voltooien.

Laten we gebruiken toevoegen trefwoord met behulp van de Car-naamruimte uit de Car.dll-bibliotheek die we hebben gemaakt, waarna we een object van de BMW-klasse zullen maken en de Output_Class_Name() -methode zullen uitvoeren.

Resultaat:

Alles werkt.

En dus nogmaals op volgorde:

  1. Maak een dynamisch bibliotheekbestand (dll).
  2. Cos aansluiten deze bibliotheek aan ons project door een link naar ons dll-bestand toe te voegen aan de map Referenties.
  3. (Optioneel) We verbinden de naamruimte van de verbonden assembly met behulp van het trefwoord Using, of gebruiken de volledige naam, dat wil zeggen Namespace.Type (Car.BMW).
  4. Winst
Deze vier stappen zullen je helpen creëren dll-bibliotheek en koppel deze aan uw project.

En uiteindelijk is er niet veel informatie over assemblagetypes:

Vergaderingen zijn er in de volgende hoofdtypen: algemeen en privé.

Privé-vergadering

Dit zijn bibliotheekbestanden, zoals ons eerder gemaakte Car.dll-bestand, die de hele tijd in de directory aanwezig zijn huidige applicatie of een van de submappen ervan.

Laten we teruggaan naar het begin van het artikel.

Nadat de applicatie “Super Parser” was gemaakt, ontvingen we de assembly in de vorm van een bestand (exe). Toen besloten we ons programma te testen en aan onze vriend te geven, en dat vermeld je ook als hij dat wil extra functies in het programma, dan hoeft hij alleen maar naast de zijne te staan exe-bestand plaats het Car.dll-bibliotheekbestand. Daarna kan hij woorden in de tekst tellen. Dat wil zeggen dat de bibliotheek in dezelfde map wordt opgeslagen als het uitvoerbare bestand.

Gedeelde montage

Dit zijn assemblages die bedoeld zijn voor meervoudig gebruik verschillende toepassingen op één computer geïnstalleerd.

We hebben bijvoorbeeld twee programma's. Welke ons Car.dll-bestand zal gebruiken, om dit bestand niet naar elke map te kopiëren, kunnen we het op een speciale plaats plaatsen genaamd Global Assembly Cache - (GAC) of globale assembly-cache. Nu wordt de assembly op één speciale plaats opgeslagen en weten uw programma's altijd waar ze deze codebibliotheek kunnen vinden. Als we de privémethode zouden gebruiken, zouden we onze bibliotheek in elke map van de applicatie moeten plaatsen waarmee deze zou moeten communiceren.

Een DLL maken die alleen bronnen bevat

Het bronbestand moet worden gecompileerd - "rc MyResDll.rc" - en door een linker naar een DLL worden geconverteerd. Zorg ervoor dat u de vlag "/NOENTRY" specificeert, aangezien deze dynamische bibliotheek slechts één bron bevat en geen regel code: " link MyRedDll.res /DLL / NOENTRY".

In Visual Studio is dit zelfs nog eenvoudiger: klik gewoon op de map "Bronnen" in het "venster" Bestandsweergave" en toevoegen nieuw bestand bron, die vervolgens kan worden gewijzigd visuele redacteur naar eigen inzicht.

Om een ​​bron uit een DLL te laden, kunt u in principe de LoadLibray-functie gebruiken die we al kennen, en de LoadString-descriptor doorgeven die erdoor wordt geretourneerd, of een andere functie die met bronnen werkt. Het laden van een dynamische bibliotheek kan echter aanzienlijk worden versneld als we aan het systeem “uitleggen” dat deze DLL alleen maar bronnen bevat, en dat we deze alleen maar in de procesadresruimte hoeven te projecteren, en dat we voor al het andere zelf kunnen zorgen. .

Dit is waar de functie LoadLibraryEx van pas komt: het eerste argument specificeert, net als zijn collega LoadLibrary, de naam van de dynamische bibliotheek die moet worden geladen, het tweede is gereserveerd en moet gelijk aan nul, en de derde, die gelijk is aan LOAD_LIBRARY_AS_DATAFILE, dwingt de functie om precies te doen wat we nodig hebben: de DLL laden als een database (als de dynamische bibliotheek naast bronnen ook code bevat, is het laden met deze sleutel nog steeds succesvol, maar de functies van de geladen DLL zijn niet beschikbaar - alleen bronnen):

#erbij betrekken

#erbij betrekken

h=LoadLibraryEx("MijnResDll.dll",0,

LAAD_LIBRARY_AS_DATAFILE);

LoadString(h,1,&buf,99);

printf("%s\n",&buf);

Demonstratie van geoptimaliseerd DLL-laden met niets anders dan bronnen

Dit programma compileert op precies dezelfde manier als de voorgaande voorbeelden van expliciet koppelen - en wanneer het wordt uitgevoerd, wordt triomfantelijk "Hallo, Word!" weergegeven, wat bevestigt dat de "string" -bron uit de dynamische linkbibliotheek met succes is geladen! Op een vergelijkbare manier kunt u bronnen downloaden van uitvoerbare bestanden; vanuit dit oogpunt verschillen ze niet van dynamische bibliotheken.

OOP en DLL

#include "stdafx.h"

DWORD ul_reason_for_call,

LPVOID lpGereserveerd

//Onze code.

//Voeg de Add-functie toe.

als(a>b) res = a; anders res = b;

De meester heeft voor ons een sjabloon gemaakt voor onze dll. Wij zullen het ontwikkelen. Voeg hiervoor 1 functie en één klasse met een methode toe. Hier is de code:

#include "stdafx.h"

BOOL APIENTRY DllMain (HANDVAT hModule,

DWORD ul_reason_for_call,

LPVOID lpGereserveerd

//Onze code.

//Voeg de Add-functie toe.

Declspec(dllexport) int Add(int a, int b)

//Voeg de MyClass-klasse toe met de MyMax-methode.

Declspec(dllexport) int MyMax(int ​​a, int b)(

als(a>b) res = a; anders res = b;

Houd er rekening mee dat wanneer u functies en methoden toevoegt die we extern willen aanroepen, u deze schrijft met de modifier __declspec(dllexport). Op deze manier markeren we de zogenaamde geëxporteerde functies.

Laten we het programma compileren. Het bestand firstdll.dll zou in de debug-map van het project moeten verschijnen.

Nu schrijven we een testprogramma.

#erbij betrekken

//Neem het vereiste headerbestand op.

#include "..\eerstedll.cpp"

uit<

uit<

Laten we het programma starten. Zoals je zou verwachten, worden 22 en 11 afgedrukt.

DllMain-functie

De meeste DLL's zijn eenvoudigweg verzamelingen van in wezen onafhankelijke functies die worden geëxporteerd naar en gebruikt door applicaties. Naast functies die bedoeld zijn voor export, heeft elke DLL een DllMain-functie. Deze functie is ontworpen om een ​​DLL te initialiseren en op te schonen. Het vervangt de LibMain- en WEP-functies uit eerdere versies van Windows. De structuur van de eenvoudigste DllMain-functie zou er als volgt uit kunnen zien:

BOOL WINAPI DllMain (HANDLE hInst,DWORD dwReason, LPVOID IpReserved) (

BOOL bAllWentWell=TRUE;

schakelaar (dwReason) (

case DLL_PROCESS_ATTACH: // Procesinitialisatie.

case DLL_THREAD_ATTACH: // Initialiseer de thread.

case DLL_THREAD_DETACH: // Draadstructuren wissen.

case DLL_PROCESS_DETACH: // Processtructuren opschonen.

if(bAllWentWell) retourneert WAAR;

anders retourneert FALSE;

De functie DllMain wordt in verschillende gevallen aangeroepen. De reden voor het aanroepen ervan wordt bepaald door de parameter dwReason, die een van de volgende waarden kan aannemen.

De eerste keer dat een proces een DLL laadt, wordt de functie DllMain aangeroepen met dwReason gelijk aan DLL_PROCESS_ATTACH. Elke keer dat een proces een nieuwe thread maakt, wordt DllMain aangeroepen met dwReason gelijk aan DLL_THREAD_ATTACH (behalve voor de eerste thread, omdat in dit geval dwReason gelijk is aan DLL_PROCESS_ATTACH).

Wanneer het proces klaar is met het werken met de DLL, wordt de functie DllMain aangeroepen met de parameter dwReason gelijk aan DLL_PROCESS_DETACH. Wanneer een thread wordt vernietigd (behalve de eerste), is dwReason gelijk aan DLL_THREAD_DETACH.

Alle initialisatie- en opschoonbewerkingen voor processen en threads die de DLL nodig heeft, moeten worden uitgevoerd op basis van de dwReason-waarde, zoals weergegeven in het vorige voorbeeld. Procesinitialisatie is doorgaans beperkt tot het toewijzen van bronnen die worden gedeeld tussen threads, zoals het laden van gedeelde bestanden en het initialiseren van bibliotheken. Thread-initialisatie wordt gebruikt om modi te configureren die alleen specifiek zijn voor een bepaalde thread, bijvoorbeeld om lokaal geheugen te initialiseren.

Een DLL kan bronnen bevatten die geen eigendom zijn van de toepassing die deze aanroept. Als DLL-functies op DLL-bronnen werken, zou het uiteraard handig zijn om ergens uit de weg een hInst-ingang op te slaan en deze te gebruiken bij het laden van bronnen uit de DLL. De IpReserved-aanwijzer is gereserveerd voor intern Windows-gebruik. De aanvraag mag er daarom geen aanspraak op maken. Je kunt alleen de betekenis ervan controleren. Als de DLL dynamisch is geladen, is deze NULL. Bij statisch laden is deze pointer niet nul.

Als dit lukt, moet de functie DllMain TRUE retourneren. Als er een fout optreedt, wordt FALSE geretourneerd en wordt verdere actie beëindigd.

Opmerking. Als u niet uw eigen DllMain()-functie schrijft, gebruikt de compiler de standaardversie, die eenvoudigweg TRUE retourneert.

Voorbeeld probleem:

HANDVAT hDraad; DWORD dwThreadId;

schakelaar(fdwReden)

geval DLL_PROCESS_ATTACH:

// De DLL wordt toegewezen aan de procesadresruimte

// maak een thread om wat werk te doen

hThread = CreateThread(NULL, 0, SomeFunction, NULL, 0, &dwThreadId);

// vertraag onze thread totdat de nieuwe thread is voltooid

WaitForSingleObject(hThread, INFINITE);

// toegang tot de nieuwe thread is niet langer nodig

SluitHandle(hThread);

geval DLL_THREAD_ATTACH:

// er is een nieuwe thread gemaakt

geval DLL_THREAD_DETACH:

// draad wordt correct beëindigd

geval DLL_PROCESS_DETACH:

// DLL wordt verwijderd uit de procesadresruimte

De ingangspuntfuncties mogen alleen eenvoudige initialisatietaken uitvoeren. Ze mogen de functie LoadLibrary of LoadLibraryEx (of een functie die deze functies aanroept) niet aanroepen, omdat hierdoor afhankelijkheidslussen kunnen ontstaan ​​in de laadvolgorde van de DLL. Dit kan het gevolg zijn van het feit dat de DLL wordt gebruikt voordat het systeem de initialisatiecode heeft uitgevoerd. Op dezelfde manier mag de entrypuntfunctie de FreeLibrary-functie (of een functie die deze aanroept) niet aanroepen, omdat dit ertoe kan leiden dat de DLL in gebruik wordt genomen nadat het systeem de exitcode heeft uitgevoerd.

Voorbeeld van Microsoft. Stap voor stap handleiding. Een DLL (C++) Visual Studio 2013 maken en gebruiken

In deze walkthrough wordt beschreven hoe u een Dynamic Link Library (DLL) maakt voor gebruik met een C++-toepassing. Het gebruik van een bibliotheek is een goede manier om code opnieuw te gebruiken. In plaats van dezelfde procedures in elk programma opnieuw te implementeren, maakt u ze één keer en verwijst u er vervolgens naar vanuit andere toepassingen. Door de code in een DLL te plaatsen, bespaart u ruimte in elke toepassing die naar de code verwijst, en kunt u de DLL ook bijwerken zonder alle toepassingen opnieuw te compileren. Zie DLL's in Visual C++ voor meer informatie over DLL's.