如何在 UWP 应用程序中创建 COM 对象? (C#)

How to create a COM object in a UWP application? (C#)

问题:如何在通用 Windows 平台 (UWP) 应用程序中创建 COM 对象?

动机:我想从 WPF 切换到 UWP。由于我的工作负载需要调用只能通过 COM 访问的第三方库(据我所知),因此我需要从 UWP 进行 COM 调用。

上下文:

背景

在Visual Studio 2013年("Classic Desktop"项目在Visual Studio 2015年),我使用了C#代码

// Conceptual:
DotNetInterface comObjectInstance =
    (DotNetInterface)Microsoft.VisualBasic.Interaction.CreateObject(
        "this string specified the COM object type"
      );

// Example:  Open Excel via COM:
Excel.Application oApp = (Excel.Application)Interaction.CreateObject("Excel.Application");

Visual Studio 项目需要引用 Microsoft.VisualBasic 才能使用 Interaction.CreateObject() 和 COM 对象的类型库。

我想在 Windows 2015 Enterprise 在 Windows 10 Education 上生成的通用 Windows 平台 (UWP) 应用程序中使用此 C# 代码。我可以添加对 COM 对象类型库的引用,但无法引用 Microsoft.VisualBasic,因为它没有出现在 Visual Studio 的引用管理器中。

想法、尝试过的解决方案、推测等

我添加了对 "Windows Desktop Extensions for the UWP" 的引用,希望它可以启用对普通 .NET 功能的调用,但还没有弄清楚如何使用它。

我认为,即使 UWP 应用程序根本无法进行 COM 调用,我们也至少可以构建一个包装器来调用普通的 .NET 程序(即使通过网络端口),该程序又能够 运行 COM 调用。由于即使在最坏的情况下也显然有可能变通,所以我觉得应该有(而且很可能是)Microsoft 提供的创建 COM 对象的解决方案。但我想由于 UWP 太新了,在线文档非常稀少,现在很难找到。

更新#1

找到一篇 MSDN 文章 Win32 and COM for Windows Runtime apps and Universal Windows Platform (UWP) apps,其中声称 WinRT 应用程序(包括 UWP 应用程序)只能使用 COM 对象的子集。 MSDN 建议使用受支持的 COM API 元素或从不受支持的 COM API 迁移到功能替代品。

我通过谷歌搜索 运行-time 错误找到了这篇文章,这是在我找到一种方法来对我的第三方库进行 COM 调用后抛出的。错误:

An exception of type 'System.Runtime.InteropServices.COMException' occurred in mscorlib.ni.dll but was not handled in user code

Additional information: Creating an instance of the COM component with CLSID {[edit: GUID removed]} using CoCreateInstanceFromApp failed due to the following error: 80040154 Class not registered (Exception from HRESULT: 0x80040154 (REGDB_E_CLASSNOTREG)). Please make sure your COM object is in the allowed list of CoCreateInstanceFromApp.

我仍然不确定是否有内置方法可以访问我的第三方库的 COM API。如果没有,这可能意味着我必须使用网络端口或其他东西制作我自己的包装器,这似乎是错误的。

您当然知道 UWP 应用程序是沙盒应用程序,它们需要获得许可才能执行几乎所有操作。例如,他们无法访问整个文件系统,而只能访问一个沙盒存储区域。 当您希望应用程序在 Windows 商店中发布时,应用程序认证工具包会检查您的应用程序是否执行不允许执行的操作。

您提供的 link(Windows 运行时应用程序的 Win32 和 COM...)描述了允许的 WIN32/COM 调用列表。 Microsoft 允许您调用这些方法,并且只能调用它们。

使用 Visual Basic COM 对象似乎遥不可及...

这与安全限制有关,但也与可用功能有关:例如,无法在 Windows Phone (regsrvr32) 上注册 COM 对象。

你可以call any COM object (or Win32 API) in C# in a WPF application, and in C++ of course. Not sure what happens if you try to copy/paste this kind of code in a UWP app. You'll may be able to run the code on Windows Desktop, but you won't certainly be able to submit your app to the Windows Store, and it won't work on other UWP platforms. Microsoft doesn't give many details about calling COM objects from UWP app.

我猜 UWP 不太适合 suited/adapted/compatible COM 对象...我不确定从 WPF 到 UWP 的迁移会给你带来什么?

UWP 或 Windows 通用应用程序在这里听起来不是正确的解决方案。 UWP 不允许使用 COM,因为它并非在所有平台上都可用。我假设您希望将 windows 存储用于当前 WPF 应用程序的部署机制。 Windows 10 确实提供了微软称之为 WPF 应用程序桥的功能,您可以在其中将 WPF 应用程序作为 appx 包部署在 windows 商店中。

希望你用这个解决方案重写的东西很少

有关如何在 APPx 文件中部署 WPF 应用程序的详细信息,请观看以下视频。 https://channel9.msdn.com/Events/Build/2015/2-692

如您所见,无法从通用 Windows 应用访问任意 COM 对象。您的第三方库很可能也使用 API,它们不能直接从 Windows 运行时中获得。

假设您打算旁加载应用程序而不是通过商店部署,您可以通过 Brokered Windows Runtime Components for side-loaded Windows Store apps 间接调用您的 COM 对象和库(Windows 8.1 的文档,但仍然对 Windows 10).此功能专为企业应用程序设计,旨在提供现代 UI,同时仍然可以访问现有功能。

如果您想通过商店进行部署,那么您将被限制在 Windows 运行时上下文中允许的 API,并且不能使用代理的 Windows 运行时组件。

如果您的主要目标是通过商店进行部署,并且您不需要以其他方式转换为通用应用程序,那么请查看即将推出的 Windows Bridge for Classic Windows apps (also called ”Project Centennial”),它将允许打包您当前的 .Net 项目存储部署并将允许扩展它以使用一些 UWP 功能。

在另一个站点上,出于安全原因,UWP/WinRT 方式似乎是 MS 在那里进行的唯一方式 OS。 我不知道 Sandbox 是否能够在从允许的对象调用的旧式自定义 COM 对象上检测到不允许的操作。我希望这对沙盒来说是可能的。