Versions-Informationen
Sehen wir uns nun die letzte Ressource (in diesem Kapitel) an, die Versions-Information.
Auch diese Ressource hat der Anwendungs-Assistent bereits zu Ihrer Anwendung hinzugefügt.
Die in dieser Ressource abgelegten Informationen sind hauptsächlich dazu gedacht,
Installationsprogrammen Informationen über die aktuelle Version des Programms zu
liefern. Sie können jedoch die in der Ressource enthaltenen Informationen auch in
Ihren eigenen Programmen verwenden um z.B. im Info-Dialog die Version-Nummer, das
Copyright usw. auszugeben. Wie Sie an die Informationen kommen, das erfahren Sie
gleich noch. Sehen wir uns zunächst aber einmal eine typische Versions-Information
an.
 |
Erstellen Sie wiederum ein SDI-Projekt und geben Sie diesem
Projekt den Namen VersInfo. Gehen dann wieder in die Ressourcen-Ansicht
und öffnen Sie den Ressource-Typ Version. Dieser Ressource-Typ sollte
laut WINDOWS Programmier-Richtlinien nur einen Eintrag mit der ID VS_VERSION_INFO
enthalten. Führen Sie einen Doppelklick auf die ID aus um die Versions-Information
letztendlich zu öffnen.

|
Der erste, obere Teil der Versions-Information ist allgemein gültig und sprachunabhängig.
In diesem Teil steht u.a. die Dateiversion oder aber auch für welches Betriebssystem
die Datei gedacht ist. Nach dem sprachunabhängigen Teil können ein oder mehrere
sprachabhängige Teile folgen. Die Bedeutung der Einträge sowie deren zulässige Werte
soll hier nicht aufgezählt werden da dies sehr umfangreich ist. Wenn Sie wollen,
können Sie in der Online-Hilfe unter dem Stichwort VERSIONINFO Resource
genaueres erfahren. Wir werden uns jetzt ansehen, wie Sie die vorgegebene Version-Information
abändern können.
 |
Falls noch nicht geschehen, öffnen Sie die Versions-Information
im Editor. Um einen der Einträge zu ändern, führen Sie einfach einen Doppelklick
auf den entsprechenden Eintrag aus. Bei den Einträgen FILEOS, FILETYPE
und FILESUBTYPE wird daraufhin eine Auswahlliste geöffnet, zu erkennen
am Pfeil rechts. Wenn Sie auf diesen Pfeil klicken werden Ihnen alle zur Zeit
möglichen Werte aufgelistet. Durch Anklicken eines Wertes wird dieser dann übernommen.
Bei allen anderen Einträge können Sie direkt den gewünschten Werte eingeben.
Ändern Sie nun nach belieben die Einträge PRODUCTVERSION, LegalCopyright,
CompanyName und SpecialBuild. Diese Einträge werden wir nachher
im Beispiel wieder auslesen |
Die gesamte Versions-Information können Sie im Prinzip als eine Art Verzeichnisstruktur
betrachten, wobei der erste, sprachunabhängige Teil das Root-Verzeichnis darstellt.
Nach diesem 'Root-Verzeichnis' können ein oder mehrere 'Unterverzeichnisse' folgen,
die die sprachabhängigen Informationen enthalten. Im obigen Beispiel ist nur ein
solches 'Unterverzeichnis' enthalten, das der Sprache Deutsch zugeordnet ist. Auf
unterster Ebene folgen dann die eigentlichen Informationen wie z.B. Comments.
Leider bietet die MFC keinerlei Unterstützung zum Auslesen der Versions-Informationen,
so dass wir hier auf das WINDOWS API zugreifen müssen. Um den Root-Eintrag auszulesen,
müssen Sie zuerst den vollständigen Pfad und den Namen der Anwendung ermitteln,
für die die Informationen auslesen werden sollen. Um den Pfad der aktuellen Anwendung
zu ermitteln wird die API-Funktion GetModuleFileName(...) aufgerufen. Setzen
Sie den ersten Parameter der Funktion hModule auf NULL um für das aktuelle
Programm den vollständigen Namen zu ermitteln.
Da für die nachher auszulesende Versions-Information von der Anwendung ein Puffer
bereitgestellt werden muss, gilt es in einem zweiten Schritt zunächst die Größe
der Information festzustellen. Hierfür wird die API-Funktion GetFileVersionInfoSize(...)
aufgerufen, die als Parameter u.a. den vorher ermittelten vollständigen Dateinamen
der Anwendung erhält. Und im letzten Schritt kann dann endlich mittels der API-Funktion
GetFileVersionInfo(...) die Versions-Information ausgelesen werden.
Bauen wir diese Schritte nun in unser Beispiel ein:
 |
Zuerst fügen Sie dem Beispiel eine neue Schnellzugriffstaste
zur späteren Anzeige der Versions-Information hinzu. Öffnen Sie die Ressource
Accelerator. Fügen Sie dann die Zugriffstaste <ALT>-<H> wie
in der letzten Lektion besprochen hinzu und geben Sie der Taste die ID ID_VERSINF.
Anschließend definieren Sie über den Klassen-Assistenten für die neue ID noch
die Methode OnVersinf(...) wie folgt. Beachten Sie dabei bitte,
dass als Klassenname CVersInfoView eingestellt ist!
void CVersInfoView::OnVersinf()
{
// TODO: Code für Befehlsbehandlungsroutine hier einfügen
Invalidate();
} |
Anschließend kann die Versions-Information zunächst in der OnDraw(...)
Methode ausgelesen werden.
void CVersInfoView::OnDraw(CDC*
pDC)
{
CVersInfoDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// ZU ERLEDIGEN: Hier Code zum Zeichnen der ursprünglichen Daten
hinzufügen
// Variablen fuer Vers-Info
definieren
char acModName[MAX_PATH];
char *pcInfoBuffer;
char acFormat[80];
DWORD dwInfoSize;
DWORD dwDummy;
WORD wCodePage;
WORD wLangID;
LPVOID pvInfo;
UINT wInfoLen;
VS_FIXEDFILEINFO *pFixedFile;
CString CValue;
LPCTSTR pcData;
// Modulname holen
::GetModuleFileName(NULL,acModName,sizeof(acModName));
// Groesse der Vers-Info
Blockes holen und Speicher allokieren
dwInfoSize = ::GetFileVersionInfoSize(acModName,&dwDummy);
pcInfoBuffer = new char[dwInfoSize];
// Vers-Info auslesen
::GetFileVersionInfo(acModName,0UL,dwInfoSize,pcInfoBuffer);
} |
|
Damit liegt die Versions-Information jetzt im Puffer. Jetzt gilt es 'nur' noch,
diese Information aus dem Puffer auszulesen. Um die im Puffer abgelegten Informationen
abzufragen dient die API-Funktion VerQueryValue(...). Diese Funktion erhält
u.a. im zweiten Parameter einen String-Zeiger der angibt, welche Information ausgelesen
werden soll, sowie im dritten Parameter einen Zeiger auf einen Pufferzeiger für
die Ablage der ausgelesenen Information. Folgende Strings sind sind für die Angabe
der auszulesenden Information erlaubt:
|
String
|
Bedeutung
|
| "\\" |
Liest den sprachunabhängigen Teil der Versions-Information
aus. Der Zeiger auf den Pufferzeiger muss vom Typ VS_FIXEDFILEINFO sein. Der
Zeiger enthält nachher die Adresse der Struktur mit den sprachunabhängigen Daten. |
| "\\VarFileInfo\\Translation" |
Liest die Sprachen und die Code-Pages aus. Der Zeiger auf den
Pufferzeiger zeigt nach dem Aufruf der Funktion auf ein DWORD-Array, in dem
alle Sprachen und Code-Pages in kodierter Form enthalten sind, für die eine
Versions-Information zur Verfügung steht. |
| "\StringFileInfo\lang-codepage\string-name" |
Liest den sprachabhängigen Teil der Versions-Information aus.
lang-codepage enthält die Sprache und Code-Page, für die die Information
ausgelesen werden soll und string-name den Namen des entsprechenden Eintrags.
Der Zeiger auf den Pufferzeiger zeigt nach dem Aufruf der Funktion aus die ausgelesene
Information. |
 |
Lesen wir im Beispiel nun den sprachunabhängigen Teil der Version-Information
aus sowie die sprachabhängigen Teile LegalCopyRight, CompanyName und
SpecialBuild. Erweitern Sie dazu die Methode OnDraw(...) wie
folgt:
void CVersInfoView::OnDraw(CDC*
pDC)
{
....
// Vers-Info auslesen
::GetFileVersionInfo(acModName,0UL,dwInfoSize,pcInfoBuffer);
// Nun Zeichensatz
fuer Ausgabe setzen
pDC->SelectStockObject(SYSTEM_FONT);
pDC->SetTextColor(RGB(255,0,0));
// Nach festen Infos suchen
::VerQueryValue(pcInfoBuffer,"\\",(void**)&pFixedFile,&wInfoLen);
wsprintf(acFormat,"Version: %d.%d.%d.%d",
HIWORD(pFixedFile->dwProductVersionMS),
LOWORD(pFixedFile->dwProductVersionMS),
HIWORD(pFixedFile->dwProductVersionLS),
LOWORD(pFixedFile->dwProductVersionLS));
pDC->TextOut(10,10,acFormat,strlen(acFormat));
// CodePage und LanguageID
auslesen
::VerQueryValue(pcInfoBuffer,"\\VarFileInfo\\Translation",
&pvInfo,&wInfoLen);
wCodePage = LOWORD(*(DWORD*)pvInfo);
wLangID = HIWORD(*(DWORD*)pvInfo);
// Copyright Notiz auslesen
wsprintf(acFormat,"StringFileInfo\\%04X%04X\\LegalCopyright",
wCodePage,wLangID);
::VerQueryValue(pcInfoBuffer,acFormat,(void**)&pcData,&wInfoLen);
pDC->TextOut(10,30,pcData,strlen(pcData));
// Firmenname auslesen
wsprintf(acFormat,"StringFileInfo\\%04X%04X\\CompanyName",
wCodePage,wLangID);
::VerQueryValue(pcInfoBuffer,acFormat,(void**)&pcData,&wInfoLen);
pDC->TextOut(150,30,pcData,strlen(pcData));
// Spezialversion auslesen
wsprintf(acFormat,"StringFileInfo\\%04X%04X\\SpecialBuild",
wCodePage,wLangID);
::VerQueryValue(pcInfoBuffer,acFormat,(void**)&pcData,&wInfoLen);
pDC->TextOut(10,50,"Gebaut für:");
pDC->TextOut(150,50,pcData,strlen(pcData));
delete [] pcInfoBuffer;
} |
Übersetzen Sie das Beispiel nun.
|
Vermutlich werden Sie beim Linken einige Fehlermeldungen erhalten. Die Versions-Informations-Funktionen
werden standardmäßig nicht zur Anwendung dazugebunden. Wenn Sie in der Online-Hilfe
zu diesen Funktionen nachsehen werden dort ganz am unteren Ende folgende Informationen
finden:
QuickInfo
Windows NT: Requires version 3.1 or later.
Windows 95/98: Requires Windows 95 or later.
Windows CE: Unsupported.
Header: Declared in winver.h.
Import Library: Use version.lib.
Unicode: Implemented as Unicode and ANSI versions on Windows NT.
|
Unter dem Eintrag Import Library finden Sie die Bibliothek, die Sie
zur Anwendung dazubinden müssen wenn Sie die Funktion verwenden wollen.
 |
Um die Bibliothek version.lib zum Beispiel dazu zu
binden, gehen Sie zunächst ins Menü Projekt-Einstellungen. Wählen Sie
dann im eingeblendeten Dialog unter Einstellungen für den Eintrag
Alle Konfigurationen aus. Damit haben Sie festgelegt, dass alle nachfolgenden
Einstellungen sowohl für die Debug- wie auch für die Release-Version Ihrer Anwendung
gelten sollten. Als nächstes fügen Sie unter Objekt-/Bibliothek-Module
das aus der Online-Hilfe entnommene Modul version.lib hinzu.

Übersetzen und starten Sie nun das Programm. Sie sollten als Ausgabe dann
die Produktion-Version, den Copyright-Vermerk, den Firmennamen sowie die Sonderversion
erhalten.
|
Das fertige Beispiel finden Sie auch unter 07Ressourcen\VersInfo.
Damit ist dieses Kapitel im Prinzip beendet. Zum Schluss können Sie sich nun
noch einige Tipps&Tricks zum Thema Ressourcen ansehen.
|