Skip to content

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

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

Installation Guide for LTSC (and Server OS) #1781

Closed
Zamiell opened this issue Dec 7, 2021 · 11 comments
Closed

Installation Guide for LTSC (and Server OS) #1781

Zamiell opened this issue Dec 7, 2021 · 11 comments
Labels
Issue-Docs It's a documentation issue that really should be on MicrosoftDocs
Milestone

Comments

@Zamiell
Copy link

Zamiell commented Dec 7, 2021

Greetings,

As a brand new winget user, it was painful to get up and running with this software.
This is an issue to request that:

  1. Better documentation should exist; please integrate my work below.
  2. The installer should automatically install the require VCLibs dependency, if necessary. If that is not possible for some technical reason, then a missing VSLibs should be detected and the user should be shown a clear and actionable error message. The existing state of affairs is bad UX; no software should be silently failing.
  3. The installer should detect if a license is specified and if it isn't, prevent the software from being installed while simultaneously showing the user the correct command for specifying a license. It doesn't make sense to allow an unlicensed version to be successfully installed when it results in bricked software.
  4. The installer should not return until winget is actually in the path. This leads to broken scripts and hard-to-troubleshoot behavior.

I'll do my part to help document what I know in this issue, and I leave it to others to do a pull request and/or integrate this information. In the meantime, this may be useful to other users searching through the GitHub issues.


How to Install winget on Windows 10 LTSC / Windows 10 IoT / Windows Server

Summary

  • The official README.md file suggests that you should use the Microsoft Store to get winget.
  • However, this is not possible on Windows 10 LTSC, Windows 10 IoT, or Windows Server, because those operating systems do not have the Microsoft Store installed. Furthermore, it is not possible to manually install the Microsoft Store on those operating systems. (Nor would you want to. 😃)
  • In short, the solution is to manually install the msixbundle file from the GitHub releases page.
  • I can verify that the following steps work properly for Windows 10 LTSC 2021, but not other operating systems. With that said, I imagine that the same steps would work.

Compatibility

winget will work on:

  • LTSC 2019 (build 1809)
  • LTSC 2021 (build 21H2)

It isn't compatible with earlier versions of LTSC.

I don't know the specific versions of Windows Server or Windows IoT that it will work on, if any.

Step 1

Add-AppxProvisionedPackage -Online -PackagePath "C:\Microsoft.VCLibs.x64.14.00.Desktop.appx" -SkipLicense
  • Note that instead of using AppxProvisionedPackage here, you could also use AppxPackage. The difference is that:
  • Also note that without this dependency installed, the winget installer will silently fail (without any error/warning messages). Specifically, the "winget.exe" file will not be added to "C:\Users[Username]\AppData\Local\Microsoft\WindowsApps".

Step 2

  • On the GitHub releases page, find the latest version that does not have a "Pre-release" tag. For reference, at the time of this writing, the latest non-pre-release version is v1.1.12653.
  • Download both the "msixbundle" file and the "License1.xml" file. For reference, at the time of this writing, this is "Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.msixbundle" and "9c0fe2ce7f8e410eb4a8f417de74517e_License1.xml", respectively.
  • Install it with the following Powershell command in an elevated/administrator shell:
Add-AppxProvisionedPackage -Online -PackagePath "C:\Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.msixbundle" -LicensePath "C:\9c0fe2ce7f8e410eb4a8f417de74517e_License1.xml"

Now, you should see the "winget.exe" file appear at "C:\Users[Username]\AppData\Local\Microsoft\WindowsApps". Furthermore, it should also be automatically added to your path.

Gotchas

The point at which winget is added to the path seems random. Sometimes, a sleep of 5 seconds works. Other times, I have to restart my whole computer to get it to show up. So your mileage may vary.


Using winget on First Boot

  • Obviously, if you plan to use winget as your primary package manager, you will want to either:
    1. integrate it into the Windows source with DISM, or
    2. install it automatically on the first boot with a PowerShell script
  • (2) is the simpler option, but I would not recommend it, as the winget installer seems to be unreliable. I was not able to get winget to appear in the PATH in post-installation scripts in a consistent way; your mileage may vary.

1) Integrating with DISM (recommended)

If you've used DISM before to e.g. integrate drivers into a Windows installation source, this process is almost exactly the same.

The following is a reference batch script to accomplish this:

rem Mount the Windows installation source
dism /Mount-Wim /WimFile:"C:\MyWindowsSource\sources\install.wim" /Index:1 /MountDir:"C:\mount"

rem Integrate winget
dism /Image:"C:\mount" /Add-ProvisionedAppxPackage /PackagePath:"C:\winget\Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.msixbundle" /DependencyPackagePath:"C:\winget\Microsoft.VCLibs.x64.14.00.Desktop.appx" /LicensePath:"C:\winget\9c0fe2ce7f8e410eb4a8f417de74517e_License1.xml" /region=all

rem Save the changes
dism /unmount-wim /mountdir:"C:\mount" /commit

2) Using autounattend.xml + PowerShell (not recommended)

  • The "autounattend.xml" file is the file that you stick inside of a Windows source to automate the install, perform additional registry tweaks, and so on.
  • The "autounattend.xml" file can run arbitrary commands, so if you want it to install winget, you have two main options:
    • You can integrate a PowerShell script into the Windows source itself using DISM, and then execute it directly from "autounattend.xml".
    • Or, you can download a script from the Internet (using e.g. curl) and then execute that. (This is the simplest way, but you may not want your script to be public, or you may not have internet access on first boot, etc.)
  • For reference, here is an "autounattend.xml" file that launches a PowerShell script on first boot. (In real life, you would want to integrate the "SynchronousCommand" section into your existing "autounattend.xml" file that automates all of the rest of the Windows setup and so on, which is outside the scope of this tutorial.)
<?xml version="1.0" encoding="utf-8"?>
<unattend xmlns="urn:schemas-microsoft-com:unattend">
	<settings pass="oobeSystem">
		<component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
			<FirstLogonCommands>
				<!--
					The PowerShell script will take a long time to execute,
					but for some reason, Windows will not wait for it to complete,
					and will instead boot as normal. The PowerShell window will be
					visible and will continue to run.
				-->
				<SynchronousCommand wcm:action="add">
					<Order>100</Order>
					<Description></Description>
					<CommandLine>powershell -ExecutionPolicy Unrestricted "C:\Windows\Setup\Scripts\install-winget.ps1"</CommandLine>
				</SynchronousCommand>
			</FirstLogonCommands>
		</component>
	</settings>
</unattend>

install-winget.ps1:

# Install winget
Add-AppxPackage "C:\Windows\Setup\Scripts\winget\Microsoft.VCLibs.x64.14.00.Desktop.appx"
Add-AppxProvisionedPackage -Online -PackagePath "C:\Windows\Setup\Scripts\winget\Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.msixbundle" -LicensePath "C:\Windows\Setup\Scripts\winget\9c0fe2ce7f8e410eb4a8f417de74517e_License1.xml"

# Sleep for 5 seconds to let winget get into the path because the installer is a buggy mess
# If this does not work, try restarting the entire computer and installing the subsequent software on the next boot
Start-Sleep -s 5

# Install software
winget install --accept-source-agreements --silent --exact --id "Microsoft.VisualStudioCode"
winget install --accept-source-agreements --silent --exact --id "Notepad++.Notepad++"
winget install --accept-source-agreements --silent --exact --id "Git.Git"
@Zamiell Zamiell added the Issue-Docs It's a documentation issue that really should be on MicrosoftDocs label Dec 7, 2021
@ghost ghost added the Needs-Triage Issue need to be triaged label Dec 7, 2021
@o-l-a-v
Copy link

o-l-a-v commented Dec 7, 2021

Running from system context, what will be the difference of installing the msixbundle using Add-AppxPackage vs. Add-AppxProvisionedPackage?

I'm looking into doing this from Intune with a Win32 package. Thought following would be sufficient.

"%SystemRoot%\sysnative\WindowsPowerShell\v1.0\powershell.exe" -ExecutionPolicy "Bypass" -NoLogo -NonInteractive -NoProfile -WindowStyle "Hidden" -Command "$null = Add-AppxPackage -Path ".\Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.msixbundle""

Alternatively if needed, install command will be

"%SystemRoot%\sysnative\WindowsPowerShell\v1.0\powershell.exe" -ExecutionPolicy "Bypass" -NoLogo -NonInteractive -NoProfile -WindowStyle "Hidden" -Command "$null = Add-AppxProvisionedPackage -Online -PackagePath ".\Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.msixbundle" -LicensePath ".\9c0fe2ce7f8e410eb4a8f417de74517e_License1""

Edit: Seems first is for user context, while 2nd is system context.

Edit2: Ended up downloading msixbundle and license xml from this GitHub repo release section. And dependencies as appx from https://store.rg-adguard.net/. With following install script wrapped in *.intunewin.

Click to view
#Requires -RunAsAdministrator
#Requires -Version 5.1
<#
    .SYNOPSIS
        Installs Microsoft App Installer if version included with this script is newer than the one installed.

    .NOTES
        Author:   Olav Rønnestad Birkeland
        Created:  211207
        Modified: 211207

    .EXAMPLE
        & $psISE.CurrentFile.FullPath; $LASTEXITCODE
#>


# Input parameters
[OutputType($null)]
Param()


# PowerShell preferences
$ErrorActionPreference = 'Stop'
$InformationPreference = 'Continue'
$ProgressPreference    = 'SilentlyContinue'


# Assets
$RequiredVersion  = [System.Version] '1.16.12653.0'
$InstalledVersion = [System.Version](
    Get-AppxPackage -Name 'Microsoft.DesktopAppInstaller' -AllUsers | Sort-Object -Property 'Version' -Descending | Select-Object -First 1 -ExpandProperty 'Version'
)
$MsixBundlePath    = [string]((Get-ChildItem -Path $PSScriptRoot -Filter '*.msixbundle' -File).'FullName')
$LicensePath       = [string]((Get-ChildItem -Path $PSScriptRoot -Filter '*.xml' -File).'FullName')
$DependenciesPaths = [string[]]((Get-ChildItem -Path $PSScriptRoot -Filter '*.appx' -File).'FullName')


# Write information
Write-Information -MessageData (
    [PSCustomObject]@{
        'RequiredVersion'  = [string] $RequiredVersion
        'InstalledVersion' = [string] $InstalledVersion
        'MsixBundlePath'   = [string] $MsixBundlePath
        'LicensePath'      = [string] $LicensePath
        'DependeciesPaths' = [string] ($DependenciesPaths -join ';')
    } | Format-List | Out-String
).Trim()


# Failproof
if ([string]::IsNullOrEmpty($MsixBundlePath)) {
    Throw 'Did not find the *.msixbundle file.'
}
if (-not [System.IO.File]::Exists($MsixBundlePath)) {
    Throw ('Path "{0}" does not exist.' -f $MsixBundlePath)
}


# Install
if ($InstalledVersion -lt $RequiredVersion) {
    Write-Information -MessageData ('Installing v{0} from "{1}".' -f $RequiredVersion, $MsixBundlePath)
    Add-AppxProvisionedPackage -Online -PackagePath $MsixBundlePath -LicensePath $LicensePath -DependencyPackagePath $DependenciesPaths
}
else {
    Write-Information -MessageData ('Same or newer version is already installed.')
}


# Exit
Write-Output -InputObject 'Done.'
Exit 0

@Zamiell
Copy link
Author

Zamiell commented Dec 7, 2021

Edit: Seems first is for user context, while 2nd is system context.

Good question.

  • I'm not sure if installing VCLibs as user context or system context changes anything. If so, it should be documented.
  • I'm not sure if installing winget as user context or system context changes anything. If so, it should be documented.

For now, I've added this information to the tutorial and assumed that the user wants to install both of them in a system context.

@mariobrostech
Copy link

Hi, thanks for taking the time to write such a detailed post on this! I've run into this issue in the past, and when I did, I opted to integrate winget directly into the Windows install image using DISM and the Windows 10 ADK to re-pack my changes into an updated ISO file. You can read the thread that explains how I did this here.

To clarify a few things:

  • winget supports Windows 10, version 1809 or later. This means that it's compatible with LTSC 2019 (build 1809) and LTSC 2021 (build 21H2). It isn't compatible with earlier versions of LTSC because of this requirement.
  • If you're more interested in using DISM customize and deploy Windows images, I recommend reading this article from TenForums here. Although this article focuses more on injecting drivers into the install image, you can use the Add-ProvisionedAppxPackage command I detailed in my GitHub Discussions post in place of these commands, and you can use the guide to help you package everything into an ISO for deployment.

I hope that can help you out! Ultimately, I do think that the documentation could be improved, but I also think that the real issue here is that Windows 10 LTSC doesn't include the App Installer package by default. This would make it much easier to install winget. Just double-click on the msixbundle file, and you're done! This is unlikely, though, so I agree that more documentation on this would be welcome (or, potentially even packaging winget as an executable binary for systems where the Microsoft Store is disabled/uninstalled).

@Zamiell
Copy link
Author

Zamiell commented Dec 7, 2021

Thanks, that is good info.

winget supports Windows 10, version 1809 or later. This means that it's compatible with LTSC 2019 (build 1809) and LTSC 2021 (build 21H2). It isn't compatible with earlier versions of LTSC because of this requirement.

I put this in the OP.

If you're more interested in using DISM customize and deploy Windows images

I did not consider integrating winget into the Windows source itself, but that is smart and I imagine that some people would want to do that.

After thinking about this a little more, I feel like in the context of "automatically installing extra software on first Windows boot", integrating winget into the source doesn't seem to get you much. I think that you (probably?) can't (or shouldn't) integrate all of the software that you want to install into the source (e.g. for me I need Visual Studio Code, Notepad++, NodeJS, Git). So, since you are going to have a post-installation script anyway, it seems like you might as well install winget at that point to keep the installation source more vanilla.

@mariobrostech
Copy link

Thanks for the feedback!

For my use case, my list of packages changes depending on which system I'm installing Windows on. For that reason, while I want winget preinstalled on all of my machines, I don't want the same set of packages shared between them, so I instead opt to use the winget export -o command to get a list of installed packages and then winget import -i to import the list of packages on each machine. For a fully automated deployment, I agree that this wouldn't make sense, but for a setup like mine, this is why I prefer integrating winget directly into the Windows image itself.

@Zamiell
Copy link
Author

Zamiell commented Dec 8, 2021

since you are going to have a post-installation script anyway, it seems like you might as well install winget at that point to keep the installation source more vanilla.

I rescind my previous statement. After another 24 hours of playing with winget in post-installation scripts, I cannot get winget to function in a reliable way. Sometimes, computers must be restarted entirely for winget to start appearing in the path.

Thus, I have opted to integrate winget into the source using dism, which seems to be a very reliable solution. I'll update the OP accordingly.

@mariobrostech
Copy link

Awesome, I'm glad you found that helpful!

@denelon
Copy link
Contributor

denelon commented Dec 8, 2021

Similar to Windows Server 2022, the Windows Package Manager should be considered experimental only on Windows 10 LTSC 1809 and 21H2. These would still not be officially supported, but they may be possible with released versions of the Windows Package Manager. We're still working through the dependencies and other long term support implications.

@denelon denelon removed the Needs-Triage Issue need to be triaged label Dec 8, 2021
@mariobrostech
Copy link

Similar to Windows Server 2022, the Windows Package Manager should be considered experimental only on Windows 10 LTSC 1809 and 21H2. These would still not be officially supported, but they may be possible with released versions of the Windows Package Manager. We're still working through the dependencies and other long term support implications.

This is unfortunate, albeit expected. UWP apps in general aren't very well supported in Windows 10 LTSC versions as-is, let alone updating them. Has your team considered an approach similar to the one that PowerShell 7 has taken where updates can be handled via Microsoft Update, which works on both LTSC 2019 and 2021? This way, you could distribute an installation package for those who wish to install winget on their Windows 10 Server/LTSC systems, and any updates could be handled either manually or via Microsoft Update.

I know this is probably a pretty sizable undertaking, but if it means having official support for Server/LTSC, it might be something to consider. What are your thoughts?

@denelon
Copy link
Contributor

denelon commented Dec 13, 2021

@mariobrostech we're looking at all of our options here. Unfortunately, you are correct regarding UWP apps on Windows 10 LTSC versions. Anything we add to LTSC versions has a very long engineering support tail. We also need to ensure all other teams agree to take on the additional risk and expense of supporting any additions. Taking the Windows Package Manager down to Windows 10 (1809) was already a large undertaking. Supporting LTSC and Server OS SKUs was not approved based on our 1.0 release date. We have been looking at the next release cycles and working with other teams to understand the total impact and cost for becoming supported on those platforms. If this changes, we will certainly share the exciting news.

@Shilionz
Copy link

There may be another way for installing winget package on Windows LTSC.
My system version is 19044.1415 LTSC.
Firstly, find the URL of the app installer page on Microsoft Store. This can be done by googling "App Installer Microsoft store". And the URL is https://www.microsoft.com/en-us/p/app-installer/9nblggh4nns1.
Secondly, type the URL into Online link generator for Microsoft store (https://store.rg-adguard.net/). Download all the dependency package for targeted machine platform (e.g. x86, x64).
Thirdly, install download package using Windows Powershell (using Powershell 7 may suffer some issue). Note that you need to install VCLibs UWPDesktop firstly.
Add-AppxPackage [package-path]

Finally you can use winget in command line. Or double clicking msix package to install them directly. This will work even after restarting the system.
Wish this comment is helpful.

@microsoft microsoft locked and limited conversation to collaborators Feb 18, 2022
@denelon denelon converted this issue into discussion #1956 Feb 18, 2022
@denelon denelon added this to the v1.3-Client milestone Jun 21, 2022

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

Labels
Issue-Docs It's a documentation issue that really should be on MicrosoftDocs
Projects
None yet
Development

No branches or pull requests

5 participants