Visual Studio causing embedded assembly manifest to be ignored while debugging

2.5k views Asked by At

My .NET client application has a dependancy on another assembly. This dependancy is declared in an app.manifest file:

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>

And then the project is configured to use our app.manifest file. You specify the use of the custom app.manifest under Project -> Application -> Resources:

enter image description here

And it all works

I have to be sure to place my other assembly in the same folder^1. For example:

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>

So i have in my folder:

  • SampleApplication.exe
  • Contoso.Grobber.Manifest
  • Grobberify.dll

And everything works. My application runs, and everything behaves correctly.

I can prove that my embedded manifest is being honored, because if i change my embedded manifest to require something called 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>

If run my application now, the Fusion loader will realize that there is no assembly called asdfasfaraasdf, and throw an error while loading:

enter image description here

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.

And if i put my dependant assembly back to the correct asdfasfaraasdf --> Contso.Grobber then everything works.

Except when debugging

For no particular reason, if i am inside the debugger then the fusion loader is not seeing my assembly manifest and it's dependant assemblies.

I can prove this by declaring in my assembly manifest that i depend on an assembly that doesn't exist (e.g. name="asdfasdfasf")

![enter image description here][3]

The application should fail to launch - but it launches! No matter what i do:

  • use a fake assembly name
  • delete the manifest of my depenent assembly
  • delete the .dll of my dependant assembly

The application does not fail to launch. That means that whatever version of my executable that Visual Studio is running: it does not contain my embedded app.manifest.

It's a problem because it's broken

You might think that having an application run is a good thing - i wouldn't want it to fail. That is wrong for two reasons:

  • i want it to fail to launch if a required assembly is not present
  • the dependent assembly contains required fusion information

The assembly i am loading is a COM dll. My .manifest file contains much needed COM clsid and filename information. When Visual Studio does not honor my application manifest, the Fusion loader will not see my registration-free COM objects:

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

Without this assembly comClass information, my .NET application cannot create the COM object while debugging:

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

IGrobberAss ga = (IGrobberAss)new Grabasstic();

enter image description here

It only happens when debugging

This failure of Visual Studio Community 2013 on Windows 7 64-bit with a 32-bit application, with a logged-in user who has no wallpaper configured only happens while debugging the application. If i run the SampleApplication.exe directly, the embedded assembly manifest is honored.

It might have something to do with the fact that Visual Studio doesn't debug

SampleApplication.exe

Visual Studio actually debugs an application called:

SampleApplication.vshost.exe

Or not. What do i know?

How do i make it work?

I know there's no solution. The volume of people on the planet who have any experience with registration-free COM is limited to:

It's safe to say that nobody actually read the entire block of "Research Effort" above. I'm also curious to see which users caught the easter-egg up there, as well as who will complain about too much research effort.

In reality, i know there is no solution. And while i can document the fact that this a problem, i am under no allusions that anyone can solve it. Which makes this entire 45 minute question a way for me to vent about unsolvable problems.

Bonus Reading

2

There are 2 answers

2
Ian Boyd On BEST ANSWER

The solution was to disable the Visual Studio hosting process from Project -> Project Properties:

enter image description here

Based on the MSDN documentation of the Hosting Process, it has no real value to developers, and can safely be turned off.

2
acelent On

Delete the *.vshost.exe file. Windows caches manifest information per binary file (EXE, DLL), so it'll use the first configuration used with the *.vshost.exe file.

This doesn't happen if you launch your application or if you don't use the Visual Studio host, because your binaries change when recompiling. However, the *.vshost.exe file is not modified or touched at all.

You must manually delete it and let Visual Studio recreate/copy it again. Or better yet, try without the Visual Studio host.

Here's a proper reference: Windows Vista Sxs Activation Context Cache. I assume things still work this way in 8.1 and in the upcoming 10.