Skip to content

Instantly share code, notes, and snippets.

@Foadsf
Created April 10, 2025 12:44
Show Gist options
  • Save Foadsf/68b4ed56782f0bde91e5a5db71e7a945 to your computer and use it in GitHub Desktop.
Save Foadsf/68b4ed56782f0bde91e5a5db71e7a945 to your computer and use it in GitHub Desktop.

Revisions

  1. Foadsf created this gist Apr 10, 2025.
    184 changes: 184 additions & 0 deletions Install-Winget.ps1
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,184 @@
    # Complete Winget Installer for Tiny10/LTSC
    # Run as Administrator
    # Created on: April 10, 2025

    # Ensure we're running with admin rights
    if (-not ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]"Administrator")) {
    Write-Host "This script requires administrative privileges. Please run as Administrator." -ForegroundColor Red
    exit 1
    }

    # Create a temporary directory
    $tempDir = "$env:TEMP\WingetInstall"
    New-Item -ItemType Directory -Force -Path $tempDir | Out-Null
    Set-Location $tempDir

    Write-Host "=== Tiny10 Winget Installer ===" -ForegroundColor Cyan
    Write-Host "Step 1: Installing Visual C++ Redistributable..." -ForegroundColor Cyan

    # Download and install VC++ Redistributable
    $vcRedistUrl = "https://aka.ms/vs/17/release/vc_redist.x64.exe"
    $vcRedistPath = "$tempDir\vc_redist.x64.exe"

    Write-Host "Downloading Visual C++ Redistributable..." -ForegroundColor Yellow
    try {
    Invoke-WebRequest -Uri $vcRedistUrl -OutFile $vcRedistPath -UseBasicParsing
    } catch {
    Write-Host "Failed to download Visual C++ Redistributable. Error: $_" -ForegroundColor Red
    exit 1
    }

    Write-Host "Installing Visual C++ Redistributable..." -ForegroundColor Yellow
    Start-Process -FilePath $vcRedistPath -ArgumentList "/quiet", "/norestart" -Wait

    Write-Host "Step 2: Downloading required files for winget..." -ForegroundColor Cyan

    # URLs for the files
    $wingetUrl = "https://github.com/microsoft/winget-cli/releases/download/v1.10.340/Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.msixbundle"
    $licenseUrl = "https://github.com/microsoft/winget-cli/releases/download/v1.10.340/4df037184d634a28b13051a797a25a16_License1.xml"
    $vclibsUrl = "https://github.com/QuangVNMC/LTSC-Add-Microsoft-Store/raw/master/Microsoft.VCLibs.140.00.UWPDesktop_14.0.33728.0_x64__8wekyb3d8bbwe.Appx"
    $xamlNugetUrl = "https://www.nuget.org/api/v2/package/Microsoft.UI.Xaml/2.7.0"

    # File paths
    $wingetPath = "$tempDir\Microsoft.DesktopAppInstaller.msixbundle"
    $licensePath = "$tempDir\License1.xml"
    $vclibsPath = "$tempDir\Microsoft.VCLibs.140.00.UWPDesktop_14.0.33728.0_x64__8wekyb3d8bbwe.Appx"
    $xamlNugetPath = "$tempDir\Microsoft.UI.Xaml.2.7.0.nuget"
    $xamlZipPath = "$tempDir\Microsoft.UI.Xaml.2.7.0.zip"
    $xamlAppxPath = "$tempDir\Microsoft.UI.Xaml.2.7.appx"

    # Download the files
    Write-Host "Downloading Winget package..." -ForegroundColor Yellow
    try {
    Invoke-WebRequest -Uri $wingetUrl -OutFile $wingetPath -UseBasicParsing
    } catch {
    Write-Host "Failed to download Winget package. Error: $_" -ForegroundColor Red
    exit 1
    }

    Write-Host "Downloading license file..." -ForegroundColor Yellow
    try {
    Invoke-WebRequest -Uri $licenseUrl -OutFile $licensePath -UseBasicParsing
    } catch {
    Write-Host "Failed to download license file. Error: $_" -ForegroundColor Red
    exit 1
    }

    Write-Host "Downloading VCLibs..." -ForegroundColor Yellow
    try {
    Invoke-WebRequest -Uri $vclibsUrl -OutFile $vclibsPath -UseBasicParsing
    } catch {
    Write-Host "Failed to download VCLibs. Error: $_" -ForegroundColor Red
    exit 1
    }

    Write-Host "Downloading Microsoft.UI.Xaml..." -ForegroundColor Yellow
    try {
    Invoke-WebRequest -Uri $xamlNugetUrl -OutFile $xamlNugetPath -UseBasicParsing
    } catch {
    Write-Host "Failed to download Microsoft.UI.Xaml. Error: $_" -ForegroundColor Red
    exit 1
    }

    Write-Host "Step 3: Processing dependencies..." -ForegroundColor Cyan

    # Process the Xaml Nuget package
    Write-Host "Processing Microsoft.UI.Xaml package..." -ForegroundColor Yellow
    Copy-Item $xamlNugetPath $xamlZipPath
    Expand-Archive -Path $xamlZipPath -DestinationPath "$tempDir\xaml" -Force
    Copy-Item "$tempDir\xaml\tools\AppX\x64\Release\Microsoft.UI.Xaml.2.7.appx" $xamlAppxPath

    # Install the dependencies
    Write-Host "Step 4: Installing dependencies..." -ForegroundColor Cyan

    Write-Host "Installing VCLibs..." -ForegroundColor Yellow
    try {
    Add-AppxPackage -Path $vclibsPath
    } catch {
    Write-Host "Failed to install VCLibs. Error: $_" -ForegroundColor Red
    exit 1
    }

    Write-Host "Installing Microsoft.UI.Xaml..." -ForegroundColor Yellow
    try {
    Add-AppxPackage -Path $xamlAppxPath
    } catch {
    Write-Host "Failed to install Microsoft.UI.Xaml. Error: $_" -ForegroundColor Red
    exit 1
    }

    # Install Winget with license
    Write-Host "Step 5: Installing Winget..." -ForegroundColor Cyan
    try {
    Add-AppxProvisionedPackage -Online -PackagePath $wingetPath -LicensePath $licensePath -Verbose
    } catch {
    Write-Host "Failed to install Winget. Error: $_" -ForegroundColor Red
    exit 1
    }

    Write-Host "Step 6: Setting up system access..." -ForegroundColor Cyan

    # Create a directory for symlinks if it doesn't exist
    $symlinksDir = "$env:SystemDrive\Tools"
    if (!(Test-Path $symlinksDir)) {
    New-Item -ItemType Directory -Path $symlinksDir -Force | Out-Null
    }

    # Find the actual winget.exe path
    $wingetExePath = (Get-ChildItem -Path "$env:ProgramFiles\WindowsApps\Microsoft.DesktopAppInstaller*" -Recurse -Filter "winget.exe" -ErrorAction SilentlyContinue | Select-Object -First 1 -ExpandProperty FullName)

    if (-not $wingetExePath) {
    Write-Host "Could not find winget.exe in WindowsApps directory." -ForegroundColor Red
    exit 1
    }

    Write-Host "Found winget at: $wingetExePath" -ForegroundColor Green

    # Create a batch file wrapper for winget in an accessible location
    $batchPath = "$symlinksDir\winget.bat"
    @"
    @echo off
    "$wingetExePath" %*
    "@ | Out-File -FilePath $batchPath -Encoding ASCII -Force

    Write-Host "Created batch wrapper at: $batchPath" -ForegroundColor Green

    # Add the Tools directory to the PATH if not already present
    $currentPath = [Environment]::GetEnvironmentVariable("PATH", "Machine")
    if ($currentPath -notlike "*$symlinksDir*") {
    [Environment]::SetEnvironmentVariable("PATH", "$currentPath;$symlinksDir", "Machine")
    Write-Host "Added $symlinksDir to system PATH" -ForegroundColor Green
    } else {
    Write-Host "$symlinksDir is already in system PATH" -ForegroundColor Yellow
    }

    # Temporarily add to current session PATH
    $env:PATH = "$env:PATH;$symlinksDir"

    # Try to set permissions for current user to access winget directly
    try {
    # Get the parent directory of winget.exe
    $wingetDir = Split-Path -Parent $wingetExePath

    # Add read & execute permissions for current user
    $acl = Get-Acl $wingetDir
    $currentUser = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name
    $accessRule = New-Object System.Security.AccessControl.FileSystemAccessRule($currentUser, "ReadAndExecute", "ContainerInherit,ObjectInherit", "None", "Allow")
    $acl.AddAccessRule($accessRule)
    Set-Acl $wingetDir $acl
    Write-Host "Added permissions for current user to access winget directly" -ForegroundColor Green
    } catch {
    Write-Host "Could not set permissions for direct access to winget.exe. The batch wrapper will still work." -ForegroundColor Yellow
    }

    # Clean up
    Write-Host "Step 7: Cleaning up..." -ForegroundColor Cyan
    Set-Location $env:USERPROFILE
    Remove-Item -Path $tempDir -Recurse -Force -ErrorAction SilentlyContinue

    Write-Host "`n=== Installation Complete ===" -ForegroundColor Green
    Write-Host "The winget command is now available through:" -ForegroundColor Cyan
    Write-Host "1. The batch file: $batchPath" -ForegroundColor Cyan
    Write-Host "2. Simply typing 'winget' in a new command prompt or PowerShell session" -ForegroundColor Cyan
    Write-Host "`nPlease restart your command prompt or PowerShell window to start using winget." -ForegroundColor Yellow
    Write-Host "To test, open a new window and type: winget --version" -ForegroundColor Yellow
    48 changes: 48 additions & 0 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,48 @@
    # Installing Winget on Tiny10 (Windows 10 Lite)

    This repository provides a PowerShell script to install the Windows Package Manager (winget) on Tiny10 or other lightweight Windows 10 distributions where it's not pre-installed.

    ## The Problem

    When trying to install winget on Tiny10, users often encounter the following issues:
    - "No applicable app licenses found" error after installing the basic components
    - Missing dependencies (VCLibs, UI.Xaml)
    - Missing runtime components (VCRUNTIME140.dll)
    - Access and PATH issues with the WindowsApps folder

    ## The Solution

    The `Install-Winget.ps1` script automates the entire installation process:

    1. Installs Visual C++ Redistributable (for VCRUNTIME140.dll)
    2. Downloads all required dependencies:
    - Microsoft.DesktopAppInstaller package
    - License XML file (critical for proper installation)
    - Microsoft.VCLibs UWP package
    - Microsoft.UI.Xaml package
    3. Properly installs winget with its license file
    4. Creates an accessible batch wrapper in C:\Tools
    5. Updates PATH settings for easy access

    ## Usage

    1. Download the script
    2. Open PowerShell as Administrator
    3. Run:
    ```powershell
    powershell -ExecutionPolicy Bypass -File "C:\path\to\Install-Winget.ps1"
    ```
    4. Restart your terminal
    5. Verify installation with `winget --version`

    ## Requirements

    - Windows 10 (Tiny10 or similar lightweight distribution)
    - Administrator privileges
    - Internet connection

    ## Notes

    - This script is specifically designed for Tiny10 and similar lightweight Windows distributions
    - The installation process doesn't require Microsoft Store
    - The installed winget will not receive automatic updates