Re: Программно изменить коментрарии к версии
От: McQwerty Россия  
Дата: 07.11.05 15:56
Оценка: 7 (1)
Здравствуйте, stepaster, Вы писали:

S>Существует готовый exe файл. Нужно в ресурсе version этого файла программно изменить коментарии (пункт Comments). Пробовал способо описанным здесь http://www.codeproject.com/samples/UpdateVersion.asp не получилось, exe-шник перестает запускаться после внесения изменений.


Разбирался я с такой штукой. Вот движок разбора/замены/сбора VERSION_INFO:

Заголовок:
class VVersionInfo: public VObject
{
public:
    class VCommonVersionInfo: public VObject
    {
    public:
        VCommonVersionInfo (LPCVOID pMemoryLocation, DWORD nLevel);
        virtual ~VCommonVersionInfo ();

    public:
        DWORD Size () const;
        DWORD HeaderSize () const;
        DWORD ChildSize () const;
        BOOL Compile (LPVOID pMemoryLocation);
        VOID ReplaceValue (LPCVOID pValue, DWORD dwSize);
        DWORD RealSize () const;

    public:
        WORD m_wLength;
        WORD m_wValueLength;
        WORD m_wType;
        LPWSTR m_pszKey;
        QBuffer m_Value;
        DWORD m_nSize;
        DWORD m_nLevel;
    }; // VCommonVersionInfo

public:
    VVersionInfo (const LPVOID pMemoryLocation, DWORD nLevel = 0);
    virtual ~VVersionInfo ();

public:
    DWORD Size () const;
    BOOL Compile (LPVOID pMemoryLocation) const;
    BOOL ReplaceValue (LPCWSTR pszPath, LPCVOID pValue, DWORD dwSize);
    BOOL ReplaceValue (LPCWSTR pszPath, LPCWSTR pszValue);
    LPBYTE GetPtr (LPCWSTR pszPath, DWORD& dwSize);
    VVersionInfo* Find (LPWSTR pszKey) const;

public:
    typedef VArray <VVersionInfo*> VChilds;

    VCommonVersionInfo* m_pInfo;
    VChilds m_Childs;
}; // VVersionInfo


Исходник:
#include "stdafx.h"

#ifndef __verInfo_h
    #include "verInfo.h"
#endif

/*****************************************************************************/

VVersionInfo::VCommonVersionInfo::VCommonVersionInfo (LPCVOID pMemoryLocation, DWORD nLevel)
{
    const LPBYTE pTemp = (LPBYTE) pMemoryLocation;

    m_nSize = 0;
    m_nLevel = nLevel;

    m_wLength = * ((LPWORD) (pTemp + m_nSize));            m_nSize += sizeof (WORD);
    m_wValueLength = * ((LPWORD) (pTemp + m_nSize));    m_nSize += sizeof (WORD);
    m_wType =  * ((LPWORD) (pTemp + m_nSize));            m_nSize += sizeof (WORD);

    m_pszKey = _wcsdup ((LPCWSTR) (pTemp + m_nSize));
    m_nSize += (wcslen (m_pszKey) + 1) * sizeof (WCHAR);

    m_nSize += (4 - m_nSize) & 3;    // выравнивание на 32 бита

    DWORD dwFactor = (m_nLevel == 3) ? sizeof (WORD) : 1;
    m_Value. Assign (pTemp + m_nSize, m_wValueLength * dwFactor);
    m_nSize += m_wValueLength * dwFactor;
    
    m_nSize += (4 - m_nSize) & 3;    // выравнивание на 32 бита
} // VVersionInfo::VCommonVersionInfo::VCommonVersionInfo

DWORD VVersionInfo::VCommonVersionInfo::HeaderSize () const
{
    DWORD nSize = (sizeof (WORD) * 3) + ((wcslen (m_pszKey) + 1) * sizeof (WCHAR));

    return nSize + ((4 - nSize) & 3);
} // VVersionInfo::VCommonVersionInfo::HeaderSize

VVersionInfo::VCommonVersionInfo::~VCommonVersionInfo ()
{
    free (m_pszKey);
} // VVersionInfo::VCommonVersionInfo::~VCommonVersionInfo

DWORD VVersionInfo::VCommonVersionInfo::Size () const
{
    return m_nSize;
} // VVersionInfo::VCommonVersionInfo::Size

VOID VVersionInfo::VCommonVersionInfo::ReplaceValue (LPCVOID pValue, DWORD dwSize)
{
    DWORD dwFactor = (m_nLevel == 3) ? sizeof (WORD) : 1;
    m_wValueLength = (WORD) (dwSize / dwFactor);
    m_Value. Assign ((LPBYTE) pValue, dwSize);

    m_nSize = m_wLength = (WORD) (RealSize ());
} // VVersionInfo::VCommonVersionInfo::ReplaceValue

BOOL VVersionInfo::VCommonVersionInfo::Compile (LPVOID pMemoryLocation)
{
    LPBYTE pTemp = (LPBYTE) pMemoryLocation;

    DWORD nOffset = 0;

    DWORD dwFactor = (m_nLevel == 3) ? sizeof (WORD) : 1;
    * ((LPWORD) (pTemp + nOffset)) = m_wLength;            nOffset += sizeof (WORD);
    * ((LPWORD) (pTemp + nOffset)) = m_wValueLength;    nOffset += sizeof (WORD);
    * ((LPWORD) (pTemp + nOffset)) = m_wType;            nOffset += sizeof (WORD);

    wcscpy ((LPWSTR) (pTemp + nOffset), m_pszKey);
    nOffset += (wcslen (m_pszKey) + 1) * sizeof (WCHAR);

    if (m_Value. Size ())
    {
        nOffset += (4 - nOffset) & 3;    // выравнивание на 32 бита
        CopyMemory (pTemp + nOffset, m_Value. Get (), m_Value. Size ());
        nOffset += m_Value. Size ();
    }

    nOffset += (4 - nOffset) & 3;    // выравнивание на 32 бита

    m_nSize = nOffset;

    return TRUE;
} // VVersionInfo::VCommonVersionInfo::Compile

DWORD VVersionInfo::VCommonVersionInfo::ChildSize () const
{
    if (m_nSize < m_wLength)
    {
        DWORD nResult = m_wLength - m_nSize;
        return nResult + ((4 - nResult) & 3);
    }
    else
        return 0;
} // VVersionInfo::VCommonVersionInfo::ChildSize

DWORD VVersionInfo::VCommonVersionInfo::RealSize () const
{
    DWORD nSize = HeaderSize ();
    if (m_wValueLength)
    {
        DWORD dwFactor = (m_nLevel == 3) ? sizeof (WORD) : 1;
        nSize += m_wValueLength * dwFactor;
        nSize += ((4 - nSize) & 3);
    }

    return nSize;
} // VVersionInfo::VCommonVersionInfo::RealSize

/*****************************************************************************/

VVersionInfo::VVersionInfo (const LPVOID pMemoryLocation, DWORD nLevel)
{
    LPBYTE pTemp = (LPBYTE) pMemoryLocation;
    m_pInfo = new VCommonVersionInfo (pMemoryLocation, nLevel);
    INT dwSizeRest = m_pInfo -> ChildSize ();
    pTemp += m_pInfo -> Size ();

    while (dwSizeRest > 0)
    {
        VVersionInfo* pChild = new VVersionInfo (pTemp, nLevel + 1);
        m_Childs. Add (pChild);
        DWORD dwItemSize = pChild -> Size ();
        pTemp += dwItemSize;
        dwSizeRest -= dwItemSize;

        if (dwSizeRest < 0)
        {
            dwSizeRest = 0;
        }
    }
} // VVersionInfo::VVersionInfo

BOOL VVersionInfo::Compile (LPVOID pMemoryLocation) const
{
    LPBYTE pTemp = (LPBYTE) pMemoryLocation;

    m_pInfo -> m_wLength = (WORD) Size ();
    m_pInfo -> Compile (pTemp);
    pTemp += m_pInfo -> Size ();

    for (INT i = 0; i < m_Childs. Count (); i ++)
    {
        m_Childs [i] -> Compile (pTemp);
        pTemp += m_Childs [i] -> Size ();
    }

    return TRUE;
} // VVersionInfo::Compile

VVersionInfo::~VVersionInfo ()
{
    delete m_pInfo;
} // VVersionInfo::~VVersionInfo

DWORD VVersionInfo::Size () const
{
    DWORD nSize = m_pInfo -> RealSize ();

    for (INT i = 0; i < m_Childs. Count (); i ++)
        nSize += m_Childs [i] -> Size ();

    return nSize;
} // VVersionInfo::Size

VVersionInfo* VVersionInfo::Find (LPWSTR pszKey) const
{
    for (INT i = 0; i < m_Childs. Count (); i ++)
        if (wcsicmp (pszKey, m_Childs [i] -> m_pInfo -> m_pszKey) == 0)
            return m_Childs [i];

    return NULL;
} // VVersionInfo::Find

BOOL VVersionInfo::ReplaceValue (LPCWSTR pszPath, LPCVOID pValue, DWORD dwSize)
{
    LPWSTR pszKeyPath = wcsdup (pszPath);
    LPWSTR pszKey = wcstok (pszKeyPath, L"\\");

    VVersionInfo *pLevel = this;

    while (pszKey)
    {
        pLevel = pLevel -> Find (pszKey);
        if (!pLevel) break;
        pszKey = wcstok (NULL, L"\\");
    }

    if (pLevel)
        pLevel -> m_pInfo -> ReplaceValue (pValue, dwSize);

    free (pszKeyPath);

    return pLevel != NULL;
} // VVersionInfo::ReplaceValue

BOOL VVersionInfo::ReplaceValue (LPCWSTR pszPath, LPCWSTR pszValue)
{
    return ReplaceValue (pszPath, pszValue, (wcslen (pszValue) + 1) * sizeof (WCHAR));
} // VVersionInfo::ReplaceValue

LPBYTE VVersionInfo::GetPtr (LPCWSTR pszPath, DWORD& dwSize)
{
    LPWSTR pszKeyPath = wcsdup (pszPath);
    LPWSTR pszKey = wcstok (pszKeyPath, L"\\");
    dwSize = 0;

    VVersionInfo *pLevel = this;

    while (pszKey)
    {
        pLevel = pLevel -> Find (pszKey);
        if (!pLevel) break;
        pszKey = wcstok (NULL, L"\\");
    }

    if (pLevel)
    {
        dwSize = pLevel -> m_pInfo -> m_Value. Size ();
        return pLevel -> m_pInfo -> m_Value. Get ();
    }

    return NULL;
} // VVersionInfo::GetPtr


Пример использования:
VOID VWorker::ProcessFileVersion (HINSTANCE hFile, LPCTSTR pszFileName, LPCTSTR pszName, WORD wLangID)
{
    HRSRC hRsrc = FindResourceEx (hFile, RT_VERSION, pszName, wLangID);

    HGLOBAL hVersion = LoadResource (hFile, hRsrc);
    LPVOID pVer = LockResource (hVersion);
    VVersionInfo ver (pVer);
    FreeLibrary (hFile);

    // Здесь можно модифицировать содержимое ver
        VS_FIXEDFILEINFO* pFixed = (VS_FIXEDFILEINFO*) ver. GetPtr (L"", dwLangsSize);

        pFixed -> dwProductVersionMS = m_dwVersionMS;
        pFixed -> dwProductVersionLS = m_dwVersionLS;

        pFixed -> dwFileVersionMS = m_dwVersionMS;
        pFixed -> dwFileVersionLS = m_dwVersionLS;
    // или так (Номера языков брать в "\\VarFileInfo\\Translation")
        ver. ReplaceValue (L"\\StringFileInfo\\????????\\CompanyName", L"bla-bla-bla");

    // pMemoryLocation - просто указатель на кусок памяти
    ZeroMemory (m_pMemoryLocation, 0x10000);
    ver. Compile (m_pMemoryLocation);

    DWORD dwNeededSize = ver. Size ();
    dwNeededSize += (16 - dwNeededSize) & 0xF;

    HANDLE hUpdate = BeginUpdateResource (pszFileName, FALSE);
    BOOL bUpdated = UpdateResource (hUpdate, RT_VERSION, MAKEINTRESOURCE (VS_VERSION_INFO),
        wLangID, m_pMemoryLocation, dwNeededSize);
    EndUpdateResource (hUpdate, FALSE);
} // VWorker::ProcessFileVersion
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.