dotnet / wpf

WPF is a .NET Core UI framework for building Windows desktop applications.
MIT License
7.08k stars 1.17k forks source link

"Trim unused assemblies (in preview)" Publish option causes simple WPF app to crash immediately upon launching #2416

Open bignis opened 4 years ago

bignis commented 4 years ago

If I republish without checking "Trim unused assemblies (in preview)", it launches just fine.

Actual behavior: Nothing appears to happen when executing the WpfCoreApp.exe file.

EventViewer says: Description: A .NET Core application failed. Application: WpfCoreApp.exe Path: C:\code\WpfCoreApp\bin\Release\netcoreapp3.1\publish\WpfCoreApp.exe Message: The application to execute does not exist: 'C:\Users\bignis\AppData\Local\Temp.net\WpfCoreApp\gusxieru.uvn\WpfCoreApp.dll'.

Expected behavior: A simple app with a few buttons appears

Minimal repro: In Visual Studio 2019 v16.4.2, load the source code of this simple WPF app = WpfAppSourceCode.zip

Use these publish settings image

and run the file \bin\Release\netcoreapp3.1\publish\WpfCoreApp.exe

nothing will happen and the error appears in the EventViewer.

vatsan-madhavan commented 4 years ago

Not a bug - this is a "use with care" feature 😉

https://github.com/mono/linker/blob/master/src/ILLink.Tasks/README.md

Adding reflection roots

If your app or its dependencies use reflection, you may need to tell the linker to keep reflection targets explicitly. For example, dependency injection in ASP.NET Core apps will activate types depending on what is present at runtime, and therefore may fail if the linker has removed assemblies that would otherwise be present. Similarly, WPF apps may call into framework code depending on the features used. If you know beforehand what your app will require at runtime, you can tell the linker about this in a few ways.

...

bignis commented 4 years ago

hi @vatsan-madhavan I didn't add any Reflection-related code in this simple app, is there something specific you think might be causing this?

vatsan-madhavan commented 4 years ago

A minimal .NET Core 3.1 WPF app with publish options "Produce Single File" and "Trim unused assemblies (in preview)" checked -> crashes immediately upon launching.

This bothers me. Are you seeing this in the stock-template WPF application that is generated by dotnet new wpf or the WPF project template that is instantiated by Visual Studio when creating a new WPF .NET Core project?

bignis commented 4 years ago

I used the Visual Studio project template, like this = image

vatsan-madhavan commented 4 years ago

Just tried it with 3.1.100 SDK and it works fine for me using VS 2019 16.5.0 Preview 2.0 29701.11.master. I suspect only 3.1.100 SDK really matters here.

Would you try these steps and report back?

bignis commented 4 years ago

sure.

I deleted the /bin and /obj folders using File Explorer to get a clean start. I created the global.json file as requested. I ran it again

Application: WpfCoreApp.exe
CoreCLR Version: 4.700.19.56402
.NET Core Version: 3.1.0
Description: The process was terminated due to an unhandled exception.
Exception Info: System.BadImageFormatException: Could not load file or assembly 'C:\Users\unistmi\AppData\Local\Temp\.net\WpfCoreApp\nqfcgp2u.scm\WpfCoreApp.dll'. Format of the executable (.exe) or library (.dll) is invalid.
File name: 'C:\Users\unistmi\AppData\Local\Temp\.net\WpfCoreApp\nqfcgp2u.scm\WpfCoreApp.dll' 

based on this new error I changed the Publish Target Runtime to x64 image

and I published again, launched, and nothing appeared to happen. I did notice this in my Error Log (which I didn't see before) - possibly relevant antivirus protection.

image

I launched again and it now works!

So to isolate what made it work, I deleted the global.json file, deleted the /bin & /obj folders and once again published with the same settings. It worked again.

Next I tried changing back to x86 target runtime, I deleted the /bin & /obj folders. The app crashes again with this in the Event Viewer (no antivirus records this time)

Application: WpfCoreApp.exe
CoreCLR Version: 4.700.19.56402
.NET Core Version: 3.1.0
Description: The process was terminated due to an unhandled exception.
Exception Info: System.BadImageFormatException: Could not load file or assembly 'C:\Users\unistmi\AppData\Local\Temp\.net\WpfCoreApp\ezplbhjd.cpc\WpfCoreApp.dll'. Format of the executable (.exe) or library (.dll) is invalid.
File name: 'C:\Users\unistmi\AppData\Local\Temp\.net\WpfCoreApp\ezplbhjd.cpc\WpfCoreApp.dll'

but the app works fine (doesn't crash) if I uncheck the "Trim unused assemblies (in preview)" option.

So it appears to me that it's the combination of x86 and "Trim unused assemblies (in preview)" that causes it to fail.

I can certainly get the logs and a crash dump, but does this info help at all?

vatsan-madhavan commented 4 years ago

I can guess about an x64 image failing with BadImageFormatException - for e.g., someone tries to launch and x64 app on an x86 OS...

I don't have any guesses for x86 failing with BIFE. It's vaguely reminiscent of #2259 but I'm not sure whether #2259 was even failing with a BIFE - it just seemed like an app-crash from a native exception and may not be related to your issue. I think we'd want to look at the crash-dump (moreso than the msbuild logs) in your case.

bignis commented 4 years ago

Ok, I think I've got it -> WpfCoreApp.exe_200110_181103_dmp.zip

C:\dev\procdump>procdump -e 1 -f "" -x c:\dumps C:\code\WpfCoreApp\bin\Release\netcoreapp3.1\publish\WpfCoreApp.exe

ProcDump v9.0 - Sysinternals process dump utility
Copyright (C) 2009-2017 Mark Russinovich and Andrew Richards
Sysinternals - www.sysinternals.com

Process:               WpfCoreApp.exe (28036)
CPU threshold:         n/a
Performance counter:   n/a
Commit threshold:      n/a
Threshold seconds:     n/a
Hung window check:     Disabled
Log debug strings:     Disabled
Exception monitor:     First Chance+Unhandled
Exception filter:      [Includes]
                       *
                       [Excludes]
                       *
Terminate monitor:     Disabled
Cloning type:          Disabled
Concurrent limit:      n/a
Avoid outage:          n/a
Number of dumps:       1
Dump folder:           c:\dumps\
Dump filename/mask:    PROCESSNAME_YYMMDD_HHMMSS
Queue to WER:          Disabled
Kill after dump:       Disabled

Press Ctrl-C to end monitoring without terminating the process.

[18:11:02] Exception: 04242420
[18:11:02] Exception: E06D7363.PAVEEFileLoadException@@
[18:11:02] Exception: E06D7363.msc
[18:11:02] Exception: E06D7363.PAVEEFileLoadException@@
[18:11:02] Exception: E06D7363.msc
[18:11:02] Exception: E06D7363.msc
[18:11:02] Exception: E0434352.CLR
[18:11:03] Unhandled: E0434352.CLR
[18:11:03] Dump 1 initiated: c:\dumps\WpfCoreApp.exe_200110_181103.dmp
[18:11:03] Dump 1 complete: 1 MB written in 0.4 seconds
[18:11:03] Dump count reached.
C:\dev\procdump>
vatsan-madhavan commented 4 years ago

Can you also zip and upload (a) published DLL/EXE, (b) PDB (from the same location) and (c) the project itself?

vatsan-madhavan commented 4 years ago

Hi @bignis, we could use the DLL's/PDB's matching the crash-dump. It would help us understand if the trimming process corrupted them somehow.

bignis commented 4 years ago

Happy to help. Source code is same as earlier, but reuploading here to keep it all in one place = SourceCode.zip

Exe+PDB of crashing app = https://drive.google.com/file/d/1_ruVOR74VlwDCFPFsdtawuicdOQc2cYh/view

vatsan-madhavan commented 4 years ago

Thanks, we'll look into it.

Quick note: your published app ran without crashing for me.

image

bignis commented 4 years ago

interesting, ok thanks! Before I zipped it up, I did confirm that it was crashing for me, so I've definitely shared the intended files.

vatsan-madhavan commented 4 years ago

@jeffschwMSFT Can we get some help investigating this?

Here is what we know:

Can someone on your end take a look at the attached dump and the DLL embedded in the single-exe that generated the BadImageFormatException and see what's wrong?

Crash dump, exe, PDB, src: https://1drv.ms/u/s!Ah63gfGkKca4lrEMUAKiWc63LiBScw?e=Q3nDJ7

jeffschwMSFT commented 4 years ago

@sbomer @tlakollo

bignis commented 4 years ago

The error I see in the Event Viewer when it crashes varies. I ran it and crashed it just now and I see:

Description: A .NET Core application failed.
Application: WpfCoreApp.exe
Path: C:\code\WpfCoreApp\bin\Release\netcoreapp3.1\publish\WpfCoreApp.exe
Message: The application to execute does not exist: 'C:\Users\unistmi\AppData\Local\Temp\.net\WpfCoreApp\cggbpqh3.wd3\WpfCoreApp.dll'.

and also one other event at the same time:

Avecto Defendpoint Service
Process started in passive mode.
 Command Line: "C:\code\WpfCoreApp\bin\Release\netcoreapp3.1\publish\WpfCoreApp.exe" 
 Process Id: 22004

event log snippet attached here = EventViewerWhenCrashing.zip

I would normally suspect this Avecto Defendpoint program interfering somehow... except that if I skip the 'trim' step everything works fine and the program launches properly.

swaroop-sridhar commented 4 years ago

@bignis what happens if the app is published without checking the "Produce Single File" option? That is, if you enable trimming, but not publish it as a single-file, is there a change in behavior?

bignis commented 4 years ago

@swaroop-sridhar when I tried it just now using these settings

image

I see 198 items in the 'publish' folder output and I run the .exe (WpfCoreApp.exe)

it does load

image

interesting...

swaroop-sridhar commented 4 years ago

Thanks for confirming @bignis.

Looks like the app works OK if only one of Single-file or Trimming publish options are enabled, but not both -- this is a bit weird.

When the app is published with single-file + trimming, the same files 198 files are packed into the ine executable file. At run time, they are extracted to %Temp%.net\WpfCoreApp\cggbpqh3.wd3\ directory (the last part -- hash code -- changes on each build of the app).

So, when the app fails to run, looks like the file %Temp%.net\WpfCoreApp\cggbpqh3.wd3\WpfCoreApp.dll is missing from the extraction directory. (When running the app, watch the contents of this directory, to see what happens to WpfCoreApp.dll)

The only possible explanation I can think of is that, after extraction, the WpfCoreApp.dll is somehow deleted from the temp-directory on your machine (maybe by an aggressive cleanup option/service).

bignis commented 4 years ago

Based on that theory, I checked my computer's antivirus scan logs and it did confirm that the file was actively deleted by the antivirus software: image

for reference this is what my computer is running: image

I wonder why that particular combination of Publish options is triggering Symantec's threat detection...

Anyway, I submitted this use case to Symantec as a false-positive report. Maybe that's all that can be done here. image

vatsan-madhavan commented 4 years ago

@richlander fyi. Do you have suggestions for how to coordinate with Symantec beyond a user-submitted report?

hshristov commented 4 years ago

I have false positives from Symantec even without using "Trim unused assemblies". It reports that vbcscomipler.exe downloaded a suspicious file and deletes it.

I am pretty sure that compiler is not downloading infected files so I reported it as a false positive with Symantec. Even sent them samples of the app I was building (I was using VS template for net Core WPF app). They told me they needed 10 different builds of my app which was ridiculous and suggested to disable this type of analysis.

What I did was to disable scanning on the folder I was working on so Symantec won't delete my assemblies.

I hope you guys can convince them it is false positive so they "fix" their engine... This whole story started with some Preview of 3.0 but still happens using the latest official 3.1.101.

swaroop-sridhar commented 4 years ago

Thanks for confirming, @bignis and @hshristov. I have filed https://github.com/dotnet/runtime/issues/2300 to track this issue in the dotnet/runtime repo. So, I think this issue can be closed in deference to https://github.com/dotnet/runtime/issues/2300

Can you please try another experiment? Please set the environment variable DOTNET_BUNDLE_EXTRACT_BASE_DIR to somewhere other than the temp directory, and then run the single-file app within that environment. This will tell us if the Antivirus is deleting files within the temp-directory, or just deleting extracted files. Thanks.

bignis commented 4 years ago

I set the Environment Variable as instructed

image

Published as Single-File + Trim

image

and executed the .exe file

and found that it created a new folder image

and the app worked without interference by the Antivirus software