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).
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;
}
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));
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));
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);
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
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.
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