首页 > 编程语言 >使用C#获取文件详情

使用C#获取文件详情

时间:2024-11-21 18:40:08浏览次数:1  
标签:string C# VALUE 获取 int version buffer 详情 out

image
有对应的需求,需要获取文件的详细信息内容。该页面信息大部分来源于文件的版本信息,使用FileInfo类并不能获取到。

VERSIONINFO 资源 - Win32 apps | Microsoft Learn

信息格式:


1 VERSIONINFO
FILEVERSION 1,0,0,323
PRODUCTVERSION 1,0,0,0
FILEOS 0x4
FILETYPE 0x1
{
BLOCK "StringFileInfo"
{
	BLOCK "000004B0"
	{
		VALUE "Comments", "这是一个示例库,由张三编写。"
		VALUE "CompanyName", "webre"
		VALUE "FileDescription", "webre"
		VALUE "FileVersion", "1.0.0.323"
		VALUE "InternalName", "webre.dll"
		VALUE "LegalCopyright", "版权所有 \xA9 2024 张三"
		VALUE "LegalTrademarks", ""
		VALUE "OriginalFilename", "webre.dll"
		VALUE "ProductName", "webre"
		VALUE "ProductVersion", "1.0.0"
		VALUE "Assembly Version", "1.0.0.323"
		VALUE "Test", "Test"//自定义属性
	}
}

BLOCK "VarFileInfo"
{
	VALUE "Translation", 0x0000 0x04B0  
}
}

为了获取versioninfo信息,需要使用version.dll内的api进行指定段内的信息获取。参考如下:

GetFileVersionInfoA function (winver.h) - Win32 apps | Microsoft Learn

GetFileVersionInfoSizeA function (winver.h) - Win32 apps | Microsoft Learn

VerQueryValueW function (winver.h) - Win32 apps | Microsoft Learn

调用代码如下:

//需要引入win32api
[DllImport("version.dll", CharSet = CharSet.Unicode)]
private static extern bool GetFileVersionInfo(string fileName, int handle, int len, byte[] data);

[DllImport("version.dll", CharSet = CharSet.Unicode)]
private static extern int GetFileVersionInfoSize(string fileName, out int handle);

[DllImport("version.dll", CharSet = CharSet.Unicode)]
private static extern bool VerQueryValue(byte[] data, string subBlock, out IntPtr buffer, out int len);

var attrs = new string[] {
"Comments","InternalName","ProductName",
"CompanyName","LegalCopyright","ProductVersion",
"FileDescription","LegalTrademarks","PrivateBuild",
"FileVersion","OriginalFilename","SpecialBuild","Test"
};

// 获取文件版本信息的大小
int handle;
int infoSize = GetFileVersionInfoSize(dllPath, out handle);
if (infoSize == 0)
{
    throw new Exception("Failed to get file version info size. Error: " + Marshal.GetLastWin32Error());
}

// 分配缓冲区
byte[] infoBuffer = new byte[infoSize];

// 获取文件版本信息
if (!GetFileVersionInfo(dllPath, 0, infoSize, infoBuffer))
{
    throw new Exception("Failed to get file version info. Error: " + Marshal.GetLastWin32Error());
}

// 获取所有语言代码
IntPtr buffer;
int len;
if (!VerQueryValue(infoBuffer, @"\VarFileInfo\Translation", out buffer, out len))
{
    throw new Exception("Failed to get language codes. Error: " + Marshal.GetLastWin32Error());
}

// 解析语言代码
List<string> languageCodes = new List<string>();
for (int i = 0; i < len / 4; i++)
{
    int langCode = Marshal.ReadInt16(buffer, i * 4);
    int subLangCode = Marshal.ReadInt16(buffer, i * 4 + 2);
    string languageCode = $"{langCode:X4}{subLangCode:X4}";//win下小端存储
    languageCodes.Add(languageCode);
}

// 输出所有语言代码
Console.WriteLine("Available Language Codes:");
foreach (string languageCode in languageCodes)
{
    Console.WriteLine(languageCode);
}

// 选择第一个语言代码
string selectedLanguageCode = languageCodes.Count > 0 ? languageCodes[0] : "040904B0";//默认为英文

foreach (var attr in attrs)
{
    if (!VerQueryValue(infoBuffer, $@"\StringFileInfo\{selectedLanguageCode}\{attr}", out buffer, out len))
    {
        Console.WriteLine($"Failed to get {attr}. Error: " + Marshal.GetLastWin32Error());
    }
    else
    {
        string value = Marshal.PtrToStringUni(buffer);
        Console.WriteLine($"{attr}: " + value);
    }
}

在调用VerQueryValue后,通过buffer获取到内存地址,观察一下内存数据。

image

version信息映射到一段连续内存中存储。

另外还有更简单的方式,通过封装好的FileVersionInfo类进行信息获取,通过各种属性即可获取版本信息。不过,自定义的属性就获取不到了。

FileVersionInfo fileVersionInfo = FileVersionInfo.GetVersionInfo(dllPath);

FileVersionInfo win平台的实现,内部也是调用了version.dll内的相关api,不过调用的都是Ex方法,并对codepage做了处理。

标签:string,C#,VALUE,获取,int,version,buffer,详情,out
From: https://www.cnblogs.com/GISyunqi/p/18561322

相关文章

  • 第三十四节:基于ShardingCore框架读写分离实操
    一. 简介       二.实操            !作       者:Yaopengfei(姚鹏飞)博客地址:http://www.cnblogs.com/yaopengfei/声     明1:如有错误,欢迎讨论,请勿谩骂^_^。声     明2:原创博客请在转载时保留......
  • ChatGPT 开启「眼睛」,实时摄像头对话来了;昆仑万维推出实时语音助手 Skyo丨 RTE 开发者
       开发者朋友们大家好: 这里是「RTE开发者日报」,每天和大家一起看新闻、聊八卦。我们的社区编辑团队会整理分享RTE(Real-TimeEngagement)领域内「有话题的新闻」、「有态度的观点」、「有意思的数据」、「有思考的文章」、「有看点的会议」,但内容仅代表编......
  • TeeChart学习汇总
    如果TeeChart的bpl文件被删除,可以通过repairtDelphi10.3来自动修复因为第三方控件(FastReport,UniGUI)依赖于原生TeeChart的bpl1]设计时的数据得以保存的方法拖一个TChart,双击它去掉3D,勾选Smooth 2]修改Title标题 ......
  • 使用再生龙CloneZilla进行Linux系统的镜像完全封装和还原
    写文章  使用再生龙CloneZilla进行Linux系统的镜像完全封装和还原巴布改不掉晚睡的咸鱼​关注 71人赞同了该文章CloneZilla可以将Linux完整移植到另一台机器中,保证数据,分区,挂载,启动项。。所有的一切完全一致注意:进行还原的机器需要......
  • Linux基础——yum downgrade和yum localinstall降级安装
    一、问题描述需求:租户需要从openssl-1.1.1t-11降级安装openssl-1.1.1f-36,安装包相关依赖问题;报错:rpm安装提示依赖问题 报错:yumlocalinstall本地rpm包无法安装; 二、解决办法1、方法一:yumdowngrade降级#通过本地rpm包或在线yum源安装,加上参数“--allowerasing”允许......
  • 【基于PyTorch的简单多层感知机(MLP)神经网络(深度学习经典代码实现)】
    importtorchfromtorchvisionimporttransformsfromtorchvisionimportdatasetsfromtorch.utils.dataimportDataLoaderimporttorch.nn.functionalasFimporttorch.optimasoptim#准备数据集batch_size=64transform=transforms.Compose([transforms.......
  • C语言 蓝桥杯某例题解决方案(查找完数)
    蓝桥杯原题: 一个数如果恰好等于它的因子之和,这个数就称为“完数”。例如6=1+2+3.编程找出1000以内的所有完数。这个题没有很大的难点,与我们上一个解决的问题“质因数分解”不同,它不需要判断因数是否是质数,因此我们的工作量会小很多。现在我们的想法还是类似,首先找到......
  • 【Flinkcdc问题解决】java.lang.NoClassDefFoundError: org/apache/flink/shaded/guav
    1.环境介绍Flink1.17+Flinkcdc2.2.12.问题描述使用Flink1.17和Flinkcdc2.2.1环境进行数据加工,但是报以上错误,原因是版本不匹配,flinkcdc2.2.1用的是guava18,但是flink1.17用的是guava30,导致冲突。3.问题解决添加flink-sql-connector-mysql-cdc依赖<dependen......
  • 使用ENSP实现DHCP+动态路由
    一、项目拓扑   二、项目实现 (1)路由器AR1配置进入系统试图sys将路由器命名为R1sysnameR1关闭信息中心undoinfo-centerenable进入g0/0/0接口intg0/0/0将g0/0/0接口IP地址配置为12.12.12.1/30ipaddress12.12.12.130退出此视图quit创建valn......
  • Greenfield vs Brownfield | QC vs QA
    注:几篇关于“绿地/棕地”的文章合辑,机翻,未校。GreenfieldvsBrownfield绿地vs棕地GreenfieldvsBrownfield:UnderstandingtheSoftwareDevelopmentDifferences绿地与棕地:了解软件开发的差异Softwarehasbecomeoneofthestrongest,mostdynamicindustr......