同一Win32程序在两台机器上VERSIONINFO信息不一致的问题
我用Embarcadero Delphi 10.2开发了一个Win32平台的Windows Service程序,通过VersionInfo.rc资源文件嵌入了版本信息。程序存在共享驱动器上,确认是同一文件,但两台机器解析出的版本信息完全不同:
- 开发机(Windows 7 Enterprise x64):资源管理器和PowerShell都能正确显示版本
1.0.0.217及Build 217注释 - 部署虚拟机(Windows Server 2012 R2):显示版本为
1.0.0.0,所有自定义字段(如CompanyName、Comments)都为空
两台机器的PowerShell输出分别如下:
开发机(Windows 7)输出
PS D:\> (get-item \\S030A2787\EdiProcessor\Build\EDIProcessor.Service.exe).VersionInfo | Select-Object * Comments : Build 217 CompanyName : ******** FileBuildPart : 0 FileDescription : EDIProcessor.exe FileMajorPart : 1 FileMinorPart : 0 FileName : \\S030A2787\EdiProcessor\Build\EDIProcessor.Service.exe FilePrivatePart : 217 FileVersion : 1.0.0.217 InternalName : EDIProcessor IsDebug : False IsPatched : False IsPrivateBuild : False IsPreRelease : False IsSpecialBuild : False Language : Englisch (USA) LegalCopyright : LegalTrademarks : OriginalFilename : PrivateBuild : ProductBuildPart : 0 ProductMajorPart : 1 ProductMinorPart : 0 ProductName : EDIProcessor ProductPrivatePart : 217 ProductVersion : 1.0.0.217 SpecialBuild : PS D:\> $PSVersionTable Name Value ---- ----- PSVersion 4.0 WSManStackVersion 3.0 SerializationVersion 1.1.0.1 CLRVersion 4.0.30319.42000 BuildVersion 6.3.9600.16406 PSCompatibleVersions {1.0, 2.0, 3.0, 4.0} PSRemotingProtocolVersion 2.2
部署机(Windows Server 2012 R2)输出
PS Y:\> (get-item \\S030A2787\EDIProcessor\build\EDIProcessor.Service.exe).VersionInfo | Select-Object * Comments : CompanyName : FileBuildPart : 0 FileDescription : EDIProcessor.Service FileMajorPart : 1 FileMinorPart : 0 FileName : \\S030A2787\EDIProcessor\build\EDIProcessor.Service.exe FilePrivatePart : 0 FileVersion : 1.0.0.0 InternalName : IsDebug : False IsPatched : False IsPrivateBuild : False IsPreRelease : False IsSpecialBuild : False Language : English (United States) LegalCopyright : LegalTrademarks : OriginalFilename : PrivateBuild : ProductBuildPart : 0 ProductMajorPart : 1 ProductMinorPart : 0 ProductName : EDIProcessor.Service ProductPrivatePart : 0 ProductVersion : 1.0.0.0 SpecialBuild : PS Y:\> $PSVersionTable Name Value ---- ----- PSVersion 4.0 WSManStackVersion 3.0 SerializationVersion 1.1.0.1 CLRVersion 4.0.30319.42000 BuildVersion 6.3.9600.18773 PSCompatibleVersions {1.0, 2.0, 3.0, 4.0} PSRemotingProtocolVersion 2.2
我的VersionInfo.rc资源文件内容
#define VERSION 1,0,0,217 #define VERSION_STR "1.0.0.217\0" #define COMMENT "Build 217\0" 1 VERSIONINFO FILEVERSION VERSION PRODUCTVERSION VERSION FILEFLAGSMASK 0x0 FILEFLAGS 0x0 FILEOS 0x4 FILETYPE 0x1 FILESUBTYPE 0x0 BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "040904E4" BEGIN VALUE "Comments", COMMENT VALUE "ProductName", "EDIProcessor\0" VALUE "CompanyName", "********\0" VALUE "InternalName", "EDIProcessor\0" VALUE "FileDescription", "EDIProcessor.exe\0" VALUE "FileVersion", VERSION_STR VALUE "ProductVersion", VERSION_STR END END BLOCK "VarFileInfo" BEGIN VALUE "Translation", 0x0409L, 1252 VALUE "Translation", 0x0407L, 1252 END END
问题原因分析
结合场景和资源文件内容,主要问题出在两个核心点:
FILETYPE类型不匹配
Windows Service是特殊的可执行文件类型,你的资源文件里FILETYPE设置为0x1(对应VFT_APP,普通桌面应用),但正确类型应为0x8(对应VFT_SERVICE,服务程序)。Windows 7对这个错误兼容性较强,能忽略类型不匹配读取资源;但Windows Server 2012 R2的版本信息解析更严格,会因类型不匹配而读取默认的空白版本信息。字符串终止符冗余
你在资源字符串末尾手动添加了\0,但Delphi的资源编译器会自动为字符串资源添加终止符,双重终止符可能导致部分系统解析异常,出现字段为空的情况。SMB缓存干扰(次要可能)
Windows Server 2012 R2的SMB客户端可能缓存了文件元数据(包括版本信息),导致你看到的是旧版本的缓存内容,而非最新文件的资源信息。
解决方案
按照以下步骤操作,即可解决问题:
1. 修改资源文件的类型设置和字符串格式
更新后的VersionInfo.rc内容如下:
#define VERSION 1,0,0,217 #define VERSION_STR "1.0.0.217" #define COMMENT "Build 217" 1 VERSIONINFO FILEVERSION VERSION PRODUCTVERSION VERSION FILEFLAGSMASK 0x0 FILEFLAGS 0x0 FILEOS 0x4 FILETYPE 0x8 // 改为服务类型VFT_SERVICE FILESUBTYPE 0x1 // 添加Win32服务子类型VFT2_SERVICE_WIN32 BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "040904E4" BEGIN VALUE "Comments", COMMENT VALUE "ProductName", "EDIProcessor" VALUE "CompanyName", "********" VALUE "InternalName", "EDIProcessor" VALUE "FileDescription", "EDIProcessor.Service" // 匹配程序实际文件名 VALUE "FileVersion", VERSION_STR VALUE "ProductVersion", VERSION_STR END END BLOCK "VarFileInfo" BEGIN VALUE "Translation", 0x0409L, 1252 // 优先放置英语(美国)的翻译条目 VALUE "Translation", 0x0407L, 1252 END END
- 调整
FILETYPE和FILESUBTYPE为服务程序对应的值 - 移除所有字符串末尾的
\0,让资源编译器自动处理终止符 - 同步
FileDescription为程序实际文件名,避免解析混淆
2. 重新编译并替换共享文件
在Delphi开发环境中重新编译程序,确保资源编译器正确嵌入修改后的版本信息,然后替换共享驱动器上的旧文件。
3. 验证文件一致性(可选但推荐)
在两台机器上运行以下命令计算文件哈希,确认是同一文件:
Get-FileHash \\S030A2787\EdiProcessor\Build\EDIProcessor.Service.exe -Algorithm SHA256
若哈希值一致,说明文件未被替换。
4. 清除部署机的SMB缓存
如果修改后部署机仍显示旧信息,执行以下操作清除缓存:
- 断开共享连接:
net use Y: /delete(Y为你的共享盘符) - 重新连接共享:
net use Y: \\S030A2787\EdiProcessor - 或直接重启部署机,彻底清除系统缓存
测试验证
完成上述步骤后,在两台机器上重新查看版本信息:
- 资源管理器中右键程序→属性→详细信息
- PowerShell中重新运行
(get-item <文件路径>).VersionInfo | Select-Object *
两台机器应显示完全一致的版本信息,包括1.0.0.217的版本号和Build 217的注释。
内容的提问来源于stack exchange,提问作者Marian Aldenhövel

