【发布时间】:2018-12-24 18:24:17
【问题描述】:
我正在尝试以编程方式更改 DLL 文件的 VersionInfo 属性。我使用this article 作为参考。
#include <iostream>
#include <stdio.h>
#include <windows.h>
int main(int argc, char** argv) {
LPCTSTR lpszFile = "E:\\_test\\rand_test\\test.dll";
DWORD dwHandle,
dwSize;
struct {
WORD wLanguage;
WORD wCodePage;
} *lpTranslate;
// determine the size of the resource information
dwSize = GetFileVersionInfoSize(lpszFile, &dwHandle);
if (0 < dwSize)
{
unsigned char* lpBuffer = (unsigned char*) malloc(dwSize);
// Get whole VersionInfo resource/structure
GetFileVersionInfo(lpszFile, 0, dwSize, lpBuffer);
char strSubBlock[37]; // fits "\\StringFileInfo\\xxxxxxxx\\CompanyName\0"
LPTSTR pValueBuffer;
HANDLE hResource = BeginUpdateResource(lpszFile, FALSE);
if (NULL != hResource)
{
UINT uTemp;
// get the language information
if (!VerQueryValue(lpBuffer, "\\VarFileInfo\\Translation", (LPVOID *) &lpTranslate, &uTemp) != FALSE)
{
printf("Error 1\n");
return 1;
}
sprintf(strSubBlock, "\\StringFileInfo\\%04x%04x\\CompanyName", lpTranslate->wLanguage, lpTranslate->wCodePage);
if (!VerQueryValue(lpBuffer, (LPTSTR) ((LPCTSTR) strSubBlock), (LPVOID *) &pValueBuffer, &uTemp)) {
printf("Error 2\n");
return 1;
}
// PROBLEM!!!
// (pValueBuffer-lpBuffer) is 0x438 (longer than the Versioninfo resource!) but should be 0xB8
// so, pValueBuffer does not point to the actual company name.
ZeroMemory(pValueBuffer, strlen(pValueBuffer) * sizeof(TCHAR));
strcpy(pValueBuffer, "My Company, Inc."); // String may only become smaller or equal, never bigger than strlen(pValueBuffer)
if (UpdateResource(hResource,
RT_VERSION,
MAKEINTRESOURCE(VS_VERSION_INFO),
lpTranslate->wLanguage, // or 0
lpBuffer,
dwSize) != FALSE)
{
EndUpdateResource(hResource, FALSE);
}
}
free(lpBuffer);
}
return 0;
}
我想我已经理解了代码所做的一切。计划是读取 Versioninfo 块,然后找到例如位置。 CompanyName 使用VerQueryValue,然后更改数据,然后使用 UpdateResource 将其写回。
但是有一个问题:VerQueryValue应该输出CompanyName字符串所在的位置。但相反,它提供了一个指针位置,距离几百字节,因此它指向 VersionInfo 结构之外的某个位置。
我做错了什么,我该如何让它发挥作用?
(另外,有没有人知道是否有更优雅的方式来完成这项任务,甚至可以消除字符串必须小于或等于原始字符串的限制?)
【问题讨论】:
-
您当然可以解构PE文件,并使用新版本资源对其进行重构。 PE 文件格式已记录在案,并且有许多带有代码的开放源程序显示如何使用它们。
-
我测试了你的代码,
VerQueryValue给出了正确的公司名称。所以你的test.dll可能有问题。 -
你做错了。
GetFileVersionInfoSize()为您提供GetFileVersionInfo()填充的内存缓冲区的大小,而不是原始资源。这包括不在原始资源数据中的连接,尤其是在您使用 API 的 ANSI 版本时。VerQueryValue()在内存缓冲区中返回指针,而不是在原始资源中。对于您想要做的事情,您需要直接解析原始资源数据,然后分配一个全新的版本资源并应用修改。您不能为此任务使用版本控制 API。 -
@DavidHeffernan 为什么我需要解构 PE 文件? BeginUpdateResource、UpdateResource 和 EndUpdateResource API 非常可靠,所以我的“唯一”问题是修改 VersionInfo 结构,它完全独立于 PE 的其余部分。
-
@Remy Lebeau 谢谢你的提示。我会进一步研究它。我开始认为 CodeProject.com 有时是一个糟糕的参考代码来源......
标签: c winapi versioninfo