Получение версии приложения из приложения

Есть ли простой способ получить информацию о версии приложения из файла ресурсов во время выполнения?

Фактически то, что я хотел бы сделать, это иметь версию "Версия X.Y.Z", отображаемую во время выполнения, без какой-либо отдельной переменной, в которой я должен был бы синхронизироваться с моими продуктами ProductVersion и FileVersion.

Чтобы уточнить: да, это стандартный проект Windows С++. Я знаю метод GetFileVersionInfo, но кажется глупым открыть двоичный файл изнутри версии в памяти, чтобы запросить информацию о версии - я Я уверен, что я пропустил что-то очевидное здесь: -)

Ответ 1

Если ОС является Windows, используйте функции GetFileVersionInfo и VerQueryValue.

Ответ 2

Я не считаю, что есть более простой способ (чем открыть файл и использовать 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;
}

Дэвид

Ответ 3

Единственный официально поддерживаемый подход - использовать GetFileVersionInfo() и VerQueryValue(). Однако, как вы заметили, GetFileVersionInfo() требует, чтобы вы передали имя исполняемого файла. Есть причина для этого. Хотя получить имя исполняемого файла процесса с помощью GetModuleFileName() просто, это не самый эффективный вариант, особенно если исполняемый файл запущен из удаленного ресурса, и даже не гарантируется точность, если исполняемый файл был изменен на после того, как процесс запущен.

Вы можете получить доступ к информации о версии процесса, который уже запущен в памяти, вызвав FindResource(), чтобы найти ресурс процесса RT_VERSION, затем используйте LoadResource() и LockResource(), чтобы получить указатель на его данные. Заманчиво передать этот указатель как параметр pBlock VerQueryValue(), но будьте осторожны, потому что может привести к сбою вашего кода! Если вы напрямую подключаетесь к ресурсу RT_VERSION, вам лучше не использовать VerQueryValue() вообще. Формат ресурса RT_VERSION документирован, поэтому вы можете вручную анализировать необработанные данные, это не очень сложно.

Ответ 4

Как уже было сказано, нет простого способа.

Вы можете найти здесь отличный рабочий пример (ATL бесплатно).