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-минутный вопрос способом для меня решить неразрешимые проблемы.
Бонус Чтение
- Вот парень, у которого встроенный манифест тоже игнорируется. Для него это заставляет приложение не соблюдать его
requireAdministrator
вход в систему безопасности - Манифест не заставляет Visual Studio 2013 перезагружаться в режиме администратора при запуске приложения в режиме отладки.
- Манифест приложения игнорируется
- Visual Studio вызывает игнорирование встроенного манифеста сборки при отладке
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.