如何为PDF文件标记版本迭代并使用C#读取该版本值
轻量型PDF迭代版本追踪方案
为什么文件版本/修改时间不可行?
System.Diagnostics.FileVersionInfo.GetVersionInfo(path)仅适用于PE格式文件(如EXE、DLL),PDF不属于这类文件,因此无法读取文件版本属性。- 文件修改时间易受系统操作、备份工具等因素干扰,无法精准对应迭代版本。
最优方案:读取PDF内置自定义元数据(XMP)
PDF原生支持XMP元数据扩展,可添加自定义版本字段,用轻量级.NET库即可读取,无需依赖大型PDF编辑软件。
1. 给PDF添加自定义版本属性
用免费工具即可完成:
- 打开Adobe Acrobat Reader → 右键PDF文件→属性→描述→添加自定义字段(例如命名为
IterationVersion,值设为v2.1这类版本标识) - 或使用在线免费PDF元数据编辑工具(无需安装本地软件)
2. C#读取实现
推荐两个轻量NuGet库方案:
方案一:PdfSharp
安装NuGet包:
Install-Package PdfSharp
读取代码:
using PdfSharp.Pdf; using PdfSharp.Pdf.IO; using System.IO; using System.Xml.Linq; public string GetPdfIterationVersion(string pdfPath) { using var doc = PdfReader.Open(pdfPath, PdfDocumentOpenMode.ReadOnly); var xmpBytes = doc.Extractor.GetXmpMetadata(); if (xmpBytes == null || xmpBytes.Length == 0) return "无版本信息"; var xmpDoc = XDocument.Load(new MemoryStream(xmpBytes)); // 自定义属性的命名空间,根据添加时的实际设置调整,默认可使用Adobe自定义命名空间 var customNs = XNamespace.Get("http://ns.adobe.com/xap/1.0/mm/"); var versionElement = xmpDoc.Descendants(customNs + "IterationVersion").FirstOrDefault(); return versionElement?.Value ?? "无版本信息"; }
方案二:iTextSharp.LGPLv2.Core
安装NuGet包:
Install-Package iTextSharp.LGPLv2.Core
读取代码:
using iTextSharp.text.pdf; using System.IO; using System.Xml; public string GetPdfVersionWithiText(string pdfPath) { using var reader = new PdfReader(pdfPath); var xmpBytes = reader.Metadata; if (xmpBytes == null) return "无版本信息"; var xmpXml = new XmlDocument(); xmpXml.Load(new MemoryStream(xmpBytes)); var nsMgr = new XmlNamespaceManager(xmpXml.NameTable); nsMgr.AddNamespace("custom", "http://ns.adobe.com/xap/1.0/mm/"); var versionNode = xmpXml.SelectSingleNode("//custom:IterationVersion", nsMgr); return versionNode?.InnerText ?? "无版本信息"; }
备选:NTFS自定义属性(不推荐)
如果不想修改PDF本身,可给文件添加NTFS自定义属性,但该方案跨平台性差、实现复杂度高:
using System.IO; using System.Management; public string GetNtfsCustomVersion(string filePath) { var drive = Path.GetPathRoot(filePath); var path = filePath.Replace(drive, "").Replace("\\", "/"); var fileObj = new ManagementObject($"Win32_LogicalFileSecuritySetting=\"{drive.Replace("\\", "\\\\")}{path}\""); var outParams = fileObj.InvokeMethod("GetSecurityDescriptor", null, null); var secDescriptor = (ManagementObject)outParams["Descriptor"]; var dacl = (ManagementBaseObject[])secDescriptor["DACL"]; foreach (var ace in dacl) { // 需匹配你设置的自定义属性标识,实际使用需自行调整 if (ace["AccessMask"].ToString() == "12345") { return ace["Description"].ToString(); } } return "无版本信息"; }
内容的提问来源于stack exchange,提问作者CBFT
相关产品推荐
相关产品推荐

