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

WinGet on Windows Server Core #4319

Open
denelon opened this issue Mar 27, 2024 · 6 comments
Open

WinGet on Windows Server Core #4319

denelon opened this issue Mar 27, 2024 · 6 comments
Labels
Issue-Feature This is a feature request for the Windows Package Manager client.

Comments

@denelon
Copy link
Contributor

denelon commented Mar 27, 2024

I'd like WinGet to function correctly on Windows Server Core. The main gap identified by @jantari was related to the way WinGet determines the locale for package metadata.

Quote from the discussion below: 

I looked into it and this API does appear to not be present in Server Core (meaning this error from our call to it is expected). That of course depends on my ability to map from the internal identifier to the marketing name, which should not be considered infallible.

I think at this point we could confidently wrap the implementation of Locale::GetUserPreferredLanguages to prevent the error from escaping. The default state would be that locale was not included in the installer selection if the call failed.

This is a good workaround in the interim.

Originally posted by @JohnMcPMS in #2361 (reply in thread)

@microsoft-github-policy-service microsoft-github-policy-service bot added the Needs-Triage Issue need to be triaged label Mar 27, 2024
@denelon denelon added Issue-Feature This is a feature request for the Windows Package Manager client. and removed Needs-Triage Issue need to be triaged labels Mar 27, 2024
@jantari
Copy link

jantari commented Jul 30, 2024

Some additional context and thoughts for this issue. I will refer to Windows Servers default install, without Desktop Experience, as "Windows Server Core" or "Server Core" for brevity, even though that term is no longer officially correct.

  1. The goal is to get winget shipped in-box with Windows Server 2025 Core installations, and easier to get going on Windows Server 2022 Core installations. Currently the bootstrapping process is very involved and kind of hacky.
  2. In my own VM-based testing with Server 2022 Core, this one API call:
    preference = Settings::User().Get<Settings::Setting::InstallLocalePreference>();
    if (preference.empty())
    {
    preference = Locale::GetUserPreferredLanguages();
    }
    failing is the last blocker before the all-important winget install command can run successfully. No further workarounds, shims or shenanigans needed. This means we're already "close to the finish line" on Server Core compatibility.
  3. The above API call does succeed on Windows Server Core 2022 with the AppCompatibility FoD installed
  4. There seem to be more errors/blockers for getting winget to run on Server 2019 Core. I wasn't able to investigate and solve these, but I'd be totally happy if it worked on 2022 and 2025 Core first. 2019 Core would be nice to have later.
  5. Winget has already been announced to ship as part of the default Windows Server 2025 with Desktop Experience install. This is great, but the Desktop Experience install is a huge compatibility bandaid you'd only use when absolutely necessary, and many environments therefore mix both Core and Desktop-Experience deployments. The inability to use winget across them all is a blocker to its adoption even if it were partially available OOTB.
  6. Some ideas for addressing the failing Locale::GetUserPreferredLanguages API call:
    • Find and use an alternative API that works on Server Core, or be naughty and get the locale from the registry somewhere as a fallback
    • Catch the error and just default to a packages' DefaultLocale when the user's preferred locale cannot be determined (I believe this is what @JohnMcPMS suggested in their own words)
    • You said a locale is required to use the "msstore" source so just block/refuse installs from the "msstore" source when the user's preferred locale cannot be determined - just like when the source agreements weren't accepted. I personally, and I imagine many business customers, will exclusively use private package repositories for software deployments to Servers anyway and never the community repo or msstore.
  7. In addition to the Locale-API blocker discussed above, you also brought up that we also don't have a good way to determine which packages are suitable for an environment with no desktop experience. I firmly believe this is not on winget to solve and doesn't have to be addressed together with the Locale API issue or to ship winget inbox with Windows Server Core. Still, some additional thoughts for when there is time to address this:
    • Package compatibility with Windows Server installs currently has to consider Windows Server Core, Windows Server Core with the AppCompatibility FoD and Windows Server with Desktop Experience. If Microsoft ever introduces an "AppCompatibilty FoD 2" as a further in-between choice, the package manifest spec should be able to support that too (keep it flexible/extensible)
    • Many community repo package authors will understandably forego testing compatibility with these 3 different deployment scenarios of Windows Server in all its various versions. Many if not most packages will therefore probably never have up-to-date compatibility metadata for Windows Server.
    • Automated pipelines could test whether the installation of a package succeeds on all these different Windows Server versions and configurations, but cannot assert the software functioning
    • Software being compatible with Server Core is not a simple yes/no checkbox. If software "A" only works partially, or maybe even doesn't open at all but the installer registered COM servers and DLLs which another software "B" depends on and CAN use successfully on Server Core then is software "A" compatible with Core or not?
    • winget should therefore never refuse to install any package, marked compatible/incompatible through its metadata or not, on any deployment-type of Windows Server. In the example above, if I want to install software "B" which is marked compatible with Server Core, and it depends on software "A" which technically isn't really compatible with Server Core but installs enough to satisfy the dependencies of software "B" then it would be really infuriating to have winget refuse to install it just because some community manifest author (understandably) didn't consider this usecase.
    • It is also possible for an administrator to solve any compatibility issue there might have been preventing a certain software to run on Server Core. This would mean that the software technically wasn't compatible with a fresh vanilla VM install of Server Core, and any automated tests or package authors would therefore rightfully mark it as incompatible in the package metadata, but a crafty Windows Server admin could create application compatibility shims or manually add a missing DLL etc. to make the application work. I know I've had success with this, so again it would be very unproductive to have winget prohibit me from installing a package that I know I can make work.
    • winget could print a warning though when installing packages that aren't explicitly marked as compatible with the installed flavor of Windows Server (Core / Core + FoD)
    • It's maybe possible to utilize the existing manifest metadata fields Platform and Dependencies.WindowsFeatures for a package to indicate compatibility with Server Core and/or Server Core with the AppCompatibility Feature.

@Karl-WE tagging you because you had some thoughts on this as well. You specifically said:

I would suggest a whitelisting method that comes via new items in manifest like CoreOSCompatibility for Windows Server / Azure Stack HCI, WS DCtr Azure Edition Core Installation mode compatibility and CoreOSFoDCompatibility for Core Installation mode plus requirement of FoD.

Source. Personally, as I've explained above I am against a whitelisting approach and think due to the impossibility of determining a software as "for sure 100% incompatible" with Server Core, winget should at most warn the user and never prohibit package installations.

@Karl-WE
Copy link
Contributor

Karl-WE commented Jul 30, 2024

@jantari was a long read but I agree with you in most parts. Also your reasons with or better said against whitelisting are very reasonable. Thanks for adding your valueable thoughts.

I strongly agree on the mixed environment of core and GUI install options and the adoption rate of winget.

Personally would like to focus on Windows Server 2025 as supported and 2022 as unsupported. 2019 is out of mainstream support and as such no hope, by definition, for any change or backport.

@denelon
Copy link
Contributor Author

denelon commented Jul 30, 2024

In general, I agree with what was stated. There may be some minor differences in my thinking currently.

Adding "allow" or "deny" lists in WinGet is something I'm currently opposed to. That kind of granularity comes with too much overhead. That's why we created the REST APIs, so enterprise customers could select which packages (and versions) they wanted to support in their own source. Of course, that means we have all kinds of interesting policies in the WinGet community repository, but the client was designed with many of these use cases in mind for future scenarios.

WinGet does have the "--force" argument, which is essentially giving users the ability to tell WinGet: "I don't really care what you think, or what the manifest says, just do what I told you. 😊"

Given that, I think having some kind of metadata in the manifest describing which target OS platform/versions a package has been tested or verified against is goodness. The client would essentially make determinations as it does today with respect to which installer it thinks is most appropriate for the device at the point in time the command is run. If no suitable match is found, WinGet would report the results, but the user could simply force the "install"/"upgrade".

If an existing version of the package is present on the system, there are other implications to consider, but I agree. An administrator should be able to override the default behavior and manage packages how they see fit.

There are several dimensions evaluated when selecting an installer. I don't know if we need to extend the list, but I'm including it below for reference. I think extending "Target Platform" makes the most sense in the context of this discussion. I'm also thinking on Server without desktop experience, the default installation mode should be "silent".

  • Architecture (ARM64, x64, x86)
  • Installer Type (exe, MSI, MSIX, portable)
  • Locale (BCP 47)
  • Scope (User vs. Machine)
  • Target Platform (Windows.Desktop)

@tristanbarcelon
Copy link

Hi @denelon would using the language value from this registry key be translatable to a locale?

image

@jantari
Copy link

jantari commented Sep 12, 2024

Looking at ProcessMonitor, winget or a library used by it currently already queries PreferredUILanguages inside HKLM\System\CurrentControlSet\Control\MUI\Settings. This contains a BCP 47 language tag on my systems, and this key also exists on Server Core 2022 out of the box.

However I believe the problem with both these keys is that they show the machine locale and winget would probably rather use the current user's locale preference. Quickly searching through the current user's registry with reg query "HKCU" /f "en-US" /d /s on Server Core 2022 shows a few results too though:

HKEY_CURRENT_USER\Control Panel\Desktop\MuiCached
    MachinePreferredUILanguages    REG_MULTI_SZ    en-US

HKEY_CURRENT_USER\Control Panel\International
    LocaleName    REG_SZ    en-US

HKEY_CURRENT_USER\Control Panel\International\User Profile
    Languages    REG_MULTI_SZ    en-US

HKEY_CURRENT_USER\Control Panel\International\User Profile System Backup
    Languages    REG_MULTI_SZ    en-US

HKEY_CURRENT_USER\SOFTWARE\Microsoft\Internet Explorer\International
    AcceptLanguage    REG_SZ    en-US,en;q=0.5

There are probably more approved ways to get to this information too, because the International PowerShell module is pre-installed on Server Core 2022 and works. There's some good cmdlets in there (check Get-Command -Module International -Verb Get). This means we can successfully run cmdlets such as:

  • Get-WinSystemLocale
  • Get-WinHomeLocation
  • Get-WinUserLanguageList

I haven't debugged whether these call Core-compatible APIs or access the registry directly, but I'd expect sixteen layers of enterprisey factory-factories aka APIs so that should be good for winget.


Unrelated, I'll soon have some more details on the Server Core 2022 compatibility of winget. My original observations in February were somewhat flawed because I was working on a system I had already experimented on and tried lots of things prior so it turns out it's not JUST that one API call after all.

@jantari
Copy link

jantari commented Sep 12, 2024

Update with additional observations regarding Server Core (2022) compatibility:

I have to make a late follow-up to this post; what I observed above isn't incorrect but I have just deployed a new, untouched Server 2022 Core and made some additional observations. The VM I had used for the troubleshooting above wasn't "clean" because I had already experimented a bunch trying to get winget to run, so here's my new (re-)discoveries:

winget depends on Windows.Globalization.dll. This library isn't present on Server Core 2022, you have to copy this file out of System32 from a machine with the Desktop Experience or with the AppCompatibility FoD installed and put it into your winget program directory next to winget.exe.

Just adding this file has already allowed winget on my new, vanilla Server 2022 Core VM to install some packages, however another package was still failing to install with the dreaded Class not registered error. I don't know exactly what exact code paths were taken here, but some troubleshooing revealed that the issue was caused by winget not understanding that an API it tried to use (Windows.System.UserProfile.GlobalizationPreferences) is actually also provided by the aforementioned Windows.Globalization.dll despite the namespaces not matching up. Winget kept trying to find Windows.System.UserProfile.dll, which I don't think is winget's fault but just default fallback behavior from Windows for DLL discovery.

On my GUI systems there's a registry key (HKLM\SOFTWARE\Microsoft\WindowsRuntime\ActivatableClassId\Windows.System.UserProfile.GlobalizationPreferences) that I believe is responsible for pointing apps to the correct DLL to use for that type (there's a DllPath key there that points to C:\Windows\System32\Windows.Globalization.dll), however I wasn't sure what kind of side-effects it would have to manually create this key on my Server Core system and I wasn't able to get it to appear naturally by running regsvr32.exe Windows.Globalization.dll, so what I ended up doing was creating a symlink in the winget program directory named Windows.System.UserProfile.dll that links to the Windows.Globalization.dll in the same location:

image

This workaround makes winget find the correct DLL it's looking for under the wrong name without having to edit global registry keys or system directories which could confuse and break other applications.

Now, interestingly, after applying these two fixes I currently do NOT need to set my locale preference using the winget settings.json file on this system to be able to install all the software I want. However I would still recommend performing all three fixes (copying over Windows.Globalization.dll, creating the symlink, setting the locale preference in settings.json) as they're harmless and winget goes through lots of different code paths during installations, calling locale/language APIs many different places and I've seen Class not registered failures related to that at many different stages of the install and show flows by now.


Copy-pasted from the related discussion #2361 (reply in thread)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Issue-Feature This is a feature request for the Windows Package Manager client.
Projects
None yet
Development

No branches or pull requests

4 participants