Font size: +
5 minutes reading time (901 words)

Winget on Server 2019

MAD_MSIX_1024

As I wrote in the blog "Winget on Server 2022", there is a reason why we can't use Winget.exe with Server 2019. Winget is started from the command line and support for it is missing in Server 2019. The situation has changed and we have a solution.
Winget, similar to "aptget" on Linux, allows a significant number of Applications can be installed with simple commands from the command line. A description of Winget can be found here: 

https://docs.microsoft.com/en-us/windows/package-manager/winget/

The Winget installation package Winget is a part of the AppInstaller package with which AppX and MSIX packages can be installed at the click of a button. In the Microsoft Store you can find the package can be found here (pay attention to the release here, possibly use Insider): 

https://www.microsoft.com/de-de/p/app-installer/9nblggh4nns1#activetab=pivot:overviewtab

Furthermore you can find the package Windows Package Manager in the GitHub repository. Manager, which can be installed manually and also includes Winget:

https://github.com/microsoft/winget-cli/releases/tag/v1.1.12653

This is all a bit confusing from a purely linguistic point of view. The key thing is that we need an easy command line tool that we can use to automatically install applications from many manufacturers in an automated way. It would now of course be nice to use this Tool, also for Server 2019 to be able to use. 

My friend Thorsten Butz (you can also find a session of PSUGH there as a recording) figured out two things:

  1. How to manually create shortcuts for the command line. Now the PowerShell module "NTObjectManager" can do that as well.
  2. How the download of dependent application components can be greatly simplified. can be. Some dependencies can be found apparently "https://aka.ms/xyz.appx". Unfortunately, as things stand, not everything can be found.

Thorsten Butz has shown, among other things, in his presentation, how to get the link (Den Repse Point) can be displayed:

Fsutil.exe reparsepoint Query "$home\AppData\Local\Microsoft\WindowsApps\winget.exe" 

Some PowerShell 7 versions before what was also possible to display the this data directly in the PowerShell to let indicate. However, there were apparently problems with the Performance. Therefore, Microsoft has removed this feature. In this view you could you could see that in reality with the, rebase point to a directory under c:\Program Files\WindowsApps.... is referenced.

With the information obtained, an installation script can be created that will Winget can deploy to Server 2019 as well.

About the script

Installation can be done offline if the package files are available offline on the target system. on the target system. The path to the directory containing the installation files is defined in the "RepoPath" variable and can be customized in the source code.

$RepoPath = "$env:TEMP\WinGetTemp"

The download can be done on a system with internet access, for example.

Now the line "$Offline = $false must also be set to $true. The Files must be recognized and present in the repo directory. Offline it only works because Microsoft provides a license file on Github. This with a parameter to the function Add-AppxProvisionedPackage and the license file must License file must be present in the repo directory.

The script absolutely requires the PowerShell module 'NTObjectManager'. If this module is not installed, the script will try to install this module itself. itself. Needed is the module for the rebase point on Winget.exe.

The execution of the script must be as administrator. Otherwise the rebase point on Winget.exe cannot be created.

# WinGet Version Installation Scrip for Server 2019
# Work with Version 1.2.10271 or internal Version="1.17.10271.0"
# Or Bundle Version="2022.127.2322.0" 
# Andreas Nick 2022

Write-Host "Download and install winget" -ForegroundColor Yellow

if(!(Get-Module -ListAvailable -Name 'NTObjectManager')){
    Install-Module  'NTObjectManager' -scope CurrentUser -Force -Confirm:$false
    
} 

Import-Module  'NTObjectManager'

$Offline = $false 
$RepoPath = "$env:TEMP\WinGetTemp"
$BaseURL = 'https://www.microsoft.com/store/productId/9NBLGGH4NNS1'
$DownloadFiles = @( 'Microsoft.DesktopAppInstaller_2022.127.2322.0_neutral_~_8wekyb3d8bbwe.msixbundle',
                     'Microsoft.VCLibs.140.00.UWPDesktop_14.0.30704.0_x64__8wekyb3d8bbwe.appx',
                     'Microsoft.UI.Xaml.2.7_7.2203.17001.0_x64__8wekyb3d8bbwe.appx')

# Version 1.2.10271 !!
$LicenseFileURL = 'https://github.com/microsoft/winget-cli/releases/download/v1.2.10271/b0a0692da1034339b76dce1c298a1e42_License1.xml'

if(Test-Path $RepoPath   ) 
{
   #Remove-Item $RepoPath -Recurse 
} else {
    New-Item $RepoPath -ItemType Directory
}

function Get-AppXPackageURL {
[CmdletBinding()]
param (
  [string]$Uri,
  [string]$Filter = '.*' #Regex
)
   
  process {
    #$Uri=$StoreLink
    $WebResponse = Invoke-WebRequest -UseBasicParsing -Method 'POST' -Uri 'https://store.rg-adguard.net/api/GetFiles' -Body "type=url&url=$Uri&ring=Retail" -ContentType 'application/x-www-form-urlencoded'
    $result =$WebResponse.Links.outerHtml | Where-Object {($_ -like '*.appx*') -or ($_ -like '*.msix*')} | Where-Object {$_ -like '*_neutral_*' -or $_ -like "*_"+$env:PROCESSOR_ARCHITECTURE.Replace("AMD","X").Replace("IA","X")+"_*"} | ForEach-Object {
       $result = "" | Select-Object -Property filename, downloadurl
       if( $_ -match '(?<=rel="noreferrer">).+(?=</a>)' )
       {
         $result.filename = $matches.Values[0]
       }
       if( $_ -match '(?<=a href=").+(?=" r)' )
       {
         $result.downloadurl = $matches.Values[0]
       }
       $result
    } 
    $result | Where-Object -Property filename -Match $filter 
  }
}


#Download Winget 2022.127.2322.0 and Dependencies
$Packlist = @()
if(-not $Offline){
  $Packlist = @(Get-AppXPackageURL -Uri $BaseURL)
  #Download License file
  Invoke-WebRequest -Uri $LicenseFileURL -OutFile (Join-Path $RepoPath -ChildPath 'license.xml' )

  #Download package files
  foreach($item in $DownloadFiles)
  {
    if(-not (Test-Path (Join-Path $RepoPath  -ChildPath $item )))
    {
       $dlurl = [string]($Packlist | Where-Object -Property filename -match $item)[0].downloadurl
       Invoke-WebRequest -Uri  $dlurl -OutFile (Join-Path $RepoPath -ChildPath $item )
    } else 
    {
        Write-Information "The file $($item) already exist in the repo. Skip download"
    }
  }

}

#Install Winget without license
#Add-AppxPackage -Path $(Join-Path $RepoPath -ChildPath  $DownloadFiles[0]) -DependencyPath  $(Join-Path $RepoPath -ChildPath  $DownloadFiles[1]), $(Join-Path $RepoPath -ChildPath  $DownloadFiles[2]) 
#Get-AppxPackage Microsoft.DesktopAppInstaller | Remove-AppxPackage

#Install Winget with license
Add-AppxProvisionedPackage -PackagePath $(Join-Path $RepoPath -ChildPath  $DownloadFiles[0]) -LicensePath $(Join-Path $RepoPath -ChildPath 'license.xml') -online `
                           -DependencyPackagePath $(Join-Path $RepoPath -ChildPath  $DownloadFiles[1]), $(Join-Path $RepoPath -ChildPath  $DownloadFiles[2])  


# Here is the trick of Thorsten Butz. We create a rebase point ourselves
# The alias can be defined somewhere in the $Temp:Path. For example, in C:\Windows\System32
Set-ExecutionAlias -Path "$env:windir\winget.exe" -Target $((Get-AppxPackage *DesktopAppInstaller*).InstallLocation + '\winget.exe') -PackageName `
                  'Microsoft.DesktopAppInstaller_8wekyb3d8bbwe' -AppType Desktop -EntryPoint 'Microsoft.DesktopAppInstaller_8wekyb3d8bbwe!winget' -Version 3

#Get-ExecutionAlias  'c:\windows\winget.exe'
#Remove-Item  'c:\windows\winget.exe'
#'Microsoft.DesktopAppInstaller_8wekyb3d8bbwe' 
×
Stay Informed

When you subscribe to the blog, we will send you an e-mail when there are new updates on the site so you wouldn't miss them.

No, App-V is not EOL in April 2026
Install WinGet and AppInstaller on Windows Server ...

Related Posts

 

Comments 6

Guest - Robert Glöckner on Saturday, February 18, 2023 18:34

Danke für das Skript! mittlerweile gibt es zu den Downloadfiles neuere Versionen:

$DownloadFiles = @( 'Microsoft.DesktopAppInstaller_2023.118.406.0_neutral_~_8wekyb3d8bbwe.msixbundle',
'Microsoft.VCLibs.140.00.UWPDesktop_14.0.30704.0_x64__8wekyb3d8bbwe.appx',
'Microsoft.UI.Xaml.2.7_7.2208.15002.0_x64__8wekyb3d8bbwe.appx'
)

Danke für das Skript! mittlerweile gibt es zu den Downloadfiles neuere Versionen: $DownloadFiles = @( 'Microsoft.DesktopAppInstaller_2023.118.406.0_neutral_~_8wekyb3d8bbwe.msixbundle', 'Microsoft.VCLibs.140.00.UWPDesktop_14.0.30704.0_x64__8wekyb3d8bbwe.appx', 'Microsoft.UI.Xaml.2.7_7.2208.15002.0_x64__8wekyb3d8bbwe.appx' )
Andreas Nick on Thursday, March 30, 2023 13:18

Danke

Danke
Guest - Henk the Hunter on Thursday, February 09, 2023 16:03

The script doesnt work for me? Can you explain why its not working for me?

Cannot index into a null array.
At C:\Users\sa_vda\Desktop\winget script.ps1:71 char:8
+ $dlurl = [string]($Packlist | Where-Object -Property filename ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: ( [], RuntimeException
+ FullyQualifiedErrorId : NullArray

Invoke-WebRequest : Cannot validate argument on parameter 'Uri'. The argument is null or empty. Provide an argument tha
t is not null or empty, and then try the command again.
At C:\Users\sa_vda\Desktop\winget script.ps1:72 char:32
+ Invoke-WebRequest -Uri $dlurl -OutFile (Join-Path $RepoPath - ...
+ ~~~~~~
+ CategoryInfo : InvalidData: ( [Invoke-WebRequest], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.PowerShell.Commands.InvokeWebRequestCommand

Cannot index into a null array.
At C:\Users\sa_vda\Desktop\winget script.ps1:71 char:8
+ $dlurl = [string]($Packlist | Where-Object -Property filename ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: ( [], RuntimeException
+ FullyQualifiedErrorId : NullArray

Add-AppxProvisionedPackage : De parameter is onjuist.
At C:\Users\sa_vda\Desktop\winget script.ps1:86 char:1
+ Add-AppxProvisionedPackage -PackagePath $(Join-Path $RepoPath -ChildP ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: ( [Add-AppxProvisionedPackage], PSArgumentException
+ FullyQualifiedErrorId : Microsoft.Dism.Commands.AddAppxProvisionedPackageCommand

The script doesnt work for me? Can you explain why its not working for me? Cannot index into a null array. At C:\Users\sa_vda\Desktop\winget script.ps1:71 char:8 + $dlurl = [string]($Packlist | Where-Object -Property filename ... + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidOperation: (:) [], RuntimeException + FullyQualifiedErrorId : NullArray Invoke-WebRequest : Cannot validate argument on parameter 'Uri'. The argument is null or empty. Provide an argument tha t is not null or empty, and then try the command again. At C:\Users\sa_vda\Desktop\winget script.ps1:72 char:32 + Invoke-WebRequest -Uri $dlurl -OutFile (Join-Path $RepoPath - ... + ~~~~~~ + CategoryInfo : InvalidData: (:) [Invoke-WebRequest], ParameterBindingValidationException + FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.PowerShell.Commands.InvokeWebRequestCommand Cannot index into a null array. At C:\Users\sa_vda\Desktop\winget script.ps1:71 char:8 + $dlurl = [string]($Packlist | Where-Object -Property filename ... + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidOperation: (:) [], RuntimeException + FullyQualifiedErrorId : NullArray Add-AppxProvisionedPackage : De parameter is onjuist. At C:\Users\sa_vda\Desktop\winget script.ps1:86 char:1 + Add-AppxProvisionedPackage -PackagePath $(Join-Path $RepoPath -ChildP ... + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : NotSpecified: (:) [Add-AppxProvisionedPackage], PSArgumentException + FullyQualifiedErrorId : Microsoft.Dism.Commands.AddAppxProvisionedPackageCommand
Andreas Nick on Thursday, March 30, 2023 13:21

The element "$Packlist" appears to be empty. Perhaps no data came over the Internet or something has changed at Microsoft.

The element "$Packlist" appears to be empty. Perhaps no data came over the Internet or something has changed at Microsoft.
Guest - Thomas Rauner on Friday, January 27, 2023 12:18

Hi Andreas,
could yoe be so kind to append a list to your posting which privides the exact files and download locations, which I habe to dump to $RepoPath before starting the script above. I cannot figure which of the download links are informational or essential for the script to succeed.
Thank you in advance, Thomas

Hi Andreas, could yoe be so kind to append a list to your posting which privides the exact files and download locations, which I habe to dump to $RepoPath before starting the script above. I cannot figure which of the download links are informational or essential for the script to succeed. Thank you in advance, Thomas
Andreas Nick on Thursday, March 30, 2023 13:23

Sorry for the late reply. The notification system was defective. Nothing has to be deposited but the following block is probably no longer up to date (see above)

$DownloadFiles = @( 'Microsoft.DesktopAppInstaller_2022.127.2322.0_neutral_~_8wekyb3d8bbwe.msixbundle',
'Microsoft.VCLibs.140.00.UWPDesktop_14.0.30704.0_x64__8wekyb3d8bbwe.appx',
'Microsoft.UI.Xaml.2.7_7.2203.17001.0_x64__8wekyb3d8bbwe.appx')

Sorry for the late reply. The notification system was defective. Nothing has to be deposited but the following block is probably no longer up to date (see above) $DownloadFiles = @( 'Microsoft.DesktopAppInstaller_2022.127.2322.0_neutral_~_8wekyb3d8bbwe.msixbundle', 'Microsoft.VCLibs.140.00.UWPDesktop_14.0.30704.0_x64__8wekyb3d8bbwe.appx', 'Microsoft.UI.Xaml.2.7_7.2203.17001.0_x64__8wekyb3d8bbwe.appx')
Already Registered? Login Here
Friday, March 29, 2024

Captcha Image

@nickinformation Tweets

My german Blog: 

http://www.software-virtualisierung.de

in 

We use cookies on our website. Some of them are essential for the operation of the site, while others help us to improve this site and the user experience (tracking cookies). You can decide for yourself whether you want to allow cookies or not. Please note that if you reject them, you may not be able to use all the functionalities of the site.