You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 05:53:17