2008-11-25 7 views
30

Ich habe eine Versionsressource in meinen Ressourcen in einem C++ - Projekt, das Versionsnummer, Copyright und Build-Details enthält. Gibt es eine einfache Möglichkeit, um diese zur Laufzeit zu erreichen, um meine Hilfe/über Dialog zu füllen, wie ich derzeit separate const Werte dieser Informationen pflege. Im Idealfall sollte die Lösung für Windows Mobile Mobile und frühere Versionen von Visual C++ (6.0 aufwärts) funktionieren.Wie lese ich aus einer Versionsressource in Visual C++

+0

Sie sollten beachten, dass '_get_pgmptr()' oder '_get_wpgmptr()' ist besser als 'GetModuleFileName (NULL, szFilename, MAX_PATH)'; erspart Ihnen unnötige Zuweisung und klärt Ihre Absicht. – q12

Antwort

30

Dies ist eine bearbeitete Version meiner ursprünglichen Antwort.

bool GetProductAndVersion(CStringA & strProductName, CStringA & strProductVersion) 
{ 
    // get the filename of the executable containing the version resource 
    TCHAR szFilename[MAX_PATH + 1] = {0}; 
    if (GetModuleFileName(NULL, szFilename, MAX_PATH) == 0) 
    { 
     TRACE("GetModuleFileName failed with error %d\n", GetLastError()); 
     return false; 
    } 

    // allocate a block of memory for the version info 
    DWORD dummy; 
    DWORD dwSize = GetFileVersionInfoSize(szFilename, &dummy); 
    if (dwSize == 0) 
    { 
     TRACE("GetFileVersionInfoSize failed with error %d\n", GetLastError()); 
     return false; 
    } 
    std::vector<BYTE> data(dwSize); 

    // load the version info 
    if (!GetFileVersionInfo(szFilename, NULL, dwSize, &data[0])) 
    { 
     TRACE("GetFileVersionInfo failed with error %d\n", GetLastError()); 
     return false; 
    } 

    // get the name and version strings 
    LPVOID pvProductName = NULL; 
    unsigned int iProductNameLen = 0; 
    LPVOID pvProductVersion = NULL; 
    unsigned int iProductVersionLen = 0; 

    // replace "040904e4" with the language ID of your resources 
    if (!VerQueryValue(&data[0], _T("\\StringFileInfo\\040904e4\\ProductName"), &pvProductName, &iProductNameLen) || 
     !VerQueryValue(&data[0], _T("\\StringFileInfo\\040904e4\\ProductVersion"), &pvProductVersion, &iProductVersionLen)) 
    { 
     TRACE("Can't obtain ProductName and ProductVersion from resources\n"); 
     return false; 
    } 

    strProductName.SetString((LPCSTR)pvProductName, iProductNameLen); 
    strProductVersion.SetString((LPCSTR)pvProductVersion, iProductVersionLen); 

    return true; 
} 
+0

Wo finden Sie die Sprach-ID? –

+0

@ JeffB Ich würde auf der MSDN-Seite [Language Identifier Constants und Strings] (https://msdn.microsoft.com/en-us/library/windows/desktop/dd318693 (v = vs.85) .aspx) starten . –

+0

Beide Ihre letzten zwei Zeilen gibt mir eine '' void ATL :: CSimpleStringT :: SetString (const char *, int) ': kann nicht konvertieren Argument 1 von' LPCTSTR 'zu' const char * '. '. Ich habe '#include ' –

5

So etwas werden Sie rohen Zugriff auf die Ressourcen-Daten geben und Ihnen den Einstieg:

HRSRC res = ::FindResource(NULL, MAKEINTRESOURCE(MY_VERSION_ID), RT_VERSION); 
DWORD size = ::SizeofResource(NULL, res); 
HGLOBAL mem = ::LoadResource(NULL, res); 
LPVOID raw_data = ::LockResource(mem); 
... 
::FreeResource(mem); 
0

Ok, fand ein bisschen mehr googleing die following auf MS-Office. Im Grunde verwendet dieser Ansatz das CFileVersionInfo Objekt, um eine beliebige Datei zu erhalten. Es sollte interessant sein zu sehen, ob es auf der aktuell laufenden .EXE-Datei und auf Windows CE funktioniert.

7

So etwas könnte man beginnen, vielleicht:

TCHAR moduleName[MAX_PATH+1]; 
(void)GetModuleFileName(AfxGetInstanceHandle(), moduleName, MAX_PATH); 
DWORD dummyZero; 
DWORD versionSize = GetFileVersionInfoSize(moduleName, &dummyZero); 
if(versionSize == 0) 
{ 
    return NULL; 
} 
void* pVersion = malloc(versionSize); 
if(pVersion == NULL) 
{ 
    return NULL; 
} 
if(!GetFileVersionInfo(moduleName, NULL, versionSize, pVersion)) 
{ 
    free(pVersion); 
    return NULL; 
} 

UINT length; 
VS_FIXEDFILEINFO* pFixInfo; 
VERIFY(VerQueryValue(pVersionInfo, const_cast<LPTSTR>("\\"), (LPVOID*)&pFixInfo, &length)); 
4

Vorsicht! Verwenden von FindResource..LockResource ist nicht korrekt. Es funktioniert manchmal (wie in meinem kleinen Demo-Programm) und verursacht manchmal Zugriffsverletzungen (Beispiel: der Produktionscode, für den ich die Demo gemacht habe).

Die VerQueryValue() - Dokumentation besagt, dass Sie stattdessen GetFileVersionInfoSize und GetFileVersionInfo aufrufen sollten. Raymond Chen erklärt, siehe http://blogs.msdn.com/oldnewthing/archive/2006/12/26/1365215.aspx

13

Um eine Sprache unabhängiges Ergebnis zu Marks Antwort Änderung zu erhalten:

// replace "040904e4" with the language ID of your resources 
    !VerQueryValue(&data[0], _T("\\StringFileInfo\\040904e4\\ProductVersion"), &pvProductVersion, &iProductVersionLen)) 
{ 
    TRACE("Can't obtain ProductName and ProductVersion from resources\n"); 
    return false; 
} 

Um

UINT    uiVerLen = 0; 
VS_FIXEDFILEINFO* pFixedInfo = 0;  // pointer to fixed file info structure 
// get the fixed file info (language-independent) 
if(VerQueryValue(&data[0], TEXT("\\"), (void**)&pFixedInfo, (UINT *)&uiVerLen) == 0) 
{ 
    return false; 
} 

strProductVersion.Format("%u.%u.%u.%u", 
    HIWORD (pFixedInfo->dwProductVersionMS), 
    LOWORD (pFixedInfo->dwProductVersionMS), 
    HIWORD (pFixedInfo->dwProductVersionLS), 
    LOWORD (pFixedInfo->dwProductVersionLS)); 
+0

Danke, das ist sehr interessant, großartige Lösung! – ghiboz

+0

Das bekommt andere Informationen von Mark Ransoms Antwort. Die Werte, die Sie abrufen, sind vier Ganzzahlen von der obersten Zeile von PRODUCTVERSION in der Ressourcendatei. Die Antwort von Marks ruft jedoch die Zeichenfolge "ProductVersion" unter dem Block "StringFileInfo" ab. –

0

Manchmal Zugriffsverletzung, wenn die Verwendung VerQueryValueA I erhalten. Aber ich habe nie diesen Fehler bei der Verwendung VerQueryValueW. Ich denke etwas stimmt nicht mit VerQueryValueA in version.dll. Daher verwende ich VerQueryValueW statt VerQueryValueA sogar in Projekten Multi-Byte-Zeichencodierung. Here is my code of ReadVersion function