Переименованный файл WPF exe вызывает исключение FileNotFoundException (нетипично)

#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, и это вызывает некоторые проблемы с выводом сборки, имеющей несоответствующие номера версий. Я опубликую ответ на этот вопрос, как только закончу его писать