Legge versjonsinformasjon til applications

Denne artikkelen vil jeg undersøke de midler som programversjon kan gjøres tilgjengelig i et program, skrive en klasse som kan bli innlemmet i en ny development.Adding Version Information Å ApplicationsLast artikkelen jeg diskutert konseptet med en build, og hvorfor en standard prosess for å produsere et konsistent sett av leveransene var en god thing.Since de tidligste dataprogrammer ble utplassert, utviklerne ønsket å ha noen måte å identifisere hvilken versjon en kunde kjørte; tross alt, det er åpenbart verdt å vite om en bug de rapporterer allerede har blitt fikset. Ganske raskt (og selvsagt) et numerisk system utviklet seg, er det bare økes versjonsnummeret hver gang en utgivelse ble gjort. Som frekvensen av utgivelser økt, utviklerne ønsket å ha noen måte å skille en stor ny utgivelse sammenlignet med en midlertidig én: begrepet større og mindre versjoner av et program ble innført - går fra v1.12 til V2.0 formidlet mye mer (selv å legge brukere) enn å gå fra V12 til V13. For mange år dur og moll versjonen var tilstrekkelig og vanlig, men som programmer ble større og komplekse krever hyppigere bug-fikser en tertiær nummer ble stiftet på til slutten av den versjonen for å indikere en "release". Alle utgivelser med de samme store og små versjonsnumre bør ha en identisk funksjon liste, men bør inkludere kumulative feilrettinger og andre forbedringer uten å legge til nye funksjoner som sådan. Latterly, har det blitt en god vane å legge build-nummeret til utgivelsen som resulterer i et komplett versjonsnummer med fire komponenter, X.Y.Z.B, der X representerer den store versjonen, Y den mindre versjonen, Z utgivelsen nummeret og B build-nummeret. Merk at selv om den mindreårige og slipp versjoner kan resettes til null (med større og mindre utgivelser), er build-nummeret aldri tilbakestille og derfor alltid øker med hver ny utgivelse (selv om det ikke nødvendigvis er strengt inkrementell, det er meget mulig å ha intern bygger i et selskap som ikke er gitt ut til kunder). Oppføring 1 oppsummerer når hver versjonsnummer komponent bør økes.
ComponentDescribesWhen å øke
XMajorAfter vesentlige endringer er gjort i søknaden
YMinorAfter nye funksjoner har blitt lagt til applikasjonen

ZReleaseEvery tiden en mindre utgivelsen er gjort tilgjengelig med feilrettinger
BBuildEvery gang byggeprosessen er fullført Anmeldelser Oppføring 1 - Komponenter av versjonsnummer XYZBAlthough markedsføring avdelinger kapret begrepet versjonsnumre for sin egen slutter når det ble innsett at et stort antall mennesker ville investere i oppgraderinger når hovedversjonsnummeret endres eller feide konkurrentene, det er fortsatt veldig nyttig å ha noen form for formell versjonsnummer i programmene dine - det er mye enklere å bekrefte at klienten kjører Build 134 eller senere, snarere enn "SuperApp 97 SR-2a Patch 13 (Y2K)". Dette ble spesielt viktig med bruk av delte DLL biblioteker i Windows som kan erstattes av en nyinstallert søknad. Selv om ikke veldig flink til å bruke ordningen nummereringen konsekvent, nesten alle Microsoft-programfiler (EXE og DLL-er) inneholder nå noen form for en 4-sifret versjonsnummeret innebygd i dem. Faktisk, Windows 2000 gjør utstrakt bruk av denne informasjonen i et forsøk på å hindre at viktige systemfiler blir overskrevet av tidligere, eller noen ganger senere versjoner. Installeringsprosedyrer også gjøre bruk av denne informasjonen ved å advare når en fil vil overskrive et lignende navn, men senere versjon av seg selv. Embedded Version Information
Hvis du høyreklikker på en EXE eller DLL-filen i Utforsker på hurtigmenyen som vises har en oppføring i bunnen heter "Egenskaper". Hvis du velger dette viser noen detaljer om filen. Hvis tilgjengelig, den andre kategorien (kalt Version) viser informasjon innebygd i filen om versjonsnummer, produktnavn, opphavsrett og så videre. Alle filer som kan ha en ressurs segment kan ha denne informasjonen integrert i det, og dette inkluderer programmer kompilert med Delphi. Microsoft har publisert informasjon og format som skal gis i ressursen delen for informasjon som skal vises. I Delphi 2, den eneste måten som dette kunne oppnås var ved å opprette en ressurs fil med akkurat de rette strengene i den, kompilere den separat med ressursen kompilatoren og deretter koble den inn i applikasjonen (dette utgjør en del av de viktigste byggeprosessen ). Selv om det ikke vanskelig, disse trinnene kreves en grad av teknisk kunnskap og ferdigheter slik at noen programutviklere gidder å gjøre det. Innenfor det ethos for å gjøre Windows utvikling mer produktiv, Delphi 3 innført en spesiell dialog hvor denne informasjonen kan være lett vedlegges søknaden. Figur 1 viser denne dialogen, tilgjengelig fra Delphi Prosjekt-menyen, bør alternativer item.By tikker av i boksen øverst på fanen for å vise at versjonsnummer informasjon være med det er mulig å legge til detaljer om ikke bare versjonsnummer, men også flagg om build er ment for offentlig utgivelse, og i bunnen er det mulig å legge til detaljer til en hel liste med forhåndsdefinerte kategorier, for eksempel en beskrivelse av filen og opphavsrett. Delphi endrer automatisk FileVersion kategori som modul versjon tall informasjonen ovenfor er oppdatert. Når denne dialogen er bekreftet, konstruerer Delphi nødvendig ressursfilen (som også inneholder slike detaljer som programikonet) i en gjennomsiktig skritt, som vil bli automatisk koblet inn i den endelige kjørbar. Hvis du gjør dette på selv de enkleste prosjektet vil du se at du nå kan høyreklikke på den kjørbare og få versjonsinformasjon, akkurat som alle veloppdragne Windows-programmer. Hva Version er jeg?
Nå som vi vet hvordan de skal plassere versjonsinformasjon i programmet, ville det være nyttig å faktisk få tilgang til informasjonen. Tross alt, til hvis du prøver å etablere over telefonen hvilken versjon en bruker kjører det ville være mye lettere å beskrive hvordan du viser dialogboksen Om snarere enn å finne programmet kjørbar i Utforsker, høyreklikke, velge Egenskaper og velge versjon tab.As versjonsinformasjonen bare er lagret som strenger i et bestemt format i ressurs-delen av programmet, vil det være mulig å bruke standard Win32 ressurs filkommandoer å trekke ut relevant informasjon, å dekode de strukturer. Det er imidlertid noen spesifikke Win32 API-kommandoer tilgjengelige som gjør nettopp dette i en mye mer praktisk form. Dette er GetFileVersionInfoSize (som returnerer informasjon om plassen som kreves for å lagre versjonsinformasjonen), GetFileVersionInfo (som trekker detaljene inn i en pre-levert buffer i riktig størrelse), og VerQueryValue (som trekker ut en navngitt stykke versjonsinformasjon fra buffer , for eksempel "LegalCopyright"). Som i vanlig når vi samhandler med Win32 API, må disse kommandoene kalles i riktig rekkefølge, bevare visse interne verdier returnert fra tidligere kommandoer gjennom Var parameters.It er en veldig god idé å kapsle noen form for interaksjon med Windows API med en mer brukervennlig og Delphi-grensesnitt. Typiske Delphi programmerere ikke ønsker å forholde seg til tildeling av minneblokker og Win32-spesifikke typer som DWORD og UINT, og det bør heller ikke de. Langt bedre å designe en fin klasse som, i de beste tradisjonene av OO, skjuler rå tilgang til versjon og presenterer en langt mer anvendelig grensesnitt. Dette har den ekstra fordelen at dersom lagring av denne versjonen informasjonen stadig endres, samme klasse kan kapsle systemavhengig samtidig opprettholde den samme offentlige interface.There er et par ting du bør vurdere når du utformer denne klassen. For det første bør det være i stand til å brukes med en hvilken som helst applikasjon fil, med den fra hvilken den utfører. Dernest bør det gi enkel tilgang til standard og mest brukte versjonen informasjons nøkler (FileVersion, Product etc.). Til slutt, som det er mulig for brukeren å tilveiebringe ytterligere tilpasset versjon nøkler og verdier i deres struktur, må klassen eksponere disse på en naturlig måte. Oppføring 2 viser felles grensesnitt for denne class.TVersionInfo = classprivate funksjon GetVersionInfo (Indeks: Integer): String; offentlig konstruktør Opprette (ThisSourceFile: String); destructor Destroy; styre; //Vilkårlig nøkkelinformasjon eiendom Key [KeyName: String]: String lese Getkey; //Standard nøkkelinformasjon eiendom Ola Normann: String index 0 lese GetVersionInfo skrive SetVersionInfo; Eiendommen FileDescription: String index en lese GetVersionInfo; Eiendommen FileVersion: String index to lese GetVersionInfo; Eiendommen Internt navn: String index tre lese GetVersionInfo; Eiendommen Copyright: String index 4 lese GetVersionInfo; eiendoms varemerker: String index 5 lese GetVersionInfo; Eiendommen OriginalFileName: String index seks lese GetVersionInfo; Eiendommen Product: String index 7 lese GetVersionInfo skrive SetVersionInfo; Eiendommen Product: String index åtte lese GetVersionInfo skrive SetVersionInfo; eiendoms Kommentarer: String index ni lese GetVersionInfo; Eiendommen BuildNumber: String lese GetBuildNumber; ende; Oppføring 2 - Offentlig grensesnittet til TVersionInfo Som man kan se fra klassen, alle de vanlige nøkkelnavn er avslørt som navngitte egenskaper, mens Key eiendommen gir tilgang til tilpasset tilleggsinformasjon ved navn. Klassen er konstruert ved å sende inn en fullt kvalifisert bane og filnavn fra hvilken versjon informasjon bør trekkes ut. Det er en veldig interessant aspekt om denne klassen som demonstrerer et lite benyttet aspekt av Delphi førsteklasses design: ved hjelp av indeksen identifikator for å kartlegge en rekke ulike egenskaper på samme tilgangsfunksjonen. Som det kan ses fra det private gjennomføring av GetVersionInfo som brukes til å lese egenskaper, er dette indeksverdi føres inn avhengig av egenskapen åpnes, slik at funksjonen for å bestemme hvilken verdi til å gå tilbake. Som vi skal se i gjennomføringen, letter dette ofte svært konsise coding.As tidligere nevnt, trekker GetFileVersionInfo kommandoen detaljer fra ressurs-delen og lagrer dem i buffer sendes som en parameter til API-kall. Det gjør derfor fornuftig å utføre dette som en engangsoperasjon i konstruktøren. Når denne informasjonen har blitt pakket ut, kan vi avhøre det for kjente nøkkelnavn. For praktisk koding og en økning i ytelse, vil vi trekke ut viktige verdier for alle de vanlige nøkkelnavn og lagre disse verdiene i en matrise med samme ordens verdi som hver eiendom indeksen. Dette betyr at gjennomføringen av GetVersionInfo eiendommen accessor funksjonen kan være transparent enkel og slett returnerer matrisen verdi på den medfølgende indeksen. For de tilpassede nøkler som kan i tillegg bli gitt vil vi bare ringe API-kommandoen for å pakke ut detaljer fra versjonsinformasjonen buffer. Selv om dette vil være litt tregere enn tilgang til detaljene direkte fra en pre-beregnet array, er det ikke forventet at disse egenskapene blir ofte tilgang, og dette er derfor en akseptabel utforming avgjørelse. Oppføring 3 viser gjennomføringen av class.constructor TVersionInfo.Create (ThisSourceFile: String); const VersionKeyNames: array [0..MaxVersionKeys] av String = ('Ola Normann', 'FileDescription', 'FileVersion', 'Internt navn', ' LegalCopyright ',' LegalTrademarks ',' OriginalFilename ',' Product ',' Product ',' Kommentarer '); Var ThisInfo: integer; InfoLength: UINT; Len: DWORD; Håndtak: DWORD; PCharset: PLongInt; begynne arvet Opprett; //Få størrelsen versjon info Len: = GetFileVersionInfoSize (PChar (ThisSourceFile), Håndtak); //Tildele VersionInfo bufferstørrelse SetLength (VersionInfo, Len + 1); //Få versjon info om GetFileVersionInfo (PChar (ThisSourceFile), Håndtak, Len, Pointer (VersionInfo)) begynner deretter //Få oversettelse info for Language /charset IDer hvis VerQueryValue (PointerVersionInfo), '\\ VarFileInfo \\ Oversettelse', Pointer (PCharset ), InfoLength) da begynne LangCharset: = Format ('% .4x% .4x', [LoWord (PCharset ^), HIWORD (PCharset ^)]); InfoAvailable: = true; //Få standardversjonen informasjon for ThisInfo: = 0 til MaxVersionKeys gjøre StandardKeys [ThisInfo]: = Getkey (VersionKeyNames [ThisInfo]); slutt; end, end, funksjon TVersionInfo.GetKey (ThisKeyName: string): string; Var InfoLength: UINT; begynne hvis InfoAvailable deretter begynne SetLength (Resultat, 255); hvis VerQueryValue (Pointer (VersionInfo), PChar (Format ('\\ StringFileInfo \\% s \\% s', [LangCharset, ThisKeyName])), Pointer (resultater), InfoLength) da begynne SetString (Resultat, PChar (resultater), InfoLength - 1); ende annet begynne Resultat: = ''; slutt; ende annet begynne Resultat: = 'N /A'; end, end, funksjon TVersionInfo.GetVersionInfo (Indeks: Integer): string; begynne Resultat: = StandardKeys [Indeks]; end; prosedyre TVersionInfo.SetVersionInfo (Indeks: Integer; Verdi: string); begynne StandardKeys [Indeks]: = verdi; enden, funksjon TVersionInfo.GetBuildNumber: string; begynne //Strip det siste elementet fra filen versjon Resultat: = FileVersion; mens Pos (, Result '.') > 0 do begynne Resultat: = Kopier ('.' Resultat, Pos (, resultater) + 1, Lengde (resultater)); end, end, en av nyansene i måten versjonen informasjonen er lagret i applikasjonen ressursen delen er at det er mulig å definere hvilket språk tegnsett har blitt brukt til å lage versjonsinformasjonen (og programmet eller DLL seg selv). Dette er definert innenfor versjonsinformasjonen som en dobbel ord, eller 32-bit usignert heltall, og må være tilstede som en del av versjonsinformasjonen streng (i heksadesimalt format) for hver tast som er trukket ut. En av jobbene til konstruktøren, samt trekke ut versjonsinformasjonen til en streng buffer (en praktisk måte å lagre statiske data returnert fra API-kall) er å trekke språk og tegnsett informasjon og for å bygge opp en riktig heksadesimal streng som vil bli brukt i fremtidige samtaler til VerQueryValue. Når dette er gjort konstruktøren deretter gjør et kall til rutine som faktisk returnerer en versjon informasjonsverdi for en medfølgende nøkkel. Denne rutinen lever et dobbeltliv, i tillegg maskert som tilgangsfunksjonen for Key eiendommen. Igjen, et interessant aspekt ved denne prosessen er at konstruktøren får en liste over de vanlige nøkkelnavn fra en privat konstant fast string array som er vedtatt og som er definert i en enkelt setning. Også dette er en lite brukt, men veldig nyttig, teknikk som også er tillatt for globale variabler samt constants.If du henviser tilbake til figur 1 kan du se noen ekstra versjonsinformasjonen i gruppe kalt "Module attributter", i hovedsak en sett med flagg som beskriver status for søknaden, enten det er en debug eller private bygg og så videre. Denne informasjonen er også tilgjengelig i ressursfilen, og kan nås ved hjelp av VerQueryValue API kommando, men med en andre parameter for bare "\\", snarere enn "\\ VarFileInfo \\ Translation". I dette tilfellet hva som returneres er en peker til en struktur som inneholder detaljer om filtype og innhold, doble ordpar som kan kombineres for å representere en streng 64-bit-versjonen som er brukt for strenge numeriske sammenligninger (av installasjonsprogrammer) samt Modul attributter definer innen Delphi. Det ville være en enkel oppgave å forlenge TVersionInfo konstruktøren å trekke ut denne informasjonen og utsetter det via enkle boolske egenskaper, og i Delphi 5, Int64 typer eiendom for den strenge versjonen numbers.This evne til å kapsle tilgang til komplekse datastrukturer via et praktisk grensesnitt er en av de skjønnobjektorientering, og en som vi vil være kontinuerlig tilbake. Klassen definert her har allerede utsatt build-nummeret som en egen eiendom, selv avledet fra det siste elementet av FileVersion å gi brukerne av klassen med passende data på en praktisk måte. For eksempel vil en hensiktsmessig bruk av dette være på Om boksen for et program, viser ikke bare programnavnet og opphavsrett detaljer, men også programversjon og bygge nummer for enkel reference.To fullføre vår undersøkelse av et byggeprosessen det ville være svært fint om, å ha fullført, kan det øke build-nummeret (og muligens slipper nummer) innenfor den informasjonen versjon for alle leveranser. Delphi ser ut til å lagre denne versjonen informasjon i .DOF filen som følger prosjektet; dette er i INI-format og inneholder det meste av detaljer avslørt av prosjektet | Dialogboksen Alternativer. Men programma å gjøre endringer i denne filen (det finnes oppføringer i [Versjonsinfo] seksjon for ting som MajorVer, Slipp og så videre) faktisk ikke medføre noen endringer i samlet søknad. Dette er fordi Delphi genererer samlet ressursfilen (Project.RES) fra denne informasjonen når den blir endret interaktivt innenfra Delphi seg selv. De res samlet ressursfilen er bare knyttet til søknaden ved kompilering, så gjør endringer i .DOF fil og deretter rekompileres søknaden ikke medfører ressursfilen som skal regenereres og utdatert en brukes. Det er god praksis derfor å oppdatere bygge og slipp tallene for hver Delphi prosjekt for hånd på slutten av hver vellykket build.In neste artikkel vil vi begynne å designe de klassene som vi trenger for å produsere en virkelig objekt-orientert program, innkapsle forretningsobjekter og databasetilgang i en svært produktiv måte. Dette vil være en stor odyssey som dekker nesten alle aspekter av Windows-program development.Next i serie