此处的文件版本信息,指:
也就是VS开发环境中的资源Version:
对于信息的读取,用C#实现起来很简单:
System.Diagnostics.FileVersionInfo fvi = System.Diagnostics.FileVersionInfo.GetVersionInfo(dllOrExeFilePathName);
fvi...
虽然C#获取的信息并不完整(当然,在大多数情况下这些信息已经足够)。
用资源修改工具或PE修改工具,可以对版本信息进行修改。
由于一些原因,需要对一些dll和exe进行批量修改、反复修改,并且将这些操作配置在VS2010的生成选项中(比如,选择Debug配置,则版本信息中的备注为“调试”,选择Release为“发行”)。
当然,在RC文件中,也是可以使用宏和预处理的:
VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,0,0,1
PRODUCTVERSION 1,0,0,1
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x40004L
FILETYPE 0x1L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "080404b0"
BEGIN
VALUE "CompanyName", "INFO"
#ifdef DEBUG
VALUE "Comment", "调试"
#else
VALUE "Comment", "发行"
#endif
VALUE "FileDescription", "INFO"
VALUE "FileVersion", "1.0.0.1"
VALUE "InternalName", "INFO"
VALUE "LegalCopyright", "INFO"
VALUE "OriginalFilename", "INFO"
VALUE "ProductName", "INFO"
VALUE "ProductVersion", "1.0.0.1"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x804, 1200
END
END
但问题在于,在IDE中一旦对资源进行了更改,则用户添加的任何内容都会丢失;也就是说,资源文件的内容是由IDE自动更新和维护的。
当然,这不是问题。我们可以使用编译前事件,写个小程序,根据配置修改rc文件中的相关内容。这个实现比较简单。
不过,本人采取了另外一种方法:使用编译后事件,对已经生成的dll或exe注入相关内容。这样做的好处是,对执行注入的程序稍加修改,就能批量处理任意数目、任意位置的dll和exe。
从网上逛了一圈,找到了一些示例,可惜的是,没看到有完整的。于是自己写了一个。
由于本人水平有限,加之时间有限,代码不大好,勿喷,欢迎改善之:
头文件:
#pragma once
class CVersionUpdater
{
public:
class CResourcePacker
{
public:
CResourcePacker() : Resource(NULL), Size(0) {}
~CResourcePacker() { Reset(); }
public:
void Reset();
void AppendWord(WORD value_);
void AppendWords(const WORD* value_, DWORD count_);
void AppendWChar(WCHAR value_);
void AppendWString(const WCHAR* value_);
void AppendAlignment() ;
void Append(const void* value_, DWORD size_);
inline BYTE* GetResource() const { return this->Resource; }
inline DWORD GetSize() const { return this->Size; }
private:
BYTE* Resource;
DWORD Size;
};
class CResourceParser
{
public:
CResourceParser(const BYTE* data_) : Data(data_),ParsedSize(0) {}
public:
WORD Word();
WCHAR WChar();
void Alignment();
const BYTE* Move(long size_);
long GetParsedSize() const { return this->ParsedSize; }
private:
const BYTE* Data;
long ParsedSize;
};
struct structLangageAndCodePage
{
WORD Language;
WORD CodePage;
};
class CStringTable : public structLangageAndCodePage
{
public:
CStringTable();
~CStringTable();
public:
inline const CString* GetComments() const { return this->Comments; }
inline const CString* GetCompanyName() const { return this->CompanyName; }
inline const CString* GetFileDescription() const { return this->FileDescription; }
inline const CString* GetFileVersion() const { return this->FileVersion; }
inline const CString* GetInternalName() const { return this->InternalName; }
inline const CString* GetLegalCopyright() const { return this->LegalCopyright; }
inline const CString* GetLegalTrademarks() const { return this->LegalTrademarks; }
inline const CString* GetOriginalFilename() const { return this->OriginalFilename; }
inline const CString* GetPrivateBuild() const { return this->PrivateBuild; }
inline const CString* GetProductName() const { return this->ProductName; }
inline const CString* GetProductVersion() const { return this->ProductVersion; }
inline const CString* GetSpecialBuild() const { return this->SpecialBuild; }
inline void SetComments(LPCTSTR value_) { this->Set(Comments, value_); }
inline void SetCompanyName(LPCTSTR value_) { this->Set(CompanyName, value_); }
inline void SetFileDescription(LPCTSTR value_) { this->Set(FileDescription, value_); }
inline void SetFileVersion(LPCTSTR value_) { this->Set(FileVersion, value_); }
inline void SetInternalName(LPCTSTR value_) { this->Set(InternalName, value_); }
inline void SetLegalCopyright(LPCTSTR value_) { this->Set(LegalCopyright, value_); }
inline void SetLegalTrademarks(LPCTSTR value_) { this->Set(LegalTrademarks, value_); }
inline void SetOriginalFilename(LPCTSTR value_) { this->Set(OriginalFilename, value_); }
inline void SetPrivateBuild(LPCTSTR value_) { this->Set(PrivateBuild, value_); }
inline void SetProductName(LPCTSTR value_) { this->Set(ProductName, value_); }
inline void SetProductVersion(LPCTSTR value_) { this->Set(ProductVersion, value_); }
inline void SetSpecialBuild(LPCTSTR value_) { this->Set(SpecialBuild, value_); }
void Set(CString*& which_, LPCTSTR value_);
void Reset();
void Pack(CResourcePacker& packer_) const;
void Parse(const BYTE* data_);
private:
CString* Comments;
CString* CompanyName;
CString* FileDescription;
CString* FileVersion;
CString* InternalName;
CString* LegalCopyright;
CString* LegalTrademarks;
CString* OriginalFilename;
CString* PrivateBuild;
CString* ProductName;
CString* ProductVersion;
CString* SpecialBuild;
};
class CStringFileInfo
{
public:
~CStringFileInfo();
public:
CArray Children;
public:
void Reset();
void Pack(CResourcePacker& packer_) const;
void Parse(const BYTE* data_);
};
class CVar
{
public:
CArray Value;
public:
void Pack(CResourcePacker& packer_) const;
void Parse(const BYTE* data_);
};
class CVarFileInfo
{
public:
~CVarFileInfo();
public:
CArray Children;
public:
void Reset();
void Pack(CResourcePacker& packer_) const;
void Parse(const BYTE* data_);
};
class CVersionInfo
{
public:
CVersionInfo();
~CVersionInfo();
public:
VS_FIXEDFILEINFO FixedFileInfo;
CStringFileInfo* StringFileInfo;
CVarFileInfo* VarFileInfo;
public:
void Reset();
void Pack(CResourcePacker& packer_) const;
void Parse(const BYTE* data_);
};
public:
CVersionUpdater();
~CVersionUpdater();
public:
bool Open(const CString& exeOrDll);
bool Update(WORD language_ = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL)) const;
public:
CVersionInfo* VersionInfo;
private:
CString ExeOrDll;
};
源文件:
#include "stdafx.h"
#include "VersionUpdater.h"
#pragma comment(linker, "/defaultlib:version.lib")
///////////////////////////////////////////////////////////////////////////
static WCHAR* SZKEY_VS_VERSION_INFO = L"VS_VERSION_INFO";
static WCHAR* SZKEY_STRINGFILEINFO = L"StringFileInfo";
static WCHAR* SZKEY_VARFILEINFO = L"VarFileInfo";
static WCHAR* SZKEY_TRANSLATION = L"Translation";
enum enumWType
{
WTYPE_TEXT = 1,
WTYPE_BINARY = 0,
};
static LPCTSTR StringKeys[] =
{
_T("Comments"),
_T("CompanyName"),
_T("FileDescription"),
_T("FileVersion"),
_T("InternalName"),
_T("LegalCopyright"),
_T("LegalTrademarks"),
_T("OriginalFilename"),
_T("PrivateBuild"),
_T("ProductName"),
_T("ProductVersion"),
_T("SpecialBuild")
};
int IndexInStringKeys(WCHAR* key)
{
int length = wcslen(key);
for(int i=0; i<12; ++i)
{
if(_wcsnicmp(StringKeys[i], key, length) == 0) return i;
}
return -1;
}
typedef CString* PCString;
typedef CString** PPCString;
DWORD WStringValueLength(const CString& value_)
{
return value_.GetLength();
}
void SetLength(BYTE* resource_, WORD length_)
{
*reinterpret_cast(resource_) = length_;
}
WORD GetLength(const BYTE* resource_)
{
return *reinterpret_cast(resource_);
}
///////////////////////////////////////////////////////////////////////////
void CVersionUpdater::CResourcePacker::Reset()
{
if(this->Resource)
{
delete []this->Resource;
this->Resource = NULL;
this->Size = 0;
}
}
void CVersionUpdater::CResourcePacker::AppendWord(WORD value_) { this->Append(&value_, sizeof(WORD)); }
void CVersionUpdater::CResourcePacker::AppendWords(const WORD* value_, DWORD count_) { this->Append(value_, sizeof(WORD)*count_); }
void CVersionUpdater::CResourcePacker::AppendWChar(WCHAR value_) { this->Append(&value_, sizeof(WCHAR)); }
void CVersionUpdater::CResourcePacker::AppendWString(const WCHAR* value_) { this->Append(value_, sizeof(WCHAR)*(wcslen(value_)+1)); }
void CVersionUpdater::CResourcePacker::AppendAlignment()
{
if(this->Size % 4 == 0) return;
static BYTE aligmentsValues[3] = {0,0,0};
DWORD aligments = 4 - (this->Size % 4);
this->Append(aligmentsValues, aligments);
}
void CVersionUpdater::CResourcePacker::Append(const void* value_, DWORD size_)
{
DWORD newSize = this->Size + size_;
BYTE* newResource = new BYTE[newSize];
if(this->Resource) memcpy(newResource, this->Resource, this->Size);
memcpy(newResource+this->Size, value_, size_);
delete []this->Resource;
this->Resource = newResource;
this->Size = newSize;
}
///////////////////////////////////////////////////////////////////////////
WORD CVersionUpdater::CResourceParser::Word()
{
return *reinterpret_cast(this->Move(sizeof(WORD)));
}
WCHAR CVersionUpdater::CResourceParser::WChar()
{
return *reinterpret_cast(this->Move(sizeof(WCHAR)));
}
void CVersionUpdater::CResourceParser::Alignment()
{
if(this->ParsedSize % 4 == 0) return;
DWORD alignments = 4 - (this->ParsedSize % 4);
this->ParsedSize += alignments;
}
const BYTE* CVersionUpdater::CResourceParser::Move(long size_)
{
const BYTE* v = (this->Data + this->ParsedSize);
this->ParsedSize += size_;
return v;
}
///////////////////////////////////////////////////////////////////////////
CVersionUpdater::CStringTable::CStringTable()
: Comments(NULL)
, CompanyName(NULL)
, FileDescription(NULL)
, FileVersion(NULL)
, InternalName(NULL)
, LegalCopyright(NULL)
, LegalTrademarks(NULL)
, OriginalFilename(NULL)
, PrivateBuild(NULL)
, ProductName(NULL)
, ProductVersion(NULL)
, SpecialBuild(NULL)
{
Language = 0;
CodePage = 0;
}
CVersionUpdater::CStringTable::~CStringTable() { Reset(); }
void CVersionUpdater::CStringTable::Set(CString*& which_, LPCTSTR value_)
{
if(which_) delete which_;
which_ = value_ ? (new CString(value_)) : NULL;
}
void CVersionUpdater::CStringTable::Reset()
{
if(this->Comments) { delete this->Comments; this->Comments = NULL; }
if(this->CompanyName) { delete this->CompanyName; this->CompanyName = NULL; }
if(this->FileDescription) { delete this->FileDescription; this->FileDescription = NULL; }
if(this->FileVersion) { delete this->FileVersion; this->FileVersion = NULL; }
if(this->InternalName) { delete this->InternalName; this->InternalName = NULL; }
if(this->LegalCopyright) { delete this->LegalCopyright; this->LegalCopyright = NULL; }
if(this->LegalTrademarks) { delete this->LegalTrademarks; this->LegalTrademarks = NULL; }
if(this->OriginalFilename) { delete this->OriginalFilename; this->OriginalFilename = NULL; }
if(this->PrivateBuild) { delete this->PrivateBuild; this->PrivateBuild = NULL; }
if(this->ProductName) { delete this->ProductName; this->ProductName = NULL; }
if(this->ProductVersion) { delete this->ProductVersion; this->ProductVersion = NULL; }
if(this->SpecialBuild) { delete this->SpecialBuild; this->SpecialBuild = NULL; }
}
void CStringTable_PackChild(CVersionUpdater::CResourcePacker& packer_, const CString& which_, const CString& value_)
{
packer_.Reset();
packer_.AppendWord(0);
packer_.AppendWord(WStringValueLength(value_));
packer_.AppendWord(WTYPE_TEXT);
packer_.AppendWString((LPCTSTR)which_);
packer_.AppendAlignment();
packer_.AppendWString(value_);
packer_.AppendAlignment();
SetLength(packer_.GetResource(), packer_.GetSize());
}
void CStringTable_ParseChild(const BYTE* data_, PPCString* values)
{
CVersionUpdater::CResourceParser parser(data_);
parser.Word();
WORD valueLength = parser.Word();
enumWType wType = (enumWType)parser.Word();ASSERT(wType == WTYPE_TEXT);
WCHAR* key = (WCHAR*)parser.Move(0);
parser.Move(sizeof(WCHAR)*(wcslen(key)+1));
parser.Alignment();
*values[IndexInStringKeys(key)] = new CString((WCHAR*)parser.Move(0));
}
void CVersionUpdater::CStringTable::Pack(CResourcePacker& packer_) const
{
packer_.Reset();
packer_.AppendWord(0);
packer_.AppendWord(0);
packer_.AppendWord(WTYPE_TEXT);
CString translate;
translate.Format(_T("%04x%04x"), this->Language, this->CodePage);
packer_.AppendWString(translate);
packer_.AppendAlignment();
PCString values[] =
{
this->Comments,
this->CompanyName,
this->FileDescription,
this->FileVersion,
this->InternalName,
this->LegalCopyright,
this->LegalTrademarks,
this->OriginalFilename,
this->PrivateBuild,
this->ProductName,
this->ProductVersion,
this->SpecialBuild
};
for(int i=0; i<12; ++i)
{
if(!values[i]) continue;
CResourcePacker childPacker;
CStringTable_PackChild(childPacker, StringKeys[i], *values[i]);
packer_.Append(childPacker.GetResource(), childPacker.GetSize());
packer_.AppendAlignment();
}
packer_.AppendAlignment();
SetLength(packer_.GetResource(), packer_.GetSize());
}
void CVersionUpdater::CStringTable::Parse(const BYTE* data_)
{
Reset();
CResourceParser parser(data_);
parser.Word();
parser.Word();
enumWType wType = (enumWType)parser.Word();ASSERT(wType == WTYPE_TEXT);
int iLanguage, iCodePage;
swscanf((WCHAR*)parser.Move(8*sizeof(WCHAR)), L"%04x%04x", &iLanguage, &iCodePage);
this->Language = iLanguage;
this->CodePage = iCodePage;
parser.Alignment();
PPCString values[] =
{
&this->Comments,
&this->CompanyName,
&this->FileDescription,
&this->FileVersion,
&this->InternalName,
&this->LegalCopyright,
&this->LegalTrademarks,
&this->OriginalFilename,
&this->PrivateBuild,
&this->ProductName,
&this->ProductVersion,
&this->SpecialBuild
};
long structLength = GetLength(data_);
long parsedLength = parser.GetParsedSize();
while(parsedLength < structLength)
{
CStringTable_ParseChild(data_ + parsedLength, values);
parsedLength += GetLength(data_ + parsedLength);
if(parsedLength % 4 != 0) parsedLength += 4 - (parsedLength % 4);
}
}
///////////////////////////////////////////////////////////////////////////
CVersionUpdater::CStringFileInfo::~CStringFileInfo() { Reset(); }
void CVersionUpdater::CStringFileInfo::Reset()
{
for(int i=0; i<=this->Children.GetUpperBound(); ++i)
{
delete this->Children.GetAt(i);
}
this->Children.RemoveAll();
}
void CVersionUpdater::CStringFileInfo::Pack(CResourcePacker& packer_) const
{
packer_.Reset();
packer_.AppendWord(0);
packer_.AppendWord(0);
packer_.AppendWord(WTYPE_TEXT);
packer_.AppendWString(SZKEY_STRINGFILEINFO);
packer_.AppendAlignment();
for(int i=0; i<=this->Children.GetUpperBound(); ++i)
{
CStringTable* st = this->Children.GetAt(i);
if(!st) continue;
CResourcePacker childPacker;
st->Pack(childPacker);
packer_.Append(childPacker.GetResource(), childPacker.GetSize());
packer_.AppendAlignment();
}
packer_.AppendAlignment();
SetLength(packer_.GetResource(), packer_.GetSize());
}
void CVersionUpdater::CStringFileInfo::Parse(const BYTE* data_)
{
Reset();
CResourceParser parser(data_);
parser.Word();
parser.Word();
enumWType wType = (enumWType)parser.Word();ASSERT(wType == WTYPE_TEXT);
parser.Move(sizeof(WCHAR)*(wcslen(SZKEY_STRINGFILEINFO)+1));
parser.Alignment();
long structLength = GetLength(data_);
long parsedLength = parser.GetParsedSize();
while(parsedLength < structLength)
{
CStringTable* st = new CStringTable;
st->Parse(data_ + parsedLength);
this->Children.Add(st);
parsedLength += GetLength(data_ + parsedLength);
if(parsedLength % 4 != 0) parsedLength += 4 - (parsedLength % 4);
}
}
///////////////////////////////////////////////////////////////////////////
void CVersionUpdater::CVar::Pack(CResourcePacker& packer_) const
{
packer_.Reset();
packer_.AppendWord(0);
packer_.AppendWord(sizeof(structLangageAndCodePage)*(this->Value.GetCount()));
packer_.AppendWord(WTYPE_BINARY);
packer_.AppendWString(SZKEY_TRANSLATION);
packer_.AppendAlignment();
for(int i=0; i<=this->Value.GetUpperBound(); ++i)
{
const structLangageAndCodePage& v = this->Value.GetAt(i);
packer_.Append(&v, sizeof(structLangageAndCodePage));
packer_.AppendAlignment();
}
packer_.AppendAlignment();
SetLength(packer_.GetResource(), packer_.GetSize());
}
void CVersionUpdater::CVar::Parse(const BYTE* data_)
{
CResourceParser parser(data_);
parser.Word();
WORD valueLength = parser.Word();
enumWType wType = (enumWType)parser.Word();ASSERT(wType == WTYPE_BINARY);
parser.Move(sizeof(WCHAR)*(wcslen(SZKEY_TRANSLATION)+1));
parser.Alignment();
long structLength = GetLength(data_);
long parsedLength = parser.GetParsedSize();
while(parsedLength < structLength)
{
this->Value.Add(*(structLangageAndCodePage*)(data_ + parsedLength));
parsedLength += GetLength(data_ + parsedLength);
if(parsedLength % 4 != 0) parsedLength += 4 - (parsedLength % 4);
}
}
///////////////////////////////////////////////////////////////////////////
CVersionUpdater::CVarFileInfo::~CVarFileInfo() { Reset(); }
void CVersionUpdater::CVarFileInfo::Reset()
{
for(int i=0; i<=this->Children.GetUpperBound(); ++i)
{
delete this->Children.GetAt(i);
}
this->Children.RemoveAll();
}
void CVersionUpdater::CVarFileInfo::Pack(CResourcePacker& packer_) const
{
packer_.Reset();
packer_.AppendWord(0);
packer_.AppendWord(0);
packer_.AppendWord(WTYPE_TEXT);
packer_.AppendWString(SZKEY_VARFILEINFO);
packer_.AppendAlignment();
for(int i=0; i<=this->Children.GetUpperBound(); ++i)
{
CVar* v = this->Children.GetAt(i);
if(!v) continue;
CResourcePacker childPacker;
v->Pack(childPacker);
packer_.Append(childPacker.GetResource(), childPacker.GetSize());
packer_.AppendAlignment();
}
packer_.AppendAlignment();
SetLength(packer_.GetResource(), packer_.GetSize());
}
void CVersionUpdater::CVarFileInfo::Parse(const BYTE* data_)
{
Reset();
CResourceParser parser(data_);
parser.Word();
parser.Word();
enumWType wType = (enumWType)parser.Word();ASSERT(wType == WTYPE_TEXT);
parser.Move(sizeof(WCHAR)*(wcslen(SZKEY_VARFILEINFO)+1));
parser.Alignment();
long structLength = GetLength(data_);
long parsedLength = parser.GetParsedSize();
while(parsedLength < structLength)
{
CVar* v = new CVar;
v->Parse(data_ + parsedLength);
this->Children.Add(v);
parsedLength += GetLength(data_ + parsedLength);
if(parsedLength % 4 != 0) parsedLength += 4 - (parsedLength % 4);
}
}
///////////////////////////////////////////////////////////////////////////
CVersionUpdater::CVersionInfo::CVersionInfo():StringFileInfo(NULL),VarFileInfo(NULL)
{
memset(&this->FixedFileInfo, 0, sizeof(VS_FIXEDFILEINFO));
}
CVersionUpdater::CVersionInfo::~CVersionInfo() { Reset(); }
void CVersionUpdater::CVersionInfo::Reset()
{
if(this->StringFileInfo) { delete this->StringFileInfo; this->StringFileInfo = NULL; }
if(this->VarFileInfo) { delete this->VarFileInfo; this->VarFileInfo = NULL; }
}
void CVersionUpdater::CVersionInfo::Pack(CResourcePacker& packer_) const
{
packer_.Reset();
packer_.AppendWord(0);
packer_.AppendWord(sizeof(VS_FIXEDFILEINFO));
packer_.AppendWord(WTYPE_BINARY);
packer_.AppendWString(SZKEY_VS_VERSION_INFO);
packer_.AppendAlignment();
packer_.Append(&this->FixedFileInfo, sizeof(VS_FIXEDFILEINFO));
packer_.AppendAlignment();
if(this->StringFileInfo)
{
CResourcePacker childPacker;
this->StringFileInfo->Pack(childPacker);
packer_.Append(childPacker.GetResource(), childPacker.GetSize());
packer_.AppendAlignment();
}
if(this->VarFileInfo)
{
CResourcePacker childPacker;
this->VarFileInfo->Pack(childPacker);
packer_.Append(childPacker.GetResource(), childPacker.GetSize());
packer_.AppendAlignment();
}
packer_.AppendAlignment();
SetLength(packer_.GetResource(), packer_.GetSize());
}
void CVersionUpdater::CVersionInfo::Parse(const BYTE* data_)
{
Reset();
CResourceParser parser(data_);
parser.Word();
parser.Word();
enumWType wType = (enumWType)parser.Word();ASSERT(wType == WTYPE_BINARY);
parser.Move(sizeof(WCHAR)*(wcslen(SZKEY_VS_VERSION_INFO)+1));
parser.Alignment();
this->FixedFileInfo = *(VS_FIXEDFILEINFO*)parser.Move(sizeof(VS_FIXEDFILEINFO));
parser.Alignment();
const BYTE* next = parser.Move(sizeof(WORD)*3);
LPCTSTR v = (LPCTSTR)parser.Move(0);
if(_wcsnicmp(v, SZKEY_STRINGFILEINFO, wcslen(SZKEY_STRINGFILEINFO)) == 0)
{
this->StringFileInfo = new CStringFileInfo;
this->StringFileInfo->Parse(next);
parser.Move(GetLength(next) - sizeof(WORD)*3);
next = parser.Move(sizeof(WORD)*3);
v = (LPCTSTR)parser.Move(0);
}
if(_wcsnicmp(v, SZKEY_VARFILEINFO, wcslen(SZKEY_VARFILEINFO)) == 0)
{
this->VarFileInfo = new CVarFileInfo;
this->VarFileInfo->Parse(next);
}
}
///////////////////////////////////////////////////////////////////////////
CVersionUpdater::CVersionUpdater() : VersionInfo(NULL) {}
CVersionUpdater::~CVersionUpdater()
{
if(this->VersionInfo)
{
delete this->VersionInfo;
this->VersionInfo = NULL;
}
}
bool CVersionUpdater::Open(const CString& exeOrDll)
{
DWORD handle = 0;
DWORD blockBytesCount = GetFileVersionInfoSize(exeOrDll, &handle);
if(blockBytesCount == 0) return false;
BYTE* blockBytes = new BYTE[blockBytesCount];
if(!GetFileVersionInfo(exeOrDll, NULL, blockBytesCount, blockBytes))
{
delete []blockBytes;
return false;
}
CVersionInfo* versionInfo = new CVersionInfo;
versionInfo->Parse(blockBytes);
delete []blockBytes;
if(this->VersionInfo) delete this->VersionInfo;
this->VersionInfo = versionInfo;
this->ExeOrDll = exeOrDll;
return true;
}
bool CVersionUpdater::Update(WORD language_) const
{
if(!this->VersionInfo) return false;
HANDLE resource = BeginUpdateResource(this->ExeOrDll, FALSE);
if(!resource) return false;
CResourcePacker packer;
this->VersionInfo->Pack(packer);
if (!UpdateResource(resource, RT_VERSION, MAKEINTRESOURCE(VS_VERSION_INFO), language_, packer.GetResource(), packer.GetSize())) return false;
return EndUpdateResource(resource, FALSE) != FALSE;
}
使用示例:
CVersionUpdater vu;
if(vu.Open(_T("D:\\PWB\\chem2009\\Debug\\My.exe")))
{
if(vu.VersionInfo == NULL) vu.VersionInfo = new CVersionUpdater::CVersionInfo;
if(vu.VersionInfo->StringFileInfo == NULL) vu.VersionInfo->StringFileInfo = new CVersionUpdater::CStringFileInfo;
if(vu.VersionInfo->StringFileInfo->Children.GetUpperBound() < 0) vu.VersionInfo->StringFileInfo->Children.Add(new CVersionUpdater::CStringTable);
for(int i=0; i<=vu.VersionInfo->StringFileInfo->Children.GetUpperBound(); ++i)
{
CVersionUpdater::CStringTable* st = vu.VersionInfo->StringFileInfo->Children.GetAt(i);
//st->SetComments(_T(""));
st->SetCompanyName(_T("My有限公司"));
// st->SetFileDescription(_T(""));
// st->SetFileVersion(_T(""));
// st->SetInternalName(_T(""));
st->SetLegalCopyright(_T("My。保留所有权利。"));
// st->SetLegalTrademarks(_T(""));
// st->SetOriginalFilename(_T(""));
// st->SetPrivateBuild(_T(""));
// st->SetProductName(_T(""));
// st->SetProductVersion(_T(""));
// st->SetSpecialBuild(_T(""));
}
}
if(vu.Update()) cout << "OK";
else cout << "error";