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

Installers should be aware of multi-arch OSes and warn users as appropriate #10192

Closed
vitek-karas opened this issue Apr 12, 2021 · 18 comments
Closed
Assignees

Comments

@vitek-karas
Copy link
Member

Most OSes are becoming multi-arch, in the sense that it's possible to run multiple different architectures on the same machine. For example:

  • Windows x64 and x86 - existing problem
  • Apple M1 x64 and arm64
  • Windows x64 and arm64
  • and so on (pending future support for platform/architecture matrix)

On all platforms, the default installers will put the location of dotnet into PATH. But if they install the second architecture, the resulting experience is confusing to the users. For example:

  • Install x64 .NET 5 on Windows (C:\Program Files\dotnet is added to the PATH)
  • Install x86 .NET 3.1 on Windows (C:\Program Files (x86)\dotnet is appended to the PATH)
    The end result is that both x64 and x86 are on PATH, but the first one wins, so running:
    dotnet --info
    Will run the x64 version and only list 5.0 as installed. Also dotnet app.dll won't work on 3.1 app, even though it was just installed.

Installers should recognize that another architecture is already on the machine and that it's on PATH and inform user about this behavior.

See dotnet/runtime#3820 (comment) for another great example of this problem and how installer warning would help.

@vitek-karas
Copy link
Member Author

/cc @Rick-Anderson

@vitek-karas
Copy link
Member Author

@richlander something like this would be needed for Apple M1 work, if we decide to go side-by-side.

@marcpopMSFT
Copy link
Member

Nikola and Jacques are already discussing how to handle this for x86 and x64. There's a separate discussion for what to do with apple M1 for arm64 and x64 tracked here: dotnet/sdk#16896

@richlander
Copy link
Member

There are two aspects of this:

  • How do we handle the PATH for multiple .NET architectures on a machine?
  • How do we handle .NET versions that are not available/legal for a given architecture?

Here is my proposal:

  • No longer automatically add the non-native .NET install directory to the PATH.
  • Teach the muxer to see all .NET installs (installed to the normal location) on the machine for the purpose of good error messages.
  • Write guidance on how someone should target both .NET Core 3.1 (x64) and .NET 6 (Arm64) on the same machine. Say they are working on two different apps, day in and day out. How do they make that efficient and delightful? This might inspire/require us to make more product changes.

@rickbrew
Copy link

rickbrew commented Jul 30, 2021

Related to this, installation is pretty borked on ARM64 right now (5.0.8).

If you start clean (no .NET installed), and install .NET 5.0.8 x64, it dumps itself into C:\Program Files. At this point, NETCoreCheck (which uses nethost.dll) doesn't function correctly, returning EXIT_FAILURE_HOSTFXREXPORTS (0x3003 / 12291). From looking at the code, this indicates either a LoadLibraryW or GetProcAddress failure (probably the former) with hostfxr.dll https://github.com/dotnet/deployment-tools/blob/3c246e582164af60a222930a2073ba2e1fa6b807/src/clickonce/native/projects/NetCoreCheck/NetCoreCheck.cpp#L39

And then if you install .NET Runtime arm64 + .NET Desktop Runtime arm64 (you have to install both because of dotnet/windowsdesktop#1823 ), you still get the error! This is completely preventing Paint.NET from being able to make heads or tails of the .NET installation status, and it can't proceed. Worse, I'm not even sure what I can or should do to be able to make things work on end-user's systems. I can't detect the installation of the runtime properly, so I can't just plow ahead with installation of the app.

(Note that the x64 version of NETCoreCheck is able to detect the .NET 5.0.8 x64 installation and returns 0 (success) just fine ... but that doesn't help either!)

Any advice on what to do? This is real end-user issue being reported right now: https://forums.getpaint.net/topic/118486-paintnet-43-alpha-build-7881/?do=findComment&comment=585096

@richlander
Copy link
Member

Totally get it and agree. That's what this spec is focused on and that we are still working on for .NET 6. dotnet/designs#217

@rickbrew
Copy link

rickbrew commented Jul 30, 2021

Is there any guidance on what to do for Desktop ARM64 apps today? Right now, if .NET x64 is installed, I simply don't know what to do on ARM64. I can't tell users to uninstall (or automate it) it because that could break other apps.

@joeloff
Copy link
Member

joeloff commented Jul 30, 2021

We're going to broken for some things no matter what unless Windows fix things like the registry. Right now, if you have an x64 and and arm64 copy of an application, they would both default to writing to the 64-bit registry view. Since there is only one, they'll stomp on each other.

The whole installer database is managed in the registry as well so SxS install will just over write and corrupt the database.

@richlander
Copy link
Member

Right. The responsibility is on the app (or framework) developer currently.

@rickbrew
Copy link

I think the only solution right now for ARM64 is to avoid framework-dependent deployment.

Bandwidth-wise that should be OK because I expect ARM64 to be a very small percentage of users at this point.

@vitek-karas
Copy link
Member Author

The whole installer database is managed in the registry as well so SxS install will just over write and corrupt the database.

Maybe we could solve this by naming the product differently (include the architecture in the name).

As for the installation itself, our .NET mechanism of registering the install location can handle this already. As described in this design doc we write the location into the 32-bit view of the registry (always, regardless of which arch we're working with, to avoid the registry virtualization) and we store it per-arch ourselves. So for example HKLM\SOFTWARE\dotnet\Setup\InstalledVersions\x64\InstallLocation for X64 and HKLM\SOFTWARE\dotnet\Setup\InstalledVersions\arm64\InstallLocation for ARM64.

So it's possible to create a working SxS install layout - it's just that our installer can't handle it today.

@joeloff
Copy link
Member

joeloff commented Aug 9, 2021

The whole installer database is managed in the registry as well so SxS install will just over write and corrupt the database.

Maybe we could solve this by naming the product differently (include the architecture in the name).

Not quite, but we are looking at ways to ensure that we have different component IDs for x64 on arm64 vs. x64 on x64. Component IDs are stable UUID3 based of a component key path. In our case, the key path is rooted in ProgramFiles64 and that is the same for both x64 and arm64 OS ("Program Files"). IDs are assigned at compile/link time, so we'd need to generate a different MSI, but we also don't want to double up on the number of MSIs when they are statically linked into the bundles, or the size of the install would explode. For example, consider the SDK carrying two copies of everything for x64. There are ways to address this, e.g. dynamic downloads or shared external CAB files, etc.

@vitek-karas
Copy link
Member Author

I know next to nothing about MSI - so I don't know if it's possible to change the install location based on some logic (detecting ARM64 OS).

@joeloff
Copy link
Member

joeloff commented Aug 9, 2021

Do you know of a reliable key we can use to determine the correct OS architecture? There are properties like VersionNT and VersionNT64 that the installer service will create, but we likely need to look at something like OS architecture. PROCESSOR_ARCHITECTURE may not be sufficient if you can install x64 OS on Arm64 (is that supported?) and then install arm64 native installers, so you have emulated OS with native applications.

I can probably dig something out of the controlset keys, but would prefer something that's stable/documented.

@rickbrew
Copy link

rickbrew commented Aug 9, 2021

@joeloff To detect ARM64 from an x64 MSI you'll likely need a custom action DLL written in native code. The Win32 API you'll want is IsWOW64Process2. It requires Win10 v1709 (aka v10.0.16299.0) despite the docs saying v1511. If the OS is pre-1709, and it says it's x64, then you're on x64 for real. Otherwise query that API.

NETCoreCheck provides a custom actions DLL for detecting .NET 5/6 from an MSI, so you might be able use that as a template for building your own CA DLL. https://github.com/dotnet/deployment-tools/tree/main/src/clickonce/native/projects/NetCoreCheck/CA

edit: Here's my code that I'm using in Paint.NET as part of my setup chainer, adapt as you see fit https://gist.github.com/rickbrew/aec72f8b430375b663c1e690a5dfc01c

@joeloff
Copy link
Member

joeloff commented Aug 9, 2021

Thanks @rickbrew, I was hoping to avoid custom actions. Oh well.

@vitek-karas
Copy link
Member Author

This sounds like something which Windows/MSI should have support for directly - we should make a feature request for this. I doubt we will be the only ones running into this problem on ARM64 OS (since there's no direct SxS support from the OS, unlike with x86/x64).

@marcpopMSFT
Copy link
Member

Old issue triage: this was from before we removed the path and did our arm64 support so closing as no longer needed.

@marcpopMSFT marcpopMSFT closed this as not planned Won't fix, can't repro, duplicate, stale Jun 18, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants