3

我的 .NET 客户端应用程序依赖于另一个程序集。这种依赖关系在一个app.manifest文件中声明:

应用程序清单

<?xml version="1.0" encoding="utf-8"?>
<asmv1:assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1" xmlns:asmv1="urn:schemas-microsoft-com:asm.v1" xmlns:asmv2="urn:schemas-microsoft-com:asm.v2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

  <assemblyIdentity version="1.0.0.0" name="Contoso.Frobber.Admin"/>

  <!-- We have a dependancy on Grobber -->
  <dependency>
    <dependentAssembly>
      <assemblyIdentity type="win32" name="Contoso.Grobber" version="1.0.0.0" processorArchitecture="x86" />
    </dependentAssembly>
  </dependency>

  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
    <security>
      <requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
        <!-- UAC Manifest Options
        <requestedExecutionLevel level="asInvoker" uiAccess="false" />
      </requestedPrivileges>
    </security>
  </trustInfo>

  <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
    <application>
      <!-- Windows 7-->
      <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
    </application>
  </compatibility>

</asmv1:assembly>

然后将项目配置为使用我们的app.manifest文件。您在Project -> Application -> Resourcesapp.manifest下指定使用自定义:

在此处输入图像描述

这一切都有效

我必须确保将我的其他程序集放在同一个文件夹中^1。例如:

Contoso.Grobber.manifest

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">

  <assemblyIdentity type="win32" name="Contoso.Grobber" version="1.0.0.0" processorArchitecture="x86" />

  <file name = "Grobberify.dll">
    <comClass
          progid="Contoso.Grobberify"
          clsid="{EB4B9718-0625-4505-BBF2-42CF7E94643E}"
          description="Grobber system frobs"
          threadingModel = "Apartment" />
  </file>
</assembly>

所以我的文件夹中有:

  • 示例应用程序.exe
  • Contoso.Grobber.Manifest
  • Grobberify.dll

一切正常。我的应用程序运行,一切正常。

我可以证明我的嵌入式清单受到尊重,因为如果我将嵌入式清单更改为需要名为Contoso.Grobber asdfasfaraasdf的东西:

  <!-- We have a dependancy on Grobber -->
  <dependency>
    <dependentAssembly>
      <assemblyIdentity type="win32" name="asdfasfaraasdf" version="1.0.0.0" processorArchitecture="x86" />
    </dependentAssembly>
  </dependency>

如果现在运行我的应用程序,Fusion 加载器将意识到没有名为asdfasfaraasdf的程序集,并在加载时抛出错误:

在此处输入图像描述

应用程序无法启动,因为它的并排配置不正确。请查看应用程序事件日志或使用命令行 sxstrace.exe 工具了解更多详细信息。

如果我将我的依赖程序集放回正确的asdfasfaraasdf --> Contso.Grobber,那么一切正常。

调试时除外

没有特别的原因,如果我在调试器中,那么融合加载程序看不到我的程序集清单,它是依赖程序集。

我可以通过在我的程序集清单中声明我依赖于一个不存在的程序集来证明这一点(例如 name="asdfasdfasf")

![enter image description here][3]

该应用程序应该无法启动 -但它会启动!不管我做什么:

  • 使用假程序集名称
  • 删除我的依赖程序集的清单
  • 删除.dll我的依赖程序集

该应用程序不会启动失败。这意味着 Visual Studio 正在运行的我的可执行文件的任何版本:它不包含我嵌入app.manifest的 .

这是一个问题,因为它坏了

您可能认为让应用程序运行是一件好事——我不希望它失败。这是错误的,原因有两个:

  • 如果所需的程序集不存在,我希望它无法启动
  • 依赖程序集包含所需的融合信息

我正在加载的程序集是一个 COM dll。我的.manifest文件包含急需的 COMclsid和文件名信息。当 Visual Studio 不支持我的应用程序清单时,Fusion 加载程序将看不到我的免注册 COM 对象:

<comClass
      progid="Contoso.Grobberify"
      clsid="{EB4B9718-0625-4505-BBF2-42CF7E94643E}"
      description="Grobber system frobs"
      threadingModel = "Apartment" />
  </file>

如果没有此程序集 comClass 信息,我的 .NET 应用程序在调试时无法创建 COM 对象:

[ComImport]
[Guid("EB4B9718-0625-4505-BBF2-42CF7E94643E")]
public class Grabasstic
{
}

IGrobberAss ga = (IGrobberAss)new Grabasstic();

在此处输入图像描述

仅在调试时发生

带有 32 位应用程序的 Windows 7 64 位上的 Visual Studio Community 2013 失败,并且登录用户未配置壁纸仅在调试应用程序时发生。如果我直接运行SampleApplication.exe,则嵌入程序集清单将受到尊重。

这可能与 Visual Studio 不调试的事实有关

示例应用程序.exe

Visual Studio 实际上调试了一个名为:

SampleApplication.vshost.exe

或不。我知道什么?

我如何使它工作?

我知道没有解决办法。地球上对免注册 COM有任何经验的人数仅限于:

可以肯定地说,没有人真正阅读过上面的“研究工作”的整个部分。我也很想知道哪些用户在那里抓住了复活节彩蛋,以及谁会抱怨过多的研究工作。

实际上,我知道没有解决方案。虽然我可以记录这是一个问题的事实,但我并没有暗示任何人都可以解决它。这使得整个 45 分钟的问题成为我发泄无法解决的问题的一种方式。

奖金阅读

4

2 回答 2

4

解决方案Project -> Project Properties禁用Visual Studio 托管进程

在此处输入图像描述

基于Hosting Process 的 MSDN 文档,它对开发人员没有实际价值,可以安全地关闭。

于 2015-06-03T13:55:37.047 回答
1

删除 *.vshost.exe 文件。Windows 缓存每个二进制文件(EXE、DLL)的清单信息,因此它将使用与 *.vshost.exe 文件一起使用的第一个配置。

如果您启动应用程序或不使用 Visual Studio 主机,则不会发生这种情况,因为重新编译时您的二进制文件会发生变化。但是,*.vshost.exe 文件根本没有被修改或触及。

您必须手动删除它并让 Visual Studio 重新创建/复制它。或者更好的是,尝试不使用 Visual Studio 主机。

这是一个正确的参考:Windows Vista Sxs Activation Context Cache。我认为在 8.1 和即将到来的 10 中事情仍然以这种方式工作。

于 2015-06-03T10:24:22.380 回答