كيف يمكنني قراءة من نسخة الموارد في Visual C++
-
11-07-2019 - |
سؤال
لدي نسخة الموارد في الموارد في C++ المشروع الذي يحتوي على رقم الإصدار ، حقوق الطبع والنشر وبناء التفاصيل.هل هناك طريقة سهلة للوصول إلى هذا في وقت التشغيل إلى ملء بلدي مساعدة/عن الحوار كما أنا حاليا الحفاظ على منفصلة const قيم هذه المعلومات.ومن الناحية المثالية ، ينبغي أن حل العمل على ويندوز/CE المحمول و الإصدارات السابقة من Visual C++ (6.0 وما فوق).
المحلول
وهذا هو نسخة معدلة من جوابي الأصلي.
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;
}
نصائح أخرى
لتحصل على نتيجة مستقلة لغة لتغير الجواب مارك:
// 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));
وشيء من هذا القبيل قد تحصل على انك بدأته، وربما:
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));
وشيء من هذا القبيل سوف اعطيكم الوصول الخام لبيانات الموارد والحصول على انك بدأته:
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);
وحذار! باستخدام FindResource..LockResource ليس صحيحا. وسوف يعمل أحيانا (كما فعلت في برنامجي تجريبي صغير) وتسبب أحيانا خرق الوصول (على سبيل المثال: رمز الإنتاج I تبذل التجريبي ل).
ووVerQueryValue () الدول الوثائق التي يجب عليك الاتصال GetFileVersionInfoSize وGetFileVersionInfo بدلا من ذلك. ريمون تشن يفسر، انظر http://blogs.msdn.com /oldnewthing/archive/2006/12/26/1365215.aspx
حسنا, قليلا أكثر googleing وجدت التالية على CodeGuru.أساسا يستخدم هذا النهج CFileVersionInfo الكائن للحصول على أي ملف.يجب أن تكون مثيرة للاهتمام أن نرى ما اذا كان يعمل على تشغيلها حاليا .ملف EXE على ويندوز CE.
وأحيانا أتلقى انتهاك وصول عند استخدام VerQueryValueA
. لكنني لم يحصل هذا الخطأ عند استخدام VerQueryValueW
. أعتقد أن هناك شيئا خاطئا مع VerQueryValueA
في version.dll. لذلك يمكنني استخدام VerQueryValueW
بدلا من VerQueryValueA
حتى في مشاريع متعددة البايت ترميز الأحرف. هنا هو قانون بلدي وظيفة ReadVersion