我一直在C ++中使用C#,C ++ / CX和WRL来试验WinRT组件。到目前为止,我设法做了我尝试过的所有事情,即使与COM相比,有些东西已经改变,要么让人感到困惑,要么令人沮丧。
我正在尝试的最后一件事,到目前为止,我做不到的是COM的基本架构模式。我只是想创建一个WRL组件的实例,而不是在使用该组件的项目中引用DLL。据我记得这是COM的基本行为,提供COM的CoClass的GUID,使用程序只知道接口,CoCreateInstance将动态加载COM并创建附加到您请求的接口的实例
我无法找到如何使用WRL。我已经定义了一些简单的接口,我甚至无法在注册表中找到它们。但是,由于COM可以在没有注册表的情况下使用对象,并且现在存在窗口元数据,我认为这就是原因。
有人知道这是不是对WinRT的限制(这会使它成为一个非常糟糕的架构......)或者如果有可能如何实现与WRL的后期绑定。
为了说清楚,在调用程序中我想只提供接口的信息(这可能是.h)然后我需要能够使用其GUID或a创建WinRT组件的实例。绰号。这是我在C ++ / COM,C#和Java中使用的架构模式,因为您可以编写应用程序并支持新功能,而无需触及应用程序的某一行,甚至无需重新编译它。
由于 O. Rouit
答案 0 :(得分:7)
到目前为止,我们还不清楚你真正想做什么。如果您正在使用C ++(将其视为WRL-is-to-WinRT-as-ATL-is-to-COM),WRL只是WinRT的C ++帮助程序库。
让我们来看看C ++,因为那是“最原始的”和“C ++”。没有像C#或JS那样的虚拟机或运行时。您是否尝试实例化一个您没有链接的WinRT对象?如果是这样,那很简单 - ActivateInstance(activateableclassid)。真正的问题是你想要实例化什么?如果它是第一方(收件箱/ Windows)组件,它应该可以工作。这非常像COM,其中ACID就像一个CLSID而ActivateInstance()就像CoCreateInstance()。
如果你试图实例化第三方WinRT组件(不是用Windows发布),它会更简单一些。注册第三方WinRT组件的 ONLY 方法是将它们包含在您的包中。包裹彼此隔离,所以你不能拥有,例如AngryBirds提供了一个FOO WinRT对象,并在Scrabble包中的应用程序中使用它。 与COM 不同,注册是机器范围的(或者甚至在HKCU下注册而不是HKLM,用户范围内),WinRT第三方(包' d)WinRT对象仅注册使用通过该软件包中的应用程序。(1)
(1)这是一个小小的谎言。从技术上讲,您的应用程序可以实例化随程序包图中包提供的Windows和WinRT组件提供的WinRT组件。您可以制作一个包含WinRT对象的Framework包,并让您的应用程序包依赖于它。 Windows表示我们的包装取决于框架,因此您的包装图表'包含 2 个包 - 您的应用包和框架包。 但是您无法向商店提交Framework包。本地开发和企业/侧载部署可以执行此操作(它们不会通过商店,因此不需要满足商店提交条件),但提交到商店的任何应用程序包都只能依赖于Windows提供的框架(WinJS,VCLibs,PlayReady / DRM)。这就是PlayReady的工作原理 - 它是一个包含(以及其他)一些WinRT对象的Framework包;如果您的应用程序包上声明了一个包,那么您的包图将包含2个包(您的应用程序的包+ playready' s),而ActivateInstance()可以解决您的应用程序包的联合中的ACID包图。
应用程序模型中内置了很多保护措施。这是其中之一。这可以防止COM地狱'和DLL地狱' - 一切都很好,然后6个月后你安装应用程序Y并且没有明显的原因app X不再有效。新的appmodel旨在防止出现这种情况。
另一个保护是限制可以找到包裹的WinRT对象。即使您将文件放在应用程序的本地文件夹(例如ApplicationData.current.localFolder)中,ActivateInstance()也无法找到它。对于已注册的WinRT对象,WinRT不会在AppData(或其他地方的oodles)下查看 - 只有您的包图中的那些(以及随操作系统提供的第一方(Windows)组件,例如StorageFolder)。
提供COM的CoClass的GUID,使用程序知道 只有关于接口和CoCreateInstance才会动态加载 COM并创建一个附加到您所在界面的实例 请求。 WinRT等效项是提供 WinRT [组件]的运行时类的 ACID ,使用程序只知道接口和 ActivateInstance()将动态加载 WinRT [组件],并创建一个附加到您请求的界面的实例。
需要注意的是,WinRT组件的实现必须在您的包图中注册,即必须列在您应用程序包的AppXManifest.xml中,或者依赖于它们。 AppXManifest.xml。
如果您直接在ABI级别处理WinRT,那么这是最原始级别的。 C ++投影是等价的,只是更方便的语法。 CLR和JS运行时提供了他们自己的增加和执行的变体(例如,搜索" windows 8 javascript本地vs网络隔离")但他们只是进一步着色行为。他们不能否决潜在的操作系统'基线行为。
Damir指出
您无法以任何其他方式将新文件放入安装文件夹 这是唯一可以加载可执行代码的位置 该应用程序。 "可执行代码"根据您的定义,它有不同的形式。
WinRT组件可以从其他地方加载(Windows提供的WinRT组件,依赖包,例如PlayReady框架包)。
(非WinRT,非COM)'原生' DLL可以从其他地方加载(可执行文件目录,System32等)。请参阅Search Order for Windows store apps。
DLL中的.NET程序集有自己类似的限制,例如: Assembly.Load()。有些人会考虑使用Javascript"代码"以及整个本地与网络分区的事情,以便在可以解析代码的地方进一步着色。
作为一般规则,您可以通过各种方式动态加载代码,但它必须是已知的代码。我们不支持您创建的方式,例如一个C ++应用程序,它将加载在商店提交时未知的DLL(WinRT或非WinRT)。您可以使用可选(有条件加载)代码编写应用,可以拥有'插件' - 但是当您提交到商店时,他们需要在您的包裹中。
您无法构建,例如今天的Outlook,Outlook使用开放式插件模型提交到商店,稍后安装Outlook可以找到并使用的OutlookNiftyCalendar插件。不在Windows 8中。
(有一些方法可以通过网络空间在Javascript应用程序中稍微改变一下这个规则,但这本身就是一个复杂的主题,即使这样也限制了硬/软/政策。并且无关紧要如果您没有编写Javascript应用程序)