如何在没有 Office.Interop 的情况下读取 'Extended' MS Word 文件标签?

How to read 'Extended' MS Word file tags without Office.Interop?

我有 .docx 文件,其自定义属性仅为 MS Office 文件指定。

如果我试图在未安装 MS Office 的计算机中打开相同的文件,则文件详细信息选项卡中没有标签 属性。

我需要在我的 C# 代码中阅读 Tags

我尝试了 this solution 并将 Tags 索引检索为 18。然后我使用下一个代码:

public class TagsReader : ITagsReader
{
    private const int keywordsIndex = 18;

    public string Read(string filePath)
    {
        var fullPath = Path.GetFullPath(filePath);

        var directoryName = Path.GetDirectoryName(fullPath);
        Folder dir = GetShell32Folder(directoryName);
        var fileName = Path.GetFileName(fullPath);

        FolderItem item = dir.ParseName(fileName);
        return dir.GetDetailsOf(item, keywordsIndex);
    }

    private Folder GetShell32Folder(string folderPath)
    {
        var shellAppType = Type.GetTypeFromProgID("Shell.Application");
        var shell = Activator.CreateInstance(shellAppType);
        return (Folder)shellAppType.InvokeMember("NameSpace",
        BindingFlags.InvokeMethod, null, shell, new object[] { folderPath });
    }
}

但它不适用于未安装 MS Office 的计算机。它仅适用于 .doc 个文件,但不适用于 .docx。现在我使用了基于 Interop 的解决方案,它不稳定,资源密集,需要在服务器上安装 MS Office:

public class WordTagsReader : ITagsReader
{
    private readonly string[] availableFileExtensions = { ".docx" };
    public string Read(string filePath)
    {
        var fileExtension = Path.GetExtension(filePath);
        if (!availableFileExtensions.Contains(fileExtension))
            return null;

        dynamic application = null;
        dynamic document = null;
        var tags = string.Empty;
        try
        {
            var typeWord = Type.GetTypeFromProgID("Word.Application");
            application = Activator.CreateInstance(typeWord);
            application.Visible = false;
            application.DisplayAlerts = false;
            var fullFilePath = Path.GetFullPath(filePath);
            document = application.Documents.Open(fullFilePath);
            tags = document.BuiltInDocumentProperties["Keywords"].Value;
        }
        finally
        {
            if (document != null)
            {
                document.Close();
                document = null;
            }
            if (application != null)
            {
                application.Quit();
                application = null;
            }
        }

        return tags;
    }
}

此代码可能会不时崩溃并留下 运行 个 MS Word 实例,它占用资源和块文件。我有许多处理程序同时工作,然后我无法将 "left" 个实例与正常工作和清洁的资源分开。

这就是搜索替代解决方案的原因。有没有一种方法可以在不使用 Office.Interop 的情况下读取 Tags 等特定(自定义)属性?

我建议使用Open Xml Sdk,打开xml是办公的'new'标准。使用此代码可以读取标签:(请注意,您需要为此使用 DocumentFormat.OpenXml.Packaging 命名空间)

string tags = "";
using(var doc = WordProcessingDocument.Open("filename",false)
    tags = doc.PackageProperties.KeyWords;

使用 open xml 不需要在机器上安装任何与 office 相关的东西,因此它非常适合在服务器上使用它,或者在您的示例中用于 reading/editing 在没有 office 的机器上的文档已安装。

你可以用温暖的lamp.docx格式阅读。像这样:

using System.IO.Packaging;

var package = Package.Open(ms, FileMode.Open, FileAccess.ReadWrite);
var corePart = package.GetPart(new Uri("/docProps/core.xml", UriKind.Relative))
XDocument settings;
using (TextReader tr = new StreamReader(settingsPart.GetStream()))
    settings = XDocument.Load(tr);

XNamespace cp = "http://schemas.openxmlformats.org/package/2006/metadata/core-properties"
var tags = settings.Root.Element(cp + "keywords");

无需使用额外的库或 sdk。只System.IO,只硬核!

Microsoft 目前不推荐也不支持从任何无人值守的非交互式客户端应用程序或组件(包括 ASP、ASP.NET 自动化 Microsoft Office 应用程序、DCOM 和 NT 服务),因为当 Office 在此环境中为 运行 时,Office 可能表现出不稳定的行为 and/or 死锁。

如果您要在服务器端上下文中构建 运行 的解决方案,您应该尝试使用已针对无人值守执行安全设置的组件。或者,您应该尝试找到至少允许 运行 客户端部分代码的替代方案。如果您从服务器端解决方案使用 Office 应用程序,该应用程序将缺少许多 运行 成功所必需的功能。此外,您将承担整体解决方案稳定性的风险。在 Considerations for server-side Automation of Office 文章中阅读更多相关信息。

作为解决方法,您可以考虑使用 Open XML SDK,有关详细信息,请参阅 Welcome to the Open XML SDK 2.5 for Office。或者使用为服务器端执行而设计的任何第三方组件。例如,看看 Aspose.