Как получить информацию о версии с помощью C ++ Builder - PullRequest
0 голосов
/ 30 ноября 2018

Поток в Как получить информацию о версии показывает код для получения FileVersion, мне нужно получить другие значения, включая некоторые, которые я сам добавил в таблицу VersionInfo.

Как я могуполучить их с помощью C ++ Builder 10.2 (Токио)?

Я использовал их для получения в C ++ Builder 6.0, используя метод VerQueryValue, но он вызывает слишком много исключений для типов.

Я не знаю, как изменить код на C ++ Builder 10.2.

Ниже приведен реальный код, который я использую:

class.h

struct TransArray
{
    WORD LanguageID, CharacterSet;
};
DWORD VerInfo, VerSize;
HANDLE MemHandle;
LPVOID MemPtr, BufferPtr;
UINT BufferLength;
TransArray *Array;
char QueryBlock[255];
String FFileVersion ;

class.cpp

// this one of the methods which have errors
String __fastcall TAppVersion::GetFileVersion(void)
{
    String Result ;
    BufferPtr = NULL ;

    // Get the product version.
    wsprintf(QueryBlock, "\\StringFileInfo\\%04x%04x\\FileVersion",
                    Array[0].LanguageID, Array[0].CharacterSet);
    VerQueryValue(MemPtr, QueryBlock, &BufferPtr, &BufferLength);

    if(BufferPtr) Result = (char *)BufferPtr;

    return(Result);
}
//---------------------------------------------------
__fastcall TAppVersion::TAppVersion()
{
    FFileName = Application->ExeName ;
    VerSize = GetFileVersionInfoSize(FFileName.c_str(), &VerInfo);
    if (VerSize > 0) {
        MemHandle = GlobalAlloc(GMEM_MOVEABLE, VerSize);
        MemPtr = GlobalLock(MemHandle);
        GetFileVersionInfo(FFileName.c_str(), VerInfo, VerSize, MemPtr);
        VerQueryValue(MemPtr, "\\VarFileInfo\\Translation", &BufferPtr,
                                &BufferLength);
        Array = (TransArray *)BufferPtr;

        FFileVersion = GetFileVersion();
    }
}
//-----------------------------------------------

Ответы [ 2 ]

0 голосов
/ 04 декабря 2018

Ваш код неправильно смешивает логику ANSI и UNICODE.VerQueryValue() - это макрос препроцессора, который отображается на VerQueryValueW() или VerQueryValueA() в зависимости от того, определен UNICODE или нет, соответственно.Ваш код предполагает, что VerQueryValueA() используется, но это не всегда так.В современных версиях C ++ Builder вместо этого по умолчанию будет использоваться VerQueryValueW().

Вместо этого попробуйте что-то вроде этого:

struct TransArray
{
    WORD LanguageID, CharacterSet;
};

DWORD VerInfo, VerSize;
LPVOID MemPtr, BufferPtr;
UINT BufferLength;
TransArray *Array;
String FFileName, FFileVersion;

...

#include <tchar.h>

String __fastcall TAppVersion::GetFileVersion(void)
{
    String Result;

    if (MemPtr && Array)
    {
        // Get the product version.
        TCHAR QueryBlock[40];
        _stprintf(QueryBlock, _T("\\StringFileInfo\\%04x%04x\\FileVersion"), Array[0].LanguageID, Array[0].CharacterSet);
        if (VerQueryValue(MemPtr, QueryBlock, &BufferPtr, &BufferLength)) {
            Result = String(static_cast<TCHAR*>(BufferPtr), BufferLength).Trim();
        }
    }

    return Result;
}
//---------------------------------------------------
__fastcall TAppVersion::TAppVersion()
{
    MemPtr = NULL;
    Array = NULL;

    FFileName = Application->ExeName;

    DWORD Unused;
    VerSize = GetFileVersionInfoSize(FFileName.c_str(), &Unused);
    if (VerSize == 0) return;

    MemPtr = new BYTE[VerSize];
    if (GetFileVersionInfo(FFileName.c_str(), Unused, VerSize, MemPtr)) {
        if (VerQueryValue(MemPtr, TEXT("\\VarFileInfo\\Translation"), &BufferPtr, &BufferLength) {
            Array = (TransArray *) BufferPtr;
            FFileVersion = GetFileVersion();
        }
    }
}
//-----------------------------------------------
__fastcall TAppVersion::~TAppVersion()
{
    delete[] static_cast<BYTE*>(MemPtr);
}
//-----------------------------------------------

Хотя на самом деле вам не следует полагатьсяна TCHAR вообще в современном коде:

struct TransArray
{
    WORD LanguageID, CharacterSet;
};

DWORD VerInfo, VerSize;
LPVOID MemPtr, BufferPtr;
UINT BufferLength;
TransArray *Array;
UnicodeString FFileName, FFileVersion;

...

UnicodeString __fastcall TAppVersion::GetFileVersion(void)
{
    UnicodeString Result;

    if (MemPtr && Array)
    {
        // Get the product version.
        WCHAR QueryBlock[40];
        swprintf(QueryBlock, L"\\StringFileInfo\\%04x%04x\\FileVersion", Array[0].LanguageID, Array[0].CharacterSet);
        if (VerQueryValueW(MemPtr, QueryBlock, &BufferPtr, &BufferLength)) {
            Result = UnicodeString(static_cast<WCHAR*>(BufferPtr), BufferLength).Trim();
        }
    }

    return Result;
}
//---------------------------------------------------
__fastcall TAppVersion::TAppVersion()
{
    MemPtr = NULL;
    Array = NULL;

    FFileName = Application->ExeName;

    DWORD Unused;
    VerSize = GetFileVersionInfoSizeW(FFileName.c_str(), &Unused);
    if (VerSize == 0) return;

    MemPtr = new BYTE[VerSize];
    if (GetFileVersionInfoW(FFileName.c_str(), Unused, VerSize, MemPtr)) {
        if (VerQueryValueW(MemPtr, L"\\VarFileInfo\\Translation", &BufferPtr, &BufferLength) {
            Array = (TransArray *) BufferPtr;
            FFileVersion = GetFileVersion();
        }
    }
}
//-----------------------------------------------
__fastcall TAppVersion::~TAppVersion()
{
    delete[] static_cast<BYTE*>(MemPtr);
}
//-----------------------------------------------
0 голосов
/ 30 ноября 2018

Некоторое время назад я немного поиграл с этим.Он не завершен, и я бы назвал его бета-1. Но он идет.

Заголовок:

class TAppVerInfo
{
public:
    __fastcall TAppVerInfo(const wchar_t* pModPath);
    __fastcall virtual ~TAppVerInfo(void);

    __property System::String LanguagesCodePage                         = {read = GetCodePage};
    __property System::String Comments[System::String LanId]            = {read = GetComments};
    __property System::String InternalName[System::String LanId]        = {read = GetInternalName};
    __property System::String ProductName[System::String LanId]         = {read = GetProductName};
    __property System::String CompanyName[System::String LanId]         = {read = GetCompanyName};
    __property System::String LegalCopyright[System::String LanId]      = {read = GetLegalCopyright};
    __property System::String ProductVersion[System::String LanId]      = {read = GetProductVersion};
    __property System::String FileDescription[System::String LanId]     = {read = GetFileDescription};
    __property System::String LegalTrademarks[System::String LanId]     = {read = GetLegalTrademarks};
    __property System::String PrivateBuild[System::String LanId]        = {read = GetPrivateBuild};
    __property System::String FileVersion[System::String LanId]         = {read = GetFileVersion};
    __property System::String OriginalFilename[System::String LanId]    = {read = GetOriginalFilename};
    __property System::String SpecialBuild[System::String LanId]        = {read = GetSpecialBuild};

protected:
    void *VerInfo;

    System::String __fastcall GetCodePage(void);
    System::String __fastcall GetComments(System::String LanId);
    System::String __fastcall GetInternalName(System::String LanId);
    System::String __fastcall GetProductName(System::String LanId);
    System::String __fastcall GetCompanyName(System::String LanId);
    System::String __fastcall GetLegalCopyright(System::String LanId);
    System::String __fastcall GetProductVersion(System::String LanId);
    System::String __fastcall GetFileDescription(System::String LanId);
    System::String __fastcall GetLegalTrademarks(System::String LanId);
    System::String __fastcall GetPrivateBuild(System::String LanId);
    System::String __fastcall GetFileVersion(System::String LanId);
    System::String __fastcall GetOriginalFilename(System::String LanId);
    System::String __fastcall GetSpecialBuild(System::String LanId);
    System::String __fastcall GetValue(const System::String& LanId, const wchar_t* pName);
};

и CPP:

__fastcall TAppVerInfo::TAppVerInfo(const wchar_t* pModPath)
{
    DWORD dwUnused;
    DWORD VerInfoSize = GetFileVersionInfoSize(pModPath, &dwUnused);

    VerInfo = malloc(VerInfoSize);
    if(VerInfo)
    {
        if(0 == GetFileVersionInfo(pModPath, 0, VerInfoSize, VerInfo))
        {
            free(VerInfo);
            VerInfo = NULL;
            throw Exception(SysErrorMessage(GetLastError()));
        }
    } //040904E4
}
//---------------------------------------------------------------------------
__fastcall TAppVerInfo::~TAppVerInfo(void)
{
    if(VerInfo)
        free(VerInfo);
}
//---------------------------------------------------------------------------
System::String __fastcall TAppVerInfo::GetCodePage(void)
{
    System::String retVal;

    if(VerInfo)
    {
        struct LANGANDCODEPAGE
        {
            WORD wLanguage;
            WORD wCodePage;
        } *lpTranslate;
        UINT cbTranslate;
        TAutoStringList tStr(new TStringList);
        UINT i;

        VerQueryValue(VerInfo,L"\\VarFileInfo\\Translation", (LPVOID*)&lpTranslate, &cbTranslate);
        for(i = 0; i < (cbTranslate/sizeof(LANGANDCODEPAGE)); i++)
            tStr->Add(System::String().sprintf(L"%04x%04x", lpTranslate[i].wLanguage, lpTranslate[i].wCodePage));
        retVal = tStr->CommaText;
    }
    return retVal;
}
//---------------------------------------------------------------------------
System::String __fastcall TAppVerInfo::GetComments(System::String LanId)
{
    return GetValue(LanId, L"Comments");
}
//---------------------------------------------------------------------------
System::String __fastcall TAppVerInfo::GetInternalName(System::String LanId)
{
    return GetValue(LanId, L"InternalName");
}
//---------------------------------------------------------------------------
System::String __fastcall TAppVerInfo::GetProductName(System::String LanId)
{
    return GetValue(LanId, L"ProductName");
}
//---------------------------------------------------------------------------
System::String __fastcall TAppVerInfo::GetCompanyName(System::String LanId)
{
    return GetValue(LanId, L"CompanyName");
}
//---------------------------------------------------------------------------
System::String __fastcall TAppVerInfo::GetLegalCopyright(System::String LanId)
{
    return GetValue(LanId, L"LegalCopyright");
}
//---------------------------------------------------------------------------
System::String __fastcall TAppVerInfo::GetProductVersion(System::String LanId)
{
    return GetValue(LanId, L"ProductVersion");
}
//---------------------------------------------------------------------------
System::String __fastcall TAppVerInfo::GetFileDescription(System::String LanId)
{
    return GetValue(LanId, L"FileDescription");
}
//---------------------------------------------------------------------------
System::String __fastcall TAppVerInfo::GetLegalTrademarks(System::String LanId)
{
    return GetValue(LanId, L"LegalTrademarks");
}
//---------------------------------------------------------------------------
System::String __fastcall TAppVerInfo::GetPrivateBuild(System::String LanId)
{
    return GetValue(LanId, L"PrivateBuild");
}
//---------------------------------------------------------------------------
System::String __fastcall TAppVerInfo::GetFileVersion(System::String LanId)
{
    return GetValue(LanId, L"FileVersion");
}
//---------------------------------------------------------------------------
System::String __fastcall TAppVerInfo::GetOriginalFilename(System::String LanId)
{
    return GetValue(LanId, L"OriginalFilename");
}
//---------------------------------------------------------------------------
System::String __fastcall TAppVerInfo::GetSpecialBuild(System::String LanId)
{
    return GetValue(LanId, L"SpecialBuild");
}
//---------------------------------------------------------------------------
System::String __fastcall TAppVerInfo::GetValue(const System::String& LanId, const wchar_t* pName)
{
    System::String retVal;

    if(VerInfo)
    {
        System::String aPath(System::String().sprintf(L"\\StringFileInfo\\%s\\%s", LanId.c_str(), pName));
        wchar_t *pBuf;
        UINT uLen;

        if(VerQueryValue(VerInfo, aPath.c_str(), (void**)&pBuf, &uLen))
            retVal = System::String(pBuf);
    }
    return retVal;
}
...