Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Build a Windows 7 compatible Single-file AppHost #13356

Closed
BrainSlugs83 opened this issue Aug 31, 2019 · 11 comments
Closed

Build a Windows 7 compatible Single-file AppHost #13356

BrainSlugs83 opened this issue Aug 31, 2019 · 11 comments

Comments

@BrainSlugs83
Copy link

General

With .NET Core 3.0-preview8 -- I compiled a standalone exe for Windows 7 (x86) RID using the following command:
dotnet publish -c Release -r win7-x86 -o .\bin\Redist\windows /p:PublishSingleFile=true /p:PublishTrimmed=true /p:DebugType=None

This produces a single .exe file output that runs fine on Windows 10 (x64).

But when I copy this .exe file to a Windows 7 Home Basic (x86) machine, I get the following error message when trying to run it:

The program can't start because api-ms-win-crt-runtime-l1-1-0.dll is missing from your computer. Try reinstalling the program to fix this problem. 

According to this issue: https://github.com/dotnet/core-setup/issues/3220 it looks like this external dependency is possibly the "Windows Universal C Runtime", which can be found at this location: https://support.microsoft.com/en-us/help/2999226/update-for-universal-c-runtime-in-windows

There does appear to be a download link for Windows 7 (x86), but when you try to install it on said operating system, you get the following message: The update is not applicable to your computer. -- This leads me to believe that it is impossible to run my app on Windows 7 (x86).

Expected Behavior:

  • My app runs on Windows 7 (x86) without having to install anything that does not ship with
    the OS. (Many Corporate and Enterprise environments do not have the ability to install
    random service packs on their machines without significant IT involvement and overhead.)

    • Also, I'd like to avoid dependency issues, e.g. if a user has the wrong version installed, etc.
  • If I do have to install some random service pack, tell me about it and where to download it
    instead of a random missing dll notice, as that's a disaster waiting to happen. (A non-technical
    user might just google the error message and follow some youtube video's instructions to
    download random .dll files from untrusted sites and dump them into the app's folder!)

Other thoughts

  • This isn't that tall of an ask. We wrote GUI software for Windows 7 with MinGW 20 years ago,
    and it never required any c runtime dlls; everything was statically linkable. (And never more
    than 2 MB) -- This is literally just a console app -- if there is some external dependency, just
    link it into the executable already! 😑
@scalablecory
Copy link
Contributor

We do not claim Windows 7 support: only Windows 7 SP1.

If I do have to install some random service pack, tell me about it and where to download it instead of a random missing dll notice

This is good feedback, thank you.

There does appear to be a download link for Windows 7 (x86), but when you try to install it on said operating system, you get the following message: The update is not applicable to your computer. -- This leads me to believe that it is impossible to run my app on Windows 7 (x86).

Correct, the update is for Windows 7 SP1.

We wrote GUI software for Windows 7 with MinGW 20 years ago, and it never required any c runtime dlls; everything was statically linkable. (And never more than 2 MB) -- This is literally just a console app -- if there is some external dependency, just link it into the executable already! 😑

Dynamic linkage gives users a better experience. By allowing the CRT to be updated independently of the app, you can fix security issues quicker without relying on developers staying on top of things.

@scalablecory scalablecory transferred this issue from dotnet/core Sep 3, 2019
@scalablecory
Copy link
Contributor

@jeffschwMSFT is this something you can assist with? I think a version check in the host exe with a useful message would be helpful.

@jeffschwMSFT
Copy link
Member

We currently do not do any native trimming, so the api-* files should still be present in the output.

cc @swaroop-sridhar @sbomer

@swaroop-sridhar
Copy link
Contributor

I tried publishing a simple console app. The trimmed published single-file for win7-x86 runtime does contain api-ms-win-crt-runtime-l1-1-0.dll.

@BrainSlugs83 Can you please confirm if api-ms-win-crt-runtime-l1-1-0.dll is indeed missing, or somehow unusable?

  1. If you take the output of a "normal" publish to the win7 machine, does it run OK?
    [dotnet publish -c Release -r win7-x86 /p:DebugType=None, copy the output folder]
  2. If you look at the temp directory (%tmp%/.net/<name-of-app>/<some-hash>/) you can see the files extracted from the single-file app. Is api-ms-win-crt-runtime-l1-1-0.dll found there?

@jkotas
Copy link
Member

jkotas commented Sep 4, 2019

@swaroop-sridhar The problem is that the apphost depends on these api-ms-win-crt-* contracts. The process fails to start. We do not even start extracting the files.

@jeffschwMSFT
Copy link
Member

In the short term we could disable these files from the bundle:


PreserveNewest
true


In the longer term we need to explore what a more Win7 compliant apphost would look like.

@BrainSlugs83
Copy link
Author

BrainSlugs83 commented Sep 11, 2019

@swaroop-sridhar the output I get from build is a single .exe file. -- so I'm confused as to what you want me to check. -- There are definitely no DLL files being dumped out into my -o directory.

The lack of SP1 on my environment is interesting. I grabbed the latest installation media from MSDN. Also, it wasn't obvious to me that SP1 was related to this (from any of the error messages I got along the way). It literally never even occurred to me. So yeah, a better error message about what's missing and how to correct it would be nice. If possible. 🤔

@jkotas to get around this issue back in the day, we used to load DLLs at runtime instead of link against them. -- It made the C++ a bit more annoying to write, but nothing a wrapper class couldn't tackle:

@swaroop-sridhar
Copy link
Contributor

@BrainSlugs83 We understand the problem given @jkotas's explanation
(https://github.com/dotnet/coreclr/issues/26493#issuecomment-527715066).

Without the Dlls being separate, there's no way to run the host (let alone extract contents or print diagnostic messages). The error message you see is from Windows.

The work around for now is to keep the api-ms-win-crt-runtime-l1-1-0.dll separate from the single-exe, as @jeffschwMSFT suggested above. But in later stages of single-exe support, we need to investigate a better solution (possibilities to link in the DLL into the host).

@msftgits msftgits transferred this issue from dotnet/coreclr Jan 31, 2020
@msftgits msftgits added this to the Future milestone Jan 31, 2020
@swaroop-sridhar swaroop-sridhar self-assigned this Feb 6, 2020
@swaroop-sridhar swaroop-sridhar changed the title Windows 7 x86 support is a lie Build a Windows 7 compatible AppHost Feb 20, 2020
@maryamariyan maryamariyan added the untriaged New issue has not been triaged by the area owner label Feb 26, 2020
@jeffschwMSFT jeffschwMSFT removed the untriaged New issue has not been triaged by the area owner label Apr 3, 2020
@swaroop-sridhar swaroop-sridhar removed their assignment Sep 8, 2020
@swaroop-sridhar swaroop-sridhar changed the title Build a Windows 7 compatible AppHost Build a Windows 7 compatible Single-file AppHost Sep 18, 2020
@BinToss
Copy link

BinToss commented Oct 15, 2021

It seems the C runtime would need to be statically linked in the CLR App Host.

When building and publishing a SingleFile executable that targets win7-x86, win7-x64, win-x86, or win-x64, the IL Linker will need to crawl to find and extract code references from the C Runtime that are not available out-of-the-box on Windows 7 SP1. A not-so-insignificant amount of time would need to be spent to create the logic necessary for the crawl to know what is and isn't available on a factory-fresh Windows 7 SP1 install.

Solution A: Extract C Runtime assembly references and inject them into the CLR App Host during Compile/ILLink time

Solution B: Instead of injecting the C Runtime references into the App Host, inject them into a wrapper assembly. The wrapper assembly would contain and run the extracted (or generated) C Runtime references alongside the code normally used to run a SingleFile App Host. The resulting executable would be an objectively messy amalgamation that (hopefully) works.

non-SingleFile App Host ->
wrapper assembly with injected/generated C Runtime and SingleFile-equivalent functionality ->
developer's root assembly.

Solution C: Update Windows 7 SP1 images to have the the C Runtime preinstalled and distribute it via Windows Update to preexisting clients. Easier said than done, I know—Especially so since the OS is being sunsetted.

Non-Solution D: Drop support for Windows 7 SP1. It would be a shame, but it would also prevent a lot of headaches. Who knows? Maybe a community-supported win7 image could arise that alleviates issues stemming from the Operating System's age and under-the-hood mess right before the heat death of universe is observed.

@BinToss
Copy link

BinToss commented Feb 5, 2022

This may have been resolved by

Two related pull requests are awaiting review in dotnet/sdk

@NN---
Copy link
Contributor

NN--- commented Feb 7, 2022

Merged today 🥳

@dotnet dotnet locked as resolved and limited conversation to collaborators Jun 1, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

11 participants