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.

Die Versionsinformation

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.

Linker-Einstellung für das Projekt

Ü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.



Copyright © 2004

Senden Sie Emails mit Fragen oder Kommentaren zu dieser Website an: mailto:info@cpp-tutor.de
 Wolfgang Schröder, Lerchenweg 23, D-72805 Lichtenstein. Tel: +49 7129 6470