Visual Studio вызывает игнорирование встроенного манифеста сборки при отладке

Мое клиентское приложение.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 файл. Вы указываете использование пользовательских 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, тогда все будет работать.

Кроме случаев отладки

Без особой причины, если я нахожусь внутри отладчика, то загрузчик fusion не видит мой манифест сборки и его зависимые сборки.

Я могу доказать это, заявив в своем манифесте сборки, что я зависим от несуществующей сборки (например, 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 в 64-разрядной версии Windows 7 с 32-разрядным приложением, когда вошедший в систему пользователь, для которого не настроены обои, возникает только во время отладки приложения. Если я запускаю SampleApplication.exe напрямую, встроенный манифест сборки учитывается.

Это может быть связано с тем, что Visual Studio не отлаживает

SampleApplication.exe

Visual Studio фактически отлаживает приложение под названием:

SampleApplication.vshost.exe

Или нет. Что я знаю?

Как мне заставить это работать?

Я знаю, что нет решения. Количество людей на планете, которые имеют опыт работы с COM без регистрации, ограничено:

Можно с уверенностью сказать, что на самом деле никто не читал весь блок "Исследования усилий" выше. Мне также любопытно посмотреть, какие пользователи поймали пасхальное яйцо там, а также кто будет жаловаться на слишком большие исследовательские усилия.

На самом деле, я знаю, что нет решения. И хотя я могу задокументировать тот факт, что это проблема, у меня нет никаких намеков на то, что кто-то может ее решить. Что делает весь этот 45-минутный вопрос способом для меня решить неразрешимые проблемы.

Бонус Чтение

2 ответа

Решение

Решением было отключить процесс размещения Visual Studio в Project -> Project Properties:

Основываясь на документации MSDN процесса хостинга, он не имеет реального значения для разработчиков и может быть безопасно отключен.

Удалите файл *.vshost.exe. Windows кэширует информацию о манифесте для каждого двоичного файла (EXE, DLL), поэтому она будет использовать первую конфигурацию, использованную с файлом *.vshost.exe.

Этого не происходит, если вы запускаете свое приложение или не используете хост Visual Studio, потому что ваши двоичные файлы изменяются при перекомпиляции. Однако файл *.vshost.exe не изменяется и не затрагивается вообще.

Вы должны вручную удалить его и позволить Visual Studio заново создать / скопировать его. Или еще лучше, попробуйте без хоста Visual Studio.

Вот правильная ссылка: Кэш контекста активации Windows Vista Sxs. Я предполагаю, что все еще работает таким образом в 8.1 и в следующих 10.

Другие вопросы по тегам