Здравствуйте, 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