#c# #.net #wpf #reflection
Вопрос:
У меня есть исполняемый файл WPF, который после сборки, если exe переименован, не будет запускаться, потому что возникает исключение FileNotFoundException. Я никогда не видел этого за десять лет работы .ЧИСТЫЕ исполняемые файлы, и это не должно быть проблемой. Наше имя exe построено как «Installer.exe», но если мы переименуем его во что-нибудь другое и попытаемся запустить его, он завершится неудачей со следующим стеком вызовов:
Application: test.exe
Framework Version: v4.0.30319
Description: The process was terminated due to an unhandled exception.
Exception Info: System.IO.FileNotFoundException
at System.Reflection.RuntimeAssembly._nLoad(System.Reflection.AssemblyName, System.String, System.Security.Policy.Evidence, System.Reflection.RuntimeAssembly, System.Threading.StackCrawlMark ByRef, IntPtr, Boolean, Boolean, Boolean)
at System.Reflection.RuntimeAssembly.InternalLoadAssemblyName(System.Reflection.AssemblyName, System.Security.Policy.Evidence, System.Reflection.RuntimeAssembly, System.Threading.StackCrawlMark ByRef, IntPtr, Boolean, Boolean, Boolean)
at System.Reflection.Assembly.Load(System.Reflection.AssemblyName)
at System.Windows.Navigation.BaseUriHelper.GetLoadedAssembly(System.String, System.String, System.String)
at MS.Internal.AppModel.ResourceContainer.GetResourceManagerWrapper(System.Uri, System.String ByRef, Boolean ByRef)
at MS.Internal.AppModel.ResourceContainer.GetPartCore(System.Uri)
at System.IO.Packaging.Package.GetPartHelper(System.Uri)
at System.IO.Packaging.Package.GetPart(System.Uri)
at System.Windows.Application.GetResourceOrContentPart(System.Uri)
at System.Windows.Application.LoadComponent(System.Object, System.Uri)
at Installer.App.InitializeComponent()
at Installer.App.Main()
Если я отлажу исполняемый файл, я смогу расширить его до:
System.IO.FileNotFoundException: 'Could not load file or assembly 'Installer, Version=1.0.0.0,
Culture=neutral' or one of its dependencies. The system cannot find the file specified.'
Я также исследовал журнал слияния:
Assembly manager loaded from: C:WindowsMicrosoft.NETFramework64v4.0.30319clr.dll
Running under executable C:UsersdandeDownloadstest.exe
--- A detailed error log follows.
=== Pre-bind state information ===
LOG: DisplayName = Installer, Version=1.0.0.0, Culture=neutral
(Partial)
WRN: Partial binding information was supplied for an assembly:
WRN: Assembly Name: Installer, Version=1.0.0.0, Culture=neutral | Domain ID: 1
WRN: A partial bind occurs when only part of the assembly display name is provided.
WRN: This might result in the binder loading an incorrect assembly.
WRN: It is recommended to provide a fully specified textual identity for the assembly,
WRN: that consists of the simple name, version, culture, and public key token.
WRN: See whitepaper http://go.microsoft.com/fwlink/?LinkId=109270 for more information and common solutions to this issue.
LOG: Appbase = file:///C:/Users/dande/Downloads/
LOG: Initial PrivatePath = NULL
Calling assembly : PresentationCore, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35.
===
LOG: This bind starts in default load context.
LOG: No application configuration file found.
LOG: Using host configuration file:
LOG: Using machine configuration file from C:WindowsMicrosoft.NETFramework64v4.0.30319configmachine.config.
LOG: Policy not being applied to reference at this time (private, custom, partial, or location-based assembly bind).
LOG: Attempting download of new URL file:///C:/Users/dande/Downloads/Installer.DLL.
LOG: Attempting download of new URL file:///C:/Users/dande/Downloads/Installer/Installer.DLL.
LOG: Attempting download of new URL file:///C:/Users/dande/Downloads/Installer.EXE.
LOG: Attempting download of new URL file:///C:/Users/dande/Downloads/Installer/Installer.EXE.
И я исследовал и исключил следующее:
- Мы не используем сборку.Загрузка для загрузки «Установщика» (который является исполняющей сборкой)
- We do not have any pack:// usages in XAML.
- We have no code analysis warnings, errors, or XAML errors
- It is not related to a application configuration file
- It is not related to the application manifest
- Application crashes even if I change the code to use a normal Window and not our MainWindow (eliminating a lot of XAML from the equation)
- .NET version doesn’t make a difference. It’s targeting and built for .NET 4.6, but changing this doesn’t change the outcome
- Confirmed that all dependencies are referenced/present using DotPeek/JustDecompile
- Confirmed that all namespaces internally are still ‘Installer’
- Исследовал частичную привязку с помощью чтения документации, но это не проблема с ссылками, ошибка указывает на то, что проблема заключается в самой выполняемой сборке (она ищет себя?)
- Не связано с подписанием кода, как это происходит с ним или без него
- Это не связано с подписанием строгого имени, так как мы его не используем
- Изменение выходного имени сборки свойств проекта, но оставление пространства имен в качестве установщика работает и не вызывает проблем
Вещи, которые я наблюдал:
- Это происходит до
OnStartup
. Я не могу выполнить отладку в приложении. - Похоже, что это PresentationCore.dll (из журнала слияния), вызвавшего эту проблему
- Подтверждено с ProcMon.exe что на самом деле он пытается получить доступ к одному из четырех зарегистрированных путей журнала fusion (Установщик.DLL, Установщик/Установщик.DLL, Установщик.EXE, Установщик.Installer.EXE)
- Это происходит в любой среде, и я могу воспроизвести локально, создав решение, затем переименовав выходной файл и запустив его
- Если я скопирую исполняемый файл, переименую его и запущу, он будет работать нормально, потому что Installer.exe присутствует в том же каталоге
Я никогда раньше не сталкивался с этой проблемой, и исследование ее не увенчалось успехом, потому что я просто нахожу все основные вещи, с которыми обычно сталкиваются новые разработчики со ссылочными проблемами и тому подобным.
Мое единственное предположение состоит в том, что, возможно, это связано с XAML, но я не нашел в XAML ничего необычного, и у нас нет никакого пакета:// обычаев или чего-то еще.
Комментарии:
1. В чем заключается ценность
Application.StartupUri
?2. Его нет, потому что я использую переопределение OnStartup.
3. Я думаю, что бы ни
System.Windows.Application.LoadComponent(System.Object, System.Uri)
происходило, Uri будет указывать на исходное имя файла. Может быть, ИлСпи скажет, что такое Uri.4. Я тоже только что наткнулся на это, изучив выходные данные каталога obj, и обнаружил, что App.g.cs имеет другой номер версии, чем сборка, и теперь это имеет смысл. Мы используем Каталог. Файл Build.props и несоответствие с файлом AssemblyInfo.cs, и это вызывает некоторые проблемы с выводом сборки, имеющей несоответствующие номера версий. Я опубликую ответ на этот вопрос, как только закончу его писать