【问题标题】:Visual Studio causing embedded assembly manifest to be ignored while debuggingVisual Studio 导致在调试时忽略嵌入式程序集清单
【发布时间】:2015-08-16 16:15:02
【问题描述】:

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

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 -> Resources 下指定使用自定义app.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>

所以我的文件夹里有:

  • SampleApplication.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 文件包含急需的 COM clsid 和文件名信息。当 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();

只有在调试时才会发生

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

这可能与 Visual Studio 不调试有关

SampleApplication.exe

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

SampleApplication.vshost.exe

或者没有。我知道什么?

如何让它发挥作用?

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

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

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

阅读奖励

【问题讨论】:

  • 您在调试时实际上并没有使用嵌入式清单。将使用磁盘上的 bin\Debug\SampleApplication.vshost.exe.manifest 文件。有什么不对的,看一下。 Fwiw,将其命名为 Contoso.Grobber.Manifest 并显示 app.manifest 的屏幕截图并不能帮助我们帮助您。还可以考虑禁用托管进程,这样就不会成为问题。
  • @HansPassant 那是因为确实两个清单。一种是主机可执行文件 (SampleApplication.exe) 及其嵌入式清单 (app.manifest)。另一个是单独的 dll (Contoso.Grobber.dll) 和它的(外部)程序集清单 (Contoso.Grobber.manifest)。
  • 其实我无法在 Visual Studio 2012 中复制这个问题,它可能是 2013 中的回归。也就是说,当我将清单更改为依赖于不存在的程序集或声明 requireAdministrator 时,转到 DEBUG > Start Debugging 会立即显示效果,例如加载失败,或 UAC 提示符。

标签: visual-studio visual-studio-2013 com registration-free-com


【解决方案1】:

解决方案Project -> Project 属性中禁用 Visual Studio 托管进程

基于 MSDN documentation of the Hosting Process,它对开发人员没有实际价值,可以安全关闭。

【讨论】:

  • 您是否在再次构建和调试之前尝试删除 *.vshost.exe?
  • 这解决了我自己的问题:我在主程序集中嵌入了四个子项目程序集,但在调试期间,我必须在每次运行前清理解决方案,以便自动递增的程序集版本修订成为与子组件构建相同。一个巨大的皮塔饼。在每个项目中禁用 VS 主机进程在 VS2013 中修复了此问题。谢谢!
【解决方案2】:

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

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

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

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

【讨论】:

  • 我赞成反对匿名反对票。我没有尝试删除 VSHost 并重试。我刚刚停止使用主机进程并继续前进。我不相信 Visual Studio 会将 my 清单构建到他们的托管 exe 中。
  • 它没有,但是 *.vhost.exe 文件没有嵌入的清单,VS 在(重新)构建时将您的清单复制到 *.vhost.exe.manifest。
猜你喜欢
  • 2018-12-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多