C# 如何阅读';扩展的';没有Office.Interop的MS Word文件标记?

C# 如何阅读';扩展的';没有Office.Interop的MS Word文件标记?,c#,file,ms-word,office-interop,file-properties,C#,File,Ms Word,Office Interop,File Properties,我有一个.docx文件,其中仅为MS Office文件指定了自定义属性。 若我试图在未安装MS office的计算机中打开同一文件,则“文件详细信息”选项卡中并没有“标记”属性 我需要阅读c#code中的标记 我试图检索标签索引为18。然后我使用了下一个代码: public class TagsReader : ITagsReader { private const int keywordsIndex = 18; public string Read(string fileP

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

若我试图在未安装MS office的计算机中打开同一文件,则“文件详细信息”选项卡中并没有“标记”属性

我需要阅读c#code中的
标记

我试图检索
标签
索引为
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的实例,这些实例占用资源并阻塞文件。我有许多处理程序同时工作,因此我无法将“左”实例与正常工作和干净的资源分开

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

我建议使用,因为开放式xml是Office的“新”标准。使用此代码可以读取标记:(注意,您需要为此使用
DocumentFormat.OpenXml.Packaging
命名空间)


使用open xml不需要在计算机上安装任何与office相关的内容,因此它非常适合在服务器上使用,或者在您的示例中,用于在未安装office的计算机上读取/编辑文档。

U可以使用warm 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,只有hardcore

Microsoft目前不建议也不支持从任何无人参与、非交互式客户端应用程序或组件(包括ASP、ASP.NET、DCOM和NT服务)自动化Microsoft Office应用程序,因为在这种环境下运行Office时,Office可能会表现出不稳定的行为和/或死锁。

如果您正在构建一个在服务器端上下文中运行的解决方案,那么您应该尝试使用安全的组件来无人值守地执行。或者,您应该尝试找到至少允许部分代码在客户端运行的替代方案。如果使用服务器端解决方案中的Office应用程序,该应用程序将缺少许多成功运行所需的功能。此外,您将面临整体解决方案稳定性方面的风险。在文章中阅读更多关于这方面的内容


作为一种解决方法,您可以使用OpenXMLSDK,有关更多信息,请参阅。或者使用为服务器端执行而设计的任何第三方组件。例如,看一看Aspose。

今天我会尽快测试您的解决方案,泰。谢谢您的提问。首先,我感到惊讶的是,我竟然选择使用OpenXMLSDK。此外,对于使用Interop正确打开的文件,我还获得了
FileFormatException
(“文件包含损坏的数据”)。我无法更改文件格式,因为它是来自客户的文档输入流。我可以使用Open XML来处理在MS Word中创建并保存为.docx文件的文件吗?Open XML仅用于docx文件,将doc转换为docx(afaik)的唯一方法是打开它并用Word保存它:/如果您处理的是旧文档,那么恐怕您唯一的解决方案就是互操作。我对doc没有问题。另外,我测试了您的和@AlexeyTrofimuk解决方案,效果很好,非常感谢。OpenXml是一个非常大的库,我不想为一个不典型的操作添加这个引用,对我来说,手动解析是更好的方法。下一次我将使用OpenXml来完成类似的任务,因为它真的很有用@VadimMartynov是的,你可以用sdk做几乎所有的事情。但是,如果你只需要查看tagsTY to all的答案,它确实是相当大的。甚至有必要获得该部分(我不确定)吗?var tags=package.PackageProperties.Keywords如何;
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");