Visual Studio 导致嵌入式程序集清单在调试时被忽略
Visual Studio causing embedded assembly manifest to be ignored while debugging
我的 .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
一切正常。我的应用程序 运行s,一切正常。
我可以证明我的嵌入式清单得到了尊重,因为如果我将我的嵌入式清单更改为需要名为 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 的程序集,并在加载时抛出错误:
The application has failed to start because its side-by-side configuration is incorrect. Please see the application event log or use the command-line sxstrace.exe tool for more detail.
如果我将依赖程序集放回正确的 asdfasfaraasdf --> Contso.Grobber 那么一切正常。
调试时除外
没有特别的原因,如果我在 调试器 中,那么融合加载器看不到我的程序集清单及其依赖程序集。
我可以通过在我的程序集清单中声明我依赖于一个不存在的程序集来证明这一点(例如 name="asdfasdfasf")
![enter image description here][3]
应用程序应该无法启动 - 但它启动了!不管我做什么:
- 使用假的程序集名称
- 删除我的依赖程序集的清单
- 删除我的依赖程序集
.dll
应用程序不会启动失败。这意味着 Visual Studio 是 运行ning 的任何版本的可执行文件:它不包含我的嵌入式 app.manifest
.
这是个问题,因为它坏了
您可能认为拥有一个应用程序 运行 是一件好事 - 我不希望 它失败。这是错误的,原因有二:
- 我希望它在所需程序集不存在时无法启动
- 依赖程序集包含所需的融合信息
我正在加载的程序集是一个 COM dll。我的 .manifest
文件包含非常需要的 COM clsid
和文件名信息。当 Visual Studio 不支持我的应用程序清单时,Fusion 加载器将看不到我的 registration-free 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 在 Windows 7 64 位和 32 位应用程序上的失败,logged-in 用户没有配置墙纸仅在调试时发生应用。如果我直接 运行 SampleApplication.exe,则嵌入式程序集清单 是 。
可能与Visual Studio不调试
有关
SampleApplication.exe
Visual Studio 实际上调试了一个名为:
的应用程序
SampleApplication.vshost.exe
还是不行。我知道什么?
我如何让它工作?
我知道没有解决办法。地球上对 registration-free COM 有任何经验的人数限制为:
- me
- me
- Raymond Chen
可以肯定地说,没有人真正阅读上面 "Research Effort" 的 整个 块。我也很想知道哪些用户在那里发现了 easter-egg,以及谁会抱怨 太多 研究工作。
实际上,我知道没有解决办法。虽然我可以证明这是一个问题,但我没有暗示任何人都可以解决它。这使得整个 45 分钟的问题成为我发泄无法解决的问题的一种方式。
红利阅读
- Here's a guy who's embedded manifest is also being ignored。对他来说,这导致应用程序不尊重他的
requireAdministrator
安全条目
- Manifest does not force Visual Studio 2013 to restart under Admin when running application in Debug mode
- App Manifest Ignored
删除 *.vshost.exe 文件。 Windows 缓存每个二进制文件(EXE、DLL)的清单信息,因此它将使用与 *.vshost.exe 文件一起使用的第一个配置。
如果您启动应用程序或不使用 Visual Studio 主机,则不会发生这种情况,因为您的二进制文件在重新编译时会发生变化。但是,*.vshost.exe 文件根本没有被修改或触及。
您必须手动删除它并让Visual Studio recreate/copy 重新出现。或者更好的是,尝试不使用 Visual Studio 主机。
这里有一个正确的参考:Windows Vista Sxs Activation Context Cache。我假设事情在 8.1 和即将到来的 10 中仍然以这种方式工作。
解决方案是禁用来自项目的Visual Studio托管进程 -> 项目 属性:
基于 MSDN documentation of the Hosting Process,它对开发人员没有实际价值,可以安全地关闭。
我的 .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
一切正常。我的应用程序 运行s,一切正常。
我可以证明我的嵌入式清单得到了尊重,因为如果我将我的嵌入式清单更改为需要名为 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 的程序集,并在加载时抛出错误:
The application has failed to start because its side-by-side configuration is incorrect. Please see the application event log or use the command-line sxstrace.exe tool for more detail.
如果我将依赖程序集放回正确的 asdfasfaraasdf --> Contso.Grobber 那么一切正常。
调试时除外
没有特别的原因,如果我在 调试器 中,那么融合加载器看不到我的程序集清单及其依赖程序集。
我可以通过在我的程序集清单中声明我依赖于一个不存在的程序集来证明这一点(例如 name="asdfasdfasf")
![enter image description here][3]
应用程序应该无法启动 - 但它启动了!不管我做什么:
- 使用假的程序集名称
- 删除我的依赖程序集的清单
- 删除我的依赖程序集
.dll
应用程序不会启动失败。这意味着 Visual Studio 是 运行ning 的任何版本的可执行文件:它不包含我的嵌入式 app.manifest
.
这是个问题,因为它坏了
您可能认为拥有一个应用程序 运行 是一件好事 - 我不希望 它失败。这是错误的,原因有二:
- 我希望它在所需程序集不存在时无法启动
- 依赖程序集包含所需的融合信息
我正在加载的程序集是一个 COM dll。我的 .manifest
文件包含非常需要的 COM clsid
和文件名信息。当 Visual Studio 不支持我的应用程序清单时,Fusion 加载器将看不到我的 registration-free 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 在 Windows 7 64 位和 32 位应用程序上的失败,logged-in 用户没有配置墙纸仅在调试时发生应用。如果我直接 运行 SampleApplication.exe,则嵌入式程序集清单 是 。
可能与Visual Studio不调试
有关SampleApplication.exe
Visual Studio 实际上调试了一个名为:
的应用程序SampleApplication.vshost.exe
还是不行。我知道什么?
我如何让它工作?
我知道没有解决办法。地球上对 registration-free COM 有任何经验的人数限制为:
- me
- me
- Raymond Chen
可以肯定地说,没有人真正阅读上面 "Research Effort" 的 整个 块。我也很想知道哪些用户在那里发现了 easter-egg,以及谁会抱怨 太多 研究工作。
实际上,我知道没有解决办法。虽然我可以证明这是一个问题,但我没有暗示任何人都可以解决它。这使得整个 45 分钟的问题成为我发泄无法解决的问题的一种方式。
红利阅读
- Here's a guy who's embedded manifest is also being ignored。对他来说,这导致应用程序不尊重他的
requireAdministrator
安全条目 - Manifest does not force Visual Studio 2013 to restart under Admin when running application in Debug mode
- App Manifest Ignored
删除 *.vshost.exe 文件。 Windows 缓存每个二进制文件(EXE、DLL)的清单信息,因此它将使用与 *.vshost.exe 文件一起使用的第一个配置。
如果您启动应用程序或不使用 Visual Studio 主机,则不会发生这种情况,因为您的二进制文件在重新编译时会发生变化。但是,*.vshost.exe 文件根本没有被修改或触及。
您必须手动删除它并让Visual Studio recreate/copy 重新出现。或者更好的是,尝试不使用 Visual Studio 主机。
这里有一个正确的参考:Windows Vista Sxs Activation Context Cache。我假设事情在 8.1 和即将到来的 10 中仍然以这种方式工作。
解决方案是禁用来自项目的Visual Studio托管进程 -> 项目 属性:
基于 MSDN documentation of the Hosting Process,它对开发人员没有实际价值,可以安全地关闭。