rc 资源文件中包含多个语言的版本信息
2025-04-10 21:44:29

查看一个 EXE/DLL 文件版本时,系统会根据当前系统设置的语言显示不同的版本信息。
版本信息是在 RC 文件中名为 StringFileInfo 块中保存的。


StringFileInfo可以写多个,就像这两个帖子中描述的那样的写法:


就像这两个帖子中描述的那样,虽然语法上可以这样写,编译不会报错,但是在系统中查看时始终只有第一个块生效。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
VS_VERSION_INFO VERSIONINFO
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "080404b0"
BEGIN
VALUE "FileDescription", "aaaaa 应用程序"
VALUE "FileVersion", "1, 0, 0, 1"
VALUE "InternalName", "aaaaa"
VALUE "LegalCopyright", "Copyright (C) 2025"
VALUE "OriginalFilename", "aaaaa.exe"
VALUE "ProductName", "aaaaa 应用程序"
VALUE "ProductVersion", "1, 0, 0, 1"
END
BLOCK "040904B0"
BEGIN
VALUE "FileDescription", "aaaaa application"
VALUE "FileVersion", "1, 0, 0, 1"
VALUE "InternalName", "aaaaa"
VALUE "LegalCopyright", "Copyright (C) 2025"
VALUE "OriginalFilename", "aaaaa.exe"
VALUE "ProductName", "aaaaa application"
VALUE "ProductVersion", "1, 0, 0, 1"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x804, 1200, 0x0409, 0x04B0
END
END

通过第三方工具来查看资源信息,发现只包含第一个信息块:

而且值得注意的是这个信息块被标记为了1033,对应英语(美国)


正确方式是用 LANGUAGE 语句来定义接下来资源属于哪种语言,Windows中显示的版本信息就是根据这个来确定的,如果没有匹配的语言,则回退到第一个资源块,所以通常推荐将英文作为第一个信息块,这样无论系统设置的什么语言都能正常显示,不至于乱码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
VS_VERSION_INFO VERSIONINFO
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904B0"
BEGIN
VALUE "CompanyName", "XXX Technology Co., Ltd.\0"
END
END

BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x0409, 0x04B0
END
END

LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED
VS_VERSION_INFO VERSIONINFO
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "080404B0"
BEGIN
VALUE "CompanyName", "XXX有限公司\0"
END
END

BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x0804, 0x04B0
END
END


StringFileInfo块中指定的语言又有什么用呢?故意写一个错误的语言ID

1
2
3
4
5
6
7
8
9
10
11
12
13
BLOCK "StringFileInfo"
BEGIN
BLOCK "000004b0"
BEGIN
VALUE "FileDescription", "aaaaa 1111111111"
VALUE "FileVersion", "1, 0, 0, 1"
VALUE "InternalName", "aaaaa"
VALUE "LegalCopyright", "Copyright (C) 2025"
VALUE "OriginalFilename", "aaaaa.exe"
VALUE "ProductName", "aaaaa 1111111"
VALUE "ProductVersion", "1, 0, 0, 1"
END
END

结果是什么都不会显示

如果指定了08040000(中文)呢?

1
2
3
4
5
6
7
8
9
10
11
12
BEGIN
BLOCK "08040000"
BEGIN
VALUE "FileDescription", "aaaaa 1111111111"
VALUE "FileVersion", "1, 0, 0, 1"
VALUE "InternalName", "aaaaa"
VALUE "LegalCopyright", "Copyright (C) 2025"
VALUE "OriginalFilename", "aaaaa.exe"
VALUE "ProductName", "aaaaa 1111111"
VALUE "ProductVersion", "1, 0, 0, 1"
END
END


还是不显示。
再改为美国英语

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "04090000"
BEGIN
VALUE "FileDescription", "aaaaa 1111111111"
VALUE "FileVersion", "1, 0, 0, 1"
VALUE "InternalName", "aaaaa"
VALUE "LegalCopyright", "Copyright (C) 2025"
VALUE "OriginalFilename", "aaaaa.exe"
VALUE "ProductName", "aaaaa 1111111"
VALUE "ProductVersion", "1, 0, 0, 1"
END
END
END


显示正常了,至此可以得到一个结论,要让对应语言的版本信息正常显示,需要:

  1. LANG语句要指定对应的语言。
  2. StringFileInfo块中的langID也要匹配。


至于VarFileInfo块下的Translation,只是控制LANGUAGE项的显示内容

关于 RC 文件的编码

如果资源文件中存在非英文字符就需要注意文件的编码问题,在早期的VS版本比如VS2008中,默认用本机编码,比如GB2312,如果要加入其他语言就要手动修改文件编码为UTF-16 LE BOM或者UTF-8
如果指定为UTF-8,则还需要用#pragma code_page(65001)指令告诉资源编译器文件编码为UTF-8
但是在VS2008中,指定UTF-8后,资源编辑器会强制在LANG下面加上对应语言的#pragma code_page

1
2
3
4
#ifdef _WIN32
LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED
#pragma code_page(936)
#endif //_WIN32

所以,在低版本VS中,建议将资源文件编码改为UTF-16 LE BOM,这样资源文件才不会强制添加#pragma code_page


新版本VS中支持UTF-8 BOM,不过在资源编辑器中编辑后,文件还是会被改为UTF-8编码并在文件首行添加#pragma code_page(65001)指令。

总结

  • LANG语句决定接下来定义的资源属于哪种语言,Windows会根据系统的语言设置匹配对应的块显示。
  • BLOCK中的语言ID要正确,否则不会显示当前块的信息。
  • Translation只是决定语言一栏中显示的内容,不影响Windows决定显示哪个块信息。
  • 在低版本的VS中,建议将资源文件编码改为UTF-16 LE BOM
  • 在新版本的VS中,可以将资源文件编码改为UTF-8 BOM,不过在资源编辑器中编辑后,文件会被强制改为UTF-8并在文件首行添加#pragma code_page(65001)指令。


如果要兼容新老版本的所有VS,还是建议将编码改为UTF-16 LE BOM

相关阅读

LANGUAGE 语句
StringFileInfo BLOCK 语句
VarFileInfo BLOCK 語句
VERSIONINFO 资源
[MS-LCID]: Windows Language Code Identifier (LCID) Reference

上一页
2025-04-10 21:44:29