Versie-informatie voor toepassingen toe te voegen




In dit artikel onderzoek ik de manieren waarop de versie-informatie in een applicatie beschikbaar kan worden gesteld, het schrijven van een klasse die in alle nieuwe ontwikkelingen kunnen worden opgenomen.



versie-informatie toepassingen toevoegen



Het laatste artikel heb ik gesproken over het concept van een generatie, en omdat een standaard proces om een ​​consistente set van resultaten te produceren was een goede zaak.

Als de oudste computerprogramma's zijn ingezet, de ontwikkelaars wilden een manier om te bepalen welke versie van een client draait is hebben; immers, het is natuurlijk handig om te weten als u de melding van een bug die al is opgelost. Vrij snel (en uiteraard) een numeriek systeem ontwikkeld door simpelweg het verhogen van het versienummer telkens een versie werd gemaakt. Aangezien de frequentie van de emissie toeneemt, de ontwikkelaars wilde een manier om een ​​belangrijke nieuwe release tegenover voorlopige te onderscheiden zijn: het concept van grote en kleine versies van een programma ingevoerd - gaande van V1.12 naar V2.0 overgedragen veel meer (zelfs voor gebruikers leggen) die gaan van V12 tot V13. Gedurende vele jaren grote en kleine versie was voldoende en triviaal, maar als programma werd groter en complexer vaker moet bug-fix een hoger aantal is geplakt aan het einde van de versie geven een "release". Alle versies met dezelfde major en minor versienummers moet een lijst van identieke kenmerken hebben, maar moet ook bug fixes en andere verbeteringen cumulatieve zonder toevoeging van nieuwe functies als zodanig. De laatste tijd is het uitgegroeid tot een goed idee om het buildnummer van de release wat resulteert in een volledige versie nummer van de vier componenten, XYZB, waarbij X staat voor de grote versie, de kleine versie Y, Z het aantal B-versie en build-nummer toe te voegen. Merk op dat, hoewel de kleine en release-versies kunnen worden gewist (met grote en kleine versies), is het buildnummer nooit op nul te zetten en dan stijgt meer met elke nieuwe versie (hoewel niet per se strikt incrementele, maar het is heel goed mogelijk om te hebben bouwen intern binnen een bedrijf die niet worden vrijgegeven aan de klant). Listing 1 toont bij elke component versienummer moet worden opgehoogd.

Component Beschrijft Wanneer toenemen




X Grote Na werden belangrijke wijzigingen aangebracht in de vraag


Y Minder Na de nieuwe functies zijn toegevoegd aan de applicatie


Z Op de markt Elke keer dat een minor release ter beschikking wordt gesteld met bug fixes


B Bouwen Elke keer dat het proces van het genereren van volledige



Listing 1 - Onderdelen van het versienummer XYZB



Hoewel marketingafdelingen gekaapt het concept van versienummers voor hun eigen doeleinden, als het eenmaal is gerealiseerd, dat een groot aantal mensen die investeren in upgrades, toen de grote versie nummer veranderd of overbrugd de competitie is nog altijd zeer bruikbaar een soort van een formele versienummer in uw applicaties - het is veel makkelijker om te bevestigen dat de client wordt uitgevoerd Build 134 of hoger, in plaats van "SuperApp 97 SR-2a Patch 13 (Y2K)". Dit is vooral belangrijk met de komst van gedeelde DLL in Windows die kunnen worden vervangen door een nieuw geïnstalleerde toepassing geworden. Hoewel het niet erg goed in het gebruik van de nummering consistent, vrijwel alle Microsoft applicatie-bestanden (EXE en DLL) bevatten nu een soort van een versienummer 4 cijfers ingebouwd in hen. In feite, Windows 2000 maakt uitgebreid gebruik van deze informatie, in een poging om belangrijke systeembestanden van wordt voordat overschreven, of soms latere versies voorkomen. De installatie procedures gebruik van deze informatie door de waarschuwing maken ook wanneer een bestand een versie soortgelijke naam kon overschrijven, maar later zelf.



Embedded Versie-informatie

Als je rechts klikt op een EXE-of DLL-bestand in de Windows Verkenner pop-up menu dat verschijnt heeft een stem op de bodem genaamd "Eigenschappen". Door dit te selecteren toont een aantal details over het bestand. Indien beschikbaar, het tweede tabblad (de zogenaamde versie) geeft het ingebed in het bestand over het versienummer, de naam van het product, designdetails en zo verder informatie. Elk bestand dat een segment van de bron kan hebben kan deze informatie ingebed in zich hebben, en dit omvat applicaties die gebouwd zijn met Delphi. Microsoft heeft de gegevens en de vorm die in de bron sectie moeten worden voorzien om deze informatie te bekijken gepubliceerd. In Delphi 2, de enige manier waarop dit kan worden bereikt was de oprichting van een bronbestand met precies de juiste snaren binnen het, compileren afzonderlijk met de resource compiler en dan het inpluggen van de applicatie (dit deel de vorming proces van lead generation). Hoewel het niet moeilijk is, deze procedure vereist een niveau van technische kennis en vaardigheden zodanig dat sommige ontwikkelaars de moeite genomen om dit te doen. Binnen ethos is om de ontwikkeling van Windows productiever te maken, Delphi 3 introduceerde een speciaal dialoogvenster waarin deze gegevens gemakkelijk kunnen worden bij de aanvraag gevoegd. Figuur 1 toont dit dialoogvenster, beschikbaar via het menu Delphi Project, Opties punt.



Door het selectievakje aan de bovenkant van de kaart aan dat de informatie over het versienummer tonen moet worden opgenomen, kunt u de details toe te voegen, niet alleen over het versienummer, maar ook de vlaggen op het feit dat de build is bedoeld voor publieke release, en aan de onderkant kunt u informatie toevoegen aan een hele lijst van vooraf gedefinieerde categorieën, zoals een beschrijving van het bestand en het auteursrecht. Delphi categorie FileVersion automatisch de versie van de module numerieke gegevens hierboven bijgewerkt. Als dit dialoogvenster wordt bevestigd, Delphi bouwt de benodigde bronbestanden (waarin ook details zoals het pictogram van de toepassing) in een transparante overgang, die automatisch wordt gekoppeld aan de uiteindelijke executable. Als je dit op zelfs de eenvoudigste project zult u zien dat u kunt nu met de rechtermuisknop op het uitvoerbare bestand en de versie-informatie, net als Windows-applicaties allemaal goed gedragen.



Welke versie ben ik?

Nu we weten hoe we de informatie over de versie van de toepassing te plaatsen, zou het echt nuttig om de toegang tot informatie zijn. Immers, als je probeert om te beslissen welke versie van de telefoon van een gebruiker wordt uitgevoerd, zou het veel gemakkelijker zijn om te beschrijven hoe het dialoogvenster Informatie te geven, in plaats van het vinden van de applicatie executable in Windows Verkenner, klik met de rechtermuisknop, kies Eigenschappen en selecteer het tabblad versie.



Sinds de versie-informatie alleen wordt opgeslagen als een string in een specifieke indeling in de sectie bron van de aanvraag, zou het mogelijk zijn om standaard Win32 resource file van commando's gebruiken om de relevante informatie te extraheren, decoderen structuren. Er zijn echter een speciale Win32 API commando's die enkel dat in veel handiger doen. Dit zijn GetFileVersionInfoSize (waar inlichtingen over de ruimte die nodig is om de versie-informatie op te slaan terug), GetFileVersionInfo (die de gegevens in een pre-geleverde buffer van de juiste maat haalt), en VerQueryValue (die een stuk van de naam van de versie-informatie van de extracten buffers, zoals "LegalCopyright"). Zoals gebruikelijk in de omgang met de Win32 API, moeten deze opdrachten worden genoemd in de juiste volgorde, met behoud van een aantal interne waarden geretourneerd door eerdere opdrachten met behulp van parameters var.



Het is een goed idee om elke vorm van interactie te kapselen met de Windows API met een meer gebruiksvriendelijke interface en Delphi. Typische Delphi programmeurs willen niet om te gaan met de toewijzing van het geheugen blokken en Win32-specifieke soorten zoals DWORD en UINT, mag ook niet. Veel beter om een ​​mooie klasse die, in de beste tradities van OO, verbergt de toegang tot de eerste versie en heeft een veel meer bruikbare ontwerpen. Dit heeft het voordeel dat de opslag van deze informatie niet moet veranderen versie dezelfde klasse kan de afhankelijkheden van het systeem in te kapselen, met behoud van dezelfde publieke interface.



Er zijn een paar dingen te overwegen bij het ontwerpen van deze klasse. In de eerste plaats moet kunnen worden gebruikt met elke toepassing, inclusief het waarvan deze draait. Ten tweede moet het gemakkelijk toegang tot de toetsen standaard en meest gebruikte versie-informatie (FileVersion, Artikelmodel etc) bieden. Tenslotte, hoe is het mogelijk voor de gebruiker om extra toetsen en waarden versie verschaffen in hun structuur, de klasse moeten deze bloot natuurlijke wijze. Listing 2 toont de openbare interface voor deze klasse.



TVersionInfo class =

private

GetVersionInfo functie (Index: Integer): String;

publiek

constructor Create (ThisSourceFile: String);

destructor Destroy; negeren;

// Informatie willekeurige sleutel

Belangrijkste eigenschap [KeyName: String]: String lezen GETKEY;

Key Information // standaard

Bedrijfsnaam eigenschap: String index 0 bed GetVersionInfo

schrijf SetVersionInfo;

FileDescription eigenschap: String index 1 bed GetVersionInfo;

FileVersion eigenschap: String index 2 bedden GetVersionInfo;

InternalName eigenschap: String index 3 bedden GetVersionInfo;

eigenschap Copyright: String index 4 bedden GetVersionInfo;

Handelsmerken eigendom: String index 5 bedden GetVersionInfo;

OriginalFileName eigenschap: String index 6 bedden GetVersionInfo;

Onroerend ProductName: String index 7 lezen GetVersionInfo

schrijf SetVersionInfo;

ProductVersion eigenschap: String index 8 Lees GetVersionInfo

schrijf SetVersionInfo;

Onroerend Reacties: String index 9 GetVersionInfo lezen;

VersieNummer eigenschap: String lezen GetBuildNumber;

eindigen;



Listing 2 - Openbare interface TVersionInfo



Zoals u kunt zien van de klasse, de namen van alle standaard toetsen, worden ze ontmaskerd als benoemde eigenschappen, terwijl de Key biedt u toegang tot extra informatie op maat van de naam. De klas wordt gebouwd door het passeren van een pad en de bestandsnaam van het bestand waaruit de volledige versie-informatie moet worden gehaald. Er is een zeer interessant aspect van deze klasse die een goede illustratie van een onderbenut aspect van klasse ontwerp Delphi met de identificatie-index naar een aantal verschillende eigenschappen op dezelfde toegang tot de functie in kaart. Zoals je kunt zien op de private uitvoering van GetVersionInfo gebruikt om het pand te lezen, wordt deze index waarde doorgegeven volgens de structuur te bereiken, waardoor de functie om te bepalen welke waarde terug. Zoals we in de uitvoering zullen zien, dit vergemakkelijkt vaak de codering zeer beknopt.



Zoals hierboven vermeld, de opdracht GetFileVersionInfo haalt de gegevens van de bron sectie en slaat ze in de buffer die als parameter de API oproep. Daarom is het zinvol om dit te doen als een one-off in de constructor. Zodra deze informatie is gehaald, kunnen we bekend voor de belangrijkste namen ondervragen. Handig voor het coderen en betere prestaties, halen we de belangrijkste waarden voor alle standaard sleutel namen en bewaar deze waarden in een array met dezelfde waarde als elke ordinale index van het pand. Dit betekent dat de uitvoering van de structuurfunctie van toegang GetVersionInfo eenvoudig en transparant kan eenvoudig de waarde van de array index ontvangen retourneert. Voor aangepaste toetsen die ook kan worden geleverd voor de eenvoud zullen we de API commando bellen om de gegevens te extraheren uit de buffer naar de versie-informatie. Hoewel dit iets langzamer dan rechtstreeks toegang tot gegevens van een vooraf berekende matrix zijn, wordt niet verwacht dat deze eigenschappen vaak wordt gebruikt en dit is derhalve een ontwerp aanvaardbaar beschikking. Listing 3 toont de uitvoering van de klas.



fabrikant TVersionInfo.Create (ThisSourceFile: String);

const

VersionKeyNames: Array = [0..MaxVersionKeys] naar String

('Bedrijfsnaam', 'FileDescription', 'FileVersion', 'InternalName',

'LegalCopyright', 'LegalTrademarks', 'OriginalFileName',

'Productnaam', 'ProductVersion', 'Reacties');

var

ThisInfo: Integer;

InfoLength: UINT;

Len: DWORD;

Handle: DWORD;

PCharset: PLongInt;

beginnen

Maak geërfd;

// Krijg de grootte van de versie-informatie

Len: = GetFileVersionInfoSize (PChar (ThisSourceFile), verwerken);

// VersionInfo Wijs buffergrootte

Setlength (versionInfo, Len + 1);

// Krijg versie-informatie

indien GetFileVersionInfo (PChar (ThisSourceFile), Handle, Len,

Pointer (versionInfo)) dan

beginnen

// Krijg vertaling informatie voor taal/charSet ID

indien VerQueryValue (PointerVersionInfo), '\ VarFileInfo \ Translation',

Pointer (PCharset), InfoLength) dan

beginnen

LangCharset: = Format ('%% .4x .4x',

[LoWord (PCharset ^), HIWORD (PCharset ^)]);

InfoAvailable: = true;

// Informatie over de standaard versie verkrijgen

voor ThisInfo: = 0 te maken MaxVersionKeys

StandardKeys [ThisInfo]: =

GETKEY (VersionKeyNames [ThisInfo]);

eindigen;

eindigen;

eindigen;



functie TVersionInfo.GetKey (ThisKeyName: String): String;

var

InfoLength: UINT;

beginnen

dan als InfoAvailable

beginnen

Setlength (Resultaat, 255);

indien VerQueryValue (Pointer (versionInfo)

PChar (Format ('\ StringFileInfo \% s \% s',

[LangCharset, ThisKeyName])), Wijzer (resultaat)

InfoLength) dan

beginnen

SetString (Resultaat, PChar (resultaat), InfoLength - 1);

eindigen de rest

beginnen

Resultaat: = '';

eindigen;

eindigen de rest

beginnen

Resultaat: = 'N/A';

eindigen;

eindigen;



TVersionInfo.GetVersionInfo functie (Index: Integer): string;

beginnen

Resultaat: = StandardKeys [Index];

eindigen;



Procedure TVersionInfo.SetVersionInfo (Index: Integer;

Waarde: string);

beginnen

StandardKeys [Index]: = Waarde;

eindigen;



TVersionInfo.GetBuildNumber functie: string;

beginnen

// Het laatste item strip op de versie van het bestand

Resultaat: = FileVersion;

terwijl Pos ('.', Result)> 0 doen

beginnen

Resultaat: = Copy ('.' Resultaat, Pos (, Resultaat) + 1, Lengte (resultaat));

eindigen;

eindigen;



Een van de nuances van de manier waarop de versie-informatie wordt opgeslagen in de bron sectie van de applicatie is dat je kunt bepalen welke tekenset taal werd gebruikt om de versie-informatie (en de toepassing of DLL-bestand zelf) te creëren. Dit is gedefinieerd binnen de versiegegevens als dubbel woord of 32-bits geheel getal zonder teken, en aanwezig als deel van de reeks versiegegevens (in hexadecimale notatie) voor elke sleutel die geëxtraheerd zijn. Een van de taken van de fabrikant, alsmede extract de versie-informatie in een string buffer (een handige manier om statische gegevens geretourneerd door de API-aanroepen te slaan) is om de taal en tekenset informatie uit te halen, en een hex correcte string te bouwen die gebruikt zullen worden in de toekomst noemt VerQueryValue. Zodra dit gedaan is, de fabrikant maakt vervolgens een oproep aan de routine die eigenlijk een waarde versie-informatie voor een sleutel terug. Deze routine leeft een dubbel leven, ook vermomd als een functie van de toegang tot de Key pand. Nogmaals, een interessant aspect van dit proces is dat de aannemer krijgt een lijst met standaard sleutel namen uit een array van strings dat particuliere vaste constante wordt gedeclareerd en gedefinieerd in een enkele verklaring. Ook dit is een weinig gebruikt maar zeer bruikbare techniek, die ook toegestaan ​​voor globale variabelen en constanten.



Als u verwijzen naar figuur 1, kunt u een aantal gegevens in verschillende versies in de groep met de naam zien "attributen Module", in wezen een set van vlaggen die de toestand te beschrijven van de toepassing, als het een debug build of prive, en ga zo maar door . Deze informatie is ook beschikbaar in het bronbestand, en kunnen worden geopend met behulp van het commando API VerQueryValue, maar met een tweede parameter van slechts "" in plaats van "\ VarFileInfo \ Translation". In dit geval, wat teruggezonden een pointer naar een structuur die informatie over het type bestand en de inhoud, het paar dubbele woorden die kunnen worden gecombineerd tot een enkele streng 64-bit versie voor strikt numerieke vergelijkingen vertegenwoordigen ('s bevat installatie), evenals de module attributen definiëren binnen Delphi. Het zou een eenvoudige taak om de fabrikant TVersionInfo breiden om deze informatie te extraheren en bloot door middel van eenvoudige Booleaanse eigenschappen en, in Delphi 5, Int64 soorten onroerend goed voor de strikte versienummers zijn.



Dit vermogen om toegang tot complexe data structuren te kapselen via een handige interface is een van de schoonheden van objectoriëntatie, en een waarop we zullen altijd terugkomen. De klasse gedefinieerd heeft reeds het buildnummer als afzonderlijke eigenschap, weer uit het laatste element van FileVersion aan de gebruikers van de klasse met de juiste gegevens op een geschikte wijze. Bijvoorbeeld, zou dit een juist gebruik van het dialoogvenster voor een toepassing zijn, waarin niet alleen de naam en de gegevens van de auteur toepassing, maar ook de programma-versie en build-nummer voor gemakkelijke verwijzing.



Om ons onderzoek naar het proces van generatie voltooien zeer leuk zou zijn als, na het met succes afgerond, kon je het buildnummer (en eventueel de release nummer) in de versie-informatie voor alle te leveren prestaties te verhogen. Delphi lijkt de versie-informatie in het bestand op te slaan .DOF bij het project; Dit is in het INI-bestand formaat en bevat de meeste van de in het project opgenomen informatie | dialoogvenster Opties. Echter, het maken van wijzigingen in de programmering van dit bestand (er zijn vermeldingen in het [Versie-info] voor zaken als MajorVer, output, enzovoort) niet echt eventuele wijzigingen in de gecompileerde applicatie te betrekken. Dit komt omdat Delphi genereert het gecompileerde bronbestand (Project.RES) van deze informatie alleen als het interactief is veranderd binnen Delphi zelf. Ik .RES gecompileerd bronbestand is gewoon gekoppeld aan de toepassing tijdens het compileren, zodat wijzigingen in het bestand .DOF maken en dan opnieuw compileren van de aanvraag niet aan de resource file veroorzaken worden geregenereerd en wordt gebruikt om een ​​date. Het is een goed idee dan de versienummers en afgifte van elk Delphi project in de hand werken eind van elke generatie van succes.



In het volgende artikel zullen we beginnen met de klassen die we nodig hebben om een ​​applicatie echt te maken object-oriented, kapselen business objects en toegang tot de database in een zeer productieve manier te ontwerpen. Dit zal een grote odyssee dat bijna alle aspecten van applicatie-ontwikkeling omvat voor Windows zijn.



Next in series



Verlaat een commentaren