Ответ 1
Если ОС является Windows, используйте функции GetFileVersionInfo
и VerQueryValue
.
Есть ли простой способ получить информацию о версии приложения из файла ресурсов во время выполнения?
Фактически то, что я хотел бы сделать, это иметь версию "Версия X.Y.Z", отображаемую во время выполнения, без какой-либо отдельной переменной, в которой я должен был бы синхронизироваться с моими продуктами ProductVersion и FileVersion.
Чтобы уточнить: да, это стандартный проект Windows С++. Я знаю метод GetFileVersionInfo, но кажется глупым открыть двоичный файл изнутри версии в памяти, чтобы запросить информацию о версии - я Я уверен, что я пропустил что-то очевидное здесь: -)
Если ОС является Windows, используйте функции GetFileVersionInfo
и VerQueryValue
.
Я не считаю, что есть более простой способ (чем открыть файл и использовать GetFileVersionInfo и VerQueryValue). Я использую следующий код, если это полезно:
static CString GetProductVersion()
{
CString strResult;
char szModPath[ MAX_PATH ];
szModPath[ 0 ] = '\0';
GetModuleFileName( NULL, szModPath, sizeof(szModPath) );
DWORD dwHandle;
DWORD dwSize = GetFileVersionInfoSize( szModPath, &dwHandle );
if( dwSize > 0 )
{
BYTE* pbBuf = static_cast<BYTE*>( alloca( dwSize ) );
if( GetFileVersionInfo( szModPath, dwHandle, dwSize, pbBuf ) )
{
UINT uiSize;
BYTE* lpb;
if( VerQueryValue( pbBuf,
"\\VarFileInfo\\Translation",
(void**)&lpb,
&uiSize ) )
{
WORD* lpw = (WORD*)lpb;
CString strQuery;
strQuery.Format( "\\StringFileInfo\\%04x%04x\\ProductVersion", lpw[ 0 ], lpw[ 1 ] );
if( VerQueryValue( pbBuf,
const_cast<LPSTR>( (LPCSTR)strQuery ),
(void**)&lpb,
&uiSize ) && uiSize > 0 )
{
strResult = (LPCSTR)lpb;
}
}
}
}
return strResult;
}
Дэвид
Единственный официально поддерживаемый подход - использовать GetFileVersionInfo()
и VerQueryValue()
. Однако, как вы заметили, GetFileVersionInfo()
требует, чтобы вы передали имя исполняемого файла. Есть причина для этого. Хотя получить имя исполняемого файла процесса с помощью GetModuleFileName()
просто, это не самый эффективный вариант, особенно если исполняемый файл запущен из удаленного ресурса, и даже не гарантируется точность, если исполняемый файл был изменен на после того, как процесс запущен.
Вы можете получить доступ к информации о версии процесса, который уже запущен в памяти, вызвав FindResource()
, чтобы найти ресурс процесса RT_VERSION
, затем используйте LoadResource()
и LockResource()
, чтобы получить указатель на его данные. Заманчиво передать этот указатель как параметр pBlock
VerQueryValue()
, но будьте осторожны, потому что может привести к сбою вашего кода! Если вы напрямую подключаетесь к ресурсу RT_VERSION
, вам лучше не использовать VerQueryValue()
вообще. Формат ресурса RT_VERSION
документирован, поэтому вы можете вручную анализировать необработанные данные, это не очень сложно.
Как уже было сказано, нет простого способа.
Вы можете найти здесь отличный рабочий пример (ATL бесплатно).