Comment lire à partir D'une ressource de version dans Visual C++

j'ai une ressource de version dans mes ressources dans un projet C++ qui contient le numéro de version, le copyright et les détails de construction. Y a-t-il un moyen facile d'y accéder à l'exécution pour remplir mon aide/à propos de dialog car je maintiens actuellement des valeurs de const séparées de cette information. Idéalement, la solution devrait fonctionner pour Windows/CE mobile et les versions précédentes de Visual C++ (6.0 upwards).

30
demandé sur Shane MacLaughlin 2008-11-25 10:54:00

7 réponses

C'est une version éditée de ma réponse originale à cette question.

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;
}
30
répondu Mark Ransom 2016-06-01 16:40:00

Pour obtenir un langage indépendant de suite à la Marque de répondre à modifier :

   // 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;
}

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));
13
répondu EdM 2017-01-17 06:57:41

quelque Chose comme pourrait vous aider à démarrer, peut-être:

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));
7
répondu Will Dean 2008-11-25 08:48:49

quelque Chose comme cela vous donnera accès direct à la ressource de données et vous aider à démarrer:

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);
5
répondu Rob 2008-11-25 07:57:48

Méfiez-vous! Utiliser FindResource..LockResource n'est pas correct. Il fonctionne parfois (comme dans mon petit programme de démo) et cause parfois des violations d'accès (exemple: le code de production pour lequel je faisais la démo).

la documentation de VerQueryValue () indique que vous devriez appeler GetFileVersionInfoSize et GetFileVersionInfo à la place. Raymond Chen explique, voir http://blogs.msdn.com/oldnewthing/archive/2006/12/26/1365215.aspx

4
répondu Leo 2010-02-24 13:02:06

Ok, un peu plus de googleing a trouvé le suivant sur CodeGuru. Fondamentalement, cette approche utilise le CFileVersionInfo objet pour obtenir sur un fichier donné. Il devrait être intéressant de voir si cela fonctionne sur le cours d'exécution .EXE et sous Windows CE.

0
répondu Shane MacLaughlin 2008-11-25 08:05:29

Parfois je recevoir une Violation d'Accès lors de l'utilisation de VerQueryValueA. Mais je n'ai jamais eu cette erreur lors de l'utilisation VerQueryValueW. Je pense que quelque chose de mal avec VerQueryValueA dans la version.DLL. C'est pourquoi j'utilise VerQueryValueW au lieu de VerQueryValueA même dans les projets D'encodage de caractères multi-octets. Voici mon code ReadVersion function

0
répondu Vitaly 2012-09-28 06:37:28