如何用C#获取文件资源的语言ID与字符集ID(数值形式)
获取文件资源的数值型语言ID和字符集ID(C#实现)
你当前使用FileVersionInfo.Language只能得到字符串形式的语言描述(如“English (USA)”),若要获取数值形式的语言ID和字符集ID,需要直接读取PE文件的VarFileInfo块——该块专门存储文件的语言与字符集映射信息,其中的Translation表以成对的16位值记录数据:第一个值为语言ID,第二个为字符集ID。
实现方案
通过P/Invoke调用Windows原生API GetFileVersionInfo 和 VerQueryValue,直接解析版本资源中的Translation数据,代码如下:
using System; using System.Runtime.InteropServices; public static class FileLanguageHelper { [StructLayout(LayoutKind.Sequential)] private struct VS_FIXEDFILEINFO { public uint dwSignature; public uint dwStrucVersion; public uint dwFileVersionMS; public uint dwFileVersionLS; public uint dwProductVersionMS; public uint dwProductVersionLS; public uint dwFileFlagsMask; public uint dwFileFlags; public uint dwFileOS; public uint dwFileType; public uint dwFileSubtype; public uint dwFileDateMS; public uint dwFileDateLS; } [DllImport("version.dll", CharSet = CharSet.Unicode, SetLastError = true)] private static extern bool GetFileVersionInfo(string lptstrFilename, uint dwHandle, uint dwLen, IntPtr lpData); [DllImport("version.dll", CharSet = CharSet.Unicode, SetLastError = true)] private static extern uint GetFileVersionInfoSize(string lptstrFilename, out uint lpdwHandle); [DllImport("version.dll", CharSet = CharSet.Unicode, SetLastError = true)] private static extern bool VerQueryValue(IntPtr pBlock, string lpSubBlock, out IntPtr lplpBuffer, out uint puLen); public static (ushort LanguageId, ushort CharsetId)? GetFileLanguageAndCharset(string filePath) { uint handle = 0; uint infoSize = GetFileVersionInfoSize(filePath, out handle); if (infoSize == 0) return null; IntPtr infoBuffer = Marshal.AllocHGlobal((int)infoSize); try { if (!GetFileVersionInfo(filePath, handle, infoSize, infoBuffer)) return null; if (VerQueryValue(infoBuffer, @"\VarFileInfo\Translation", out IntPtr translationPtr, out uint translationLen)) { // Translation数组每个元素是两个ushort:语言ID + 字符集ID int count = (int)(translationLen / 4); // 每个条目占4字节(2个ushort) if (count > 0) { ushort languageId = Marshal.ReadUInt16(translationPtr); ushort charsetId = Marshal.ReadUInt16(translationPtr + 2); return (languageId, charsetId); } } return null; } finally { Marshal.FreeHGlobal(infoBuffer); } } }
使用示例
var result = FileLanguageHelper.GetFileLanguageAndCharset(@"C:\example.exe"); if (result.HasValue) { Console.WriteLine($"语言ID: 0x{result.Value.LanguageId:X4}"); Console.WriteLine($"字符集ID: 0x{result.Value.CharsetId:X4}"); } else { Console.WriteLine("无法获取文件语言和字符集信息"); }
关键说明
\VarFileInfo\Translation是版本资源中存储语言与字符集映射的固定路径- 每个Translation条目占4字节:前2字节为语言ID(如0x0409对应英语(美国)),后2字节为字符集ID(如0x04B0对应UTF-8)
- 若文件包含多语言资源,
translationLen会对应多个条目,示例中仅返回第一个条目,可根据需求遍历所有条目
内容的提问来源于stack exchange,提问作者Sem
相关产品推荐
相关产品推荐

