除非我引用项目,否则无法加载WinRT组件

时间:2013-10-24 01:31:00

标签: c# visual-c++ windows-runtime windows-store-apps windows-8.1

我遇到了一个奇怪的问题。我创建了一个Windows运行时组件(用于Windows应用商店),它通过一些C#包装器类为.NET提供了一些旧的C / C ++代码。

我编写了一个测试工具Store App(以下简称“test1”),它引用了WRC 项目(两个项目都在同一个解决方案中)。它调用组件,一切正常。

接下来,我从WRC项目中获取以下输出文件:

MyWrtComponent.dll
MyWrtComponent.exp
MyWrtComponent.pdb
MyWrtComponent.pri
MyWrtComponent.winmd

...并尝试在其他商店应用项目(“test2”)中使用它们。在这个项目中,我添加了对.winmd文件的引用,而不是引用MyWrtComponent项目。一切都很好,但是当我运行test2应用程序时,一旦我尝试使用MyWrtComponent中实现的一个C#类,我就会从mscorlib获得一个System.IO.FileNotFound异常:

at System.StubHelpers.StubHelpers.GetWinRTFactoryObject(IntPtr pCPCMD)
at MyWrtComponent.MyWrtClass..ctor()

The specified module could not be found.
(Exception from HRESULT: 0x8007007E)

使用MyWrtComponent的release vs. debug构建没有任何区别。

在test2上运行ProcMon,我看到几次尝试加载vccorlib120_app.DLL(或者如果我正在构建调试时为vccorlib120d_app.DLL)的尝试失败:

QueryOpen   F:\test2\bin\Debug\AppX\vccorlib120d_app.DLL    NAME NOT FOUND
QueryOpen   F:\test2\bin\Debug\AppX\vccorlib120d_app.DLL    NAME NOT FOUND
CreateFile  C:\Windows\SysWOW64\vccorlib120d_app.DLL    NAME NOT FOUND

我已确认此文件在我的C:\ Windows \ SysWOW64文件夹中不存在。我不知道这是否与我的问题有关。

当我运行test1时,会搜索不同的位置,并找到该文件:

QueryOpen   F:\test1\bin\Debug\AppX\vccorlib120d_app.DLL    NAME NOT FOUND
CreateFile  C:\Program Files\WindowsApps\Microsoft.VCLibs.120.00.Debug_12.0.20827.3_x86__8wekyb3d8bbwe\vccorlib120d_app.dll SUCCESS

我比较了两个测试项目的bin \ Debug \ AppxManifest.xml,并注意到一个重要的区别; test1有以下内容,test2没有:

<Dependencies>
  <PackageDependency Name="Microsoft.VCLibs.120.00.Debug" MinVersion="12.0.20827.3" />
</Dependencies>

如果我将这三行添加到test2的生成输出并运行应用程序,它可以正常工作,但当然这不是一个真正的修复。

有谁知道这里发生了什么? MyWrtComponent是否具有以某种方式未进行通信的依赖关系,或者我是否应该执行某些操作来将vccorlib120d_app.DLL与我的运行时组件一起打包,或者......?

提前致谢。

2 个答案:

答案 0 :(得分:14)

嗯,你在这里遇到了几个问题,第一个是你的WinRT组件使用C ++,你需要在你的应用程序中引用Microsoft Visual C ++运行时包,这是预期的由组件的最终用户(应用程序开发人员)完成,所以要执行此操作,右键单击应用程序的解决方案资源管理器中的References文件夹,然后转到Windows-&gt; Extensions,从列表中选择Microsoft Visual C ++运行时包可用的SDK,然后单击“确定”。

其次,如果您打算自己保留此组件,最好引用项目,因为这是更简单的方法,如果您计划分发它,那么您需要创建一个SDK以确保所有片段在一起,请注意这对于C ++ WinRT组件是必要的,但对于C#或VB.NET组件则不然,原因似乎是C ++ WinRT组件被分成元数据(WinMD文件)和实现(DLL文件),甚至如果你并排放置它们就无法识别对方,而在C#和VB.NET中,元数据及其实现都在同一个文件(WinMD)上。如果您要创建SDK,请在MSDN上阅读this documentation

答案 1 :(得分:4)

您的第二次构建违反了app-package要求。您向应用商店提交的应用程序包具有所有嵌入的依赖关系,以及应用程序清单列出所有这些依赖关系的状态。这是一个强大的DLL Hell对策,Store用户只是没有希望解决你遇到的那种问题。

添加对.winmd文件的引用可使编译器满意,它包含足够的信息来编译源代码。但是下一步出错了.winmd文件没有为构建系统提供足够的信息来将应用程序包放在一起。它无法从.winmd文件中找出您的组件具有其他依赖项。您的主项目不依赖于Microsoft.VCLibs,因为它是一个托管项目。

这并不是说你不能自己维护appxmanifest。它只是额外的工作,这很容易出错,从它们与Debug和Release版本不同开始。下一个VS更新会让你遇到麻烦,毫无疑问它将有一个Microsoft.VCLibs的更新,要求你更新清单中的版本号。

使用项目引用是始终获得正确包的简单方法。