嵌入互操作类型问题

Embed Interop types issue

当然Embed interop类型特性是个好东西,但即使在简单的情况下我也无法使用它,所以请指教 这是我在未安装 powerPoint 的机器上 运行 我的项目时遇到的错误:

我的代码非常简单,我只是从 powerPoint 创建对象,创建演示文稿并在其中写一些东西。

我嵌入的库是OfficeMicrosoft.Office.Interop.PowerPoint

将构建配置转换为 x68 未能解决问题,

我正在构建 windows 应用程序并将代码放入按钮点击中,如下所示:

 private void button1_Click(object sender, EventArgs e)
 {
     var pp = new powerpoint.Application();
     var oPres=pp.Presentations;
     pp.Visible = Office.MsoTriState.msoTrue;
     powerpoint.Presentation  oPre= oPres.Add(Office.MsoTriState.msoTrue);

     powerpoint.Slides oSlides = oPre.Slides;
     powerpoint.Slide oSlide = oSlides.Add(1, powerpoint.PpSlideLayout.ppLayoutText);
     powerpoint.Shapes oShapes = oSlide.Shapes;
     powerpoint.Shape oShape = oShapes[1];
     powerpoint.TextFrame oTxtFrame = oShape.TextFrame;
     powerpoint.TextRange oTxtRange = oTxtFrame.TextRange;
     oTxtRange.Text = "All-In-One Code Framework";

     string fileName = Path.GetDirectoryName(
         Assembly.GetExecutingAssembly().Location) + "\Sample1.pptx";
     oPre.SaveAs(fileName,
         powerpoint.PpSaveAsFileType.ppSaveAsOpenXMLPresentation,
         Office.MsoTriState.msoTriStateMixed);
     oPre.Close();

     pp.Quit();
     pp = null;
 }

在顶部我添加了

 using powerpoint = Microsoft.Office.Interop.PowerPoint; 
 using Office = Microsoft.Office.Core; 
 using System.IO; 
 using System.Reflection;

注意:该程序在我安装了 Office 2013 的那一端运行良好,但此错误出现在我的客户端电脑上

有趣的是,错误消息中最重要的信息竟然隐藏得如此之深,以至于很难看到。

Class not Registered

这是你的错误。基本上,您尝试创建的对象不存在或未正确安装在您 运行 软件所在的机器上。 powerpoint确实安装了吗?

如前所述,问题是客户端计算机上没有安装 Powerpoint。

powerpoint对象是在COM类型库中实现的,在安装powerpoint时安装注册。 COM 和.NET 是完全不同的技术。要在 .NET 应用程序中使用 COM 类型,您不直接使用 COM 类型,而是使用特殊的互操作 .NET 程序集。该程序集不包含任何 PPT 功能,它只是一个包装器,充当 .NET 应用程序和 COM 类型之间的桥梁。互操作程序集会为您完成所有艰苦的工作,并定义您可以用作其他 .NET 类 的 .NET 类型(来自 COM 类型),例如 powerpoint.Application.

互操作程序集只是一个普通的 .NET 程序集。您可以将其作为其他 .NET 引用来引用(Embed Interop Types = false)。在这种情况下,您需要将互操作 DLL 与您的应用程序一起分发。如果您设置 Embed Interop Types = true,则互操作程序集将被编译并直接嵌入到您的应用程序程序集中。而且,只嵌入真正使用的类型和函数。因此使用此选项具有优化和单一装配的优势。

但是,即使嵌入,互操作信息也只是对必须安装在客户端计算机上的真实 COM 类型的包装。如果不是,您将收到错误消息。 在 https://msdn.microsoft.com/en-us/library/xwzy44e4.aspx

查看更多详细信息

您的选择是强制客户端安装 PPT 或避免Microsoft.Office.Interop.PowerPoint并使用一些您可以随应用程序分发的第三方 PPT 库。

"Embed interop types" 不是 的意思 "embed the Office program"。您收到此错误的原因很简单,那台机器上没有安装 Powerpoint。

我想 "interop types" 这个词可以用一个解释。您可以使用 COM 自动化 Office 程序,COM 是一种先于 .NET 并与 .NET 有许多相似之处的互操作技术。它还具有元数据的概念,就像 .NET 程序集一样,编译器在您添加对 .NET 程序集的引用时使用的类型信息。该元数据在 COM 中称为 "type library"。 Powerpoint 的类型库为 C:\Program Files (x86)\Microsoft Office\Office15\MSPPT.OLB for the Office 2013 version.

类型库并不完美,它们存在歧义问题,这些问题在用 C++ 编写的应用程序中无关紧要,但在 .NET 中却很重要。所以.NET 设计者决定不直接使用类型库。并指定 Tlbimp.exe utility,它将库内容转换为 .NET 程序集。 CLR 和托管语言编译器可以直接使用,而无需处理解释类型库内容的麻烦。

按照惯例,Tlbimp.exe 生成的 .NET 程序集称为 "interop library"。它与类型库是一对一匹配的。最重要的是,在这个问题的上下文中,它只包含 声明 ,它不包含可执行代码。代码保留在 COM 组件中,用非 .NET 语言编写。像 Office 程序一样,用 C++ 编写。

编译时需要互操作程序集,编译器使用它来了解 COM 组件实现了哪些类型,因此它可以正确地对您编写的代码进行类型检查,并在您出错时告诉您。它在运行时 需要,只要您使用其中一种 COM 类型,它就会由 CLR 加载。

必须将互操作程序集部署到执行程序的机器上是一种负担。至少不是因为您经常需要 "Primary Interop Assembly",这是另一个与解决 .NET 类型标识问题相关的神秘术语。我将在这里跳过一个细节。 Office 的 PIA 非常大。究竟由谁负责确保将 PIA 部署在机器上通常是非常模糊的。程序在没有人照顾的情况下失败,这是一种非常常见的事故。

Microsoft 在 .NET 4 中解决了一个负担,当两个 COM 接口类型具有相同的 [Guid] 时,它们被认为是相同的,即使它们来自不同的程序集。这允许一个技巧,编译器现在可以将互操作程序集中的类型声明复制到输出程序集中。只有你实际使用的。解决部署问题和庞大的互操作库问题。您不再需要 PIA,也不必再部署互操作程序集。这就是"Embed interop types"的意思。

长话短说,元数据不足以执行代码。您确实必须在目标计算机上安装 Office 程序。当它不是时得到这个确切的异常。