microsoft / winget-cli

WinGet is the Windows Package Manager. This project includes a CLI (Command Line Interface), PowerShell modules, and a COM (Component Object Model) API (Application Programming Interface).
https://learn.microsoft.com/windows/package-manager/
MIT License
23.08k stars 1.44k forks source link

Installing winget with docker #3037

Closed helmesjo closed 4 months ago

helmesjo commented 1 year ago

Brief description of your issue

I've read through a bunch of similar issues but either the suggestions don't work (any more) or when I do get winget.exe into the container it would just not do anything (winget.exe --version just exited with 0 instantly without any output, similar for any other command).

Feels like such an essential thing to be able to easily install winget.exe in various environments so this should really 1. "just work" and 2. have clear instructions for how to do it (docker is widely used so one example explicitly for this feels necessary).

Thanks.

stephengillie commented 1 year ago

Hi @helmesjo,

The command winget --version should output the current version:

PS C:\ManVal> winget --version
v1.4.10173

What does winget --info provide?

This is within a Docker container -- which OS is it running? How is the WinGet application called - directly, in script, or another way? Is this in an interactive session with the container, or is it through automated operation?

denelon commented 1 year ago

Due to the way winget is installed via MSIX via the App Installer package, I see a couple of challenges. The first is depending on the Windows SKU, WinGet might not be registered. This generally happens a few minutes (15-ish) after the OS is logged into, the Microsoft Store will check for an upgrade, download it and then register it. It may be registered via PowerShell. The second is WinGet is not available in the System context.

There are workarounds to both of these.

This may work, but is not officially supported:

helmesjo commented 1 year ago

Hi @helmesjo,

The command winget --version should output the current version:

PS C:\ManVal> winget --version
v1.4.10173

I mean, yes... (:

What does winget --info provide?

Nothing.

This is within a Docker container -- which OS is it running? How is the WinGet application called - directly, in script, or another way? Is this in an interactive session with the container, or is it through automated operation?

These are the exact commands I run which do not work inside a container (docker run --rm -it <image>, winget.exe --version produces no output), but it does work locally all fine.

Run this in a fresh cmd.exe terminal (cd to some tempdir you've created):

powershell mkdir "./winget-cli"
curl.exe -L https://github.com/microsoft/winget-cli/releases/download/v1.4.10173/Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.msixbundle --output ./winget-cli/winget.zip
powershell -Command "Expand-Archive -LiteralPath ./winget-cli/winget.zip -DestinationPath ./winget-cli -Force"
powershell mv ./winget-cli/AppInstaller_x64.msix ./winget-cli/AppInstaller_x64.zip
powershell -Command "Expand-Archive -LiteralPath ./winget-cli/AppInstaller_x64.zip -DestinationPath ./winget-cli/ -Force"
winget-cli\winget.exe --help

My current dockerfile is exactly this:

FROM mcr.microsoft.com/windows/server:ltsc2022

USER ContainerAdministrator

RUN mkdir "C:\TEMP\winget-cli"
RUN curl.exe -L https://github.com/microsoft/winget-cli/releases/download/v1.4.10173/Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.msixbundle --output C:/TEMP/winget-cli/winget.zip
RUN powershell -Command "Expand-Archive -LiteralPath C:/TEMP/winget-cli/winget.zip -DestinationPath C:/TEMP/winget-cli -Force"
RUN powershell mv C:/TEMP/winget-cli/AppInstaller_x64.msix C:/TEMP/winget-cli/AppInstaller_x64.zip
RUN powershell -Command "Expand-Archive -LiteralPath C:/TEMP/winget-cli/AppInstaller_x64.zip -DestinationPath C:/TEMP/winget-cli/ -Force"
RUN mkdir "C:\winget-cli" && `
  move "C:\TEMP\winget-cli\winget.exe" "C:\winget-cli\winget.exe" && `
  move "C:\TEMP\winget-cli\resources.pri" "C:\winget-cli\"

WORKDIR C:/winget-cli
ENTRYPOINT ["cmd"]
CMD [""]
helmesjo commented 1 year ago

Any update here?

ItzLevvie commented 1 year ago

Have you looked into installing VCRedist 2015 to 2022?

helmesjo commented 1 year ago

No, I can give that a try. What would be the reason? Just for the sake of it, or is it explicitly required?

ItzLevvie commented 1 year ago

It has a dependency on Microsoft Visual C++ 2015-2022: image

With Microsoft Visual C++ 2015-2022 installed on the VM: image

You will also need to extract WindowsPackageManager.dll from AppInstaller_x64.msix for winget.exe to work properly.

jwillikers commented 1 year ago

In case this helps anyone, here's how to do this with Powershell, just be sure to open up a new terminal afterwards for it to be available in PATH. This also extracts WindowsPackageManager.dll.

New-Item -Force -ItemType 'directory' -Name 'winget-cli' -Path 'C:/temp'; `
Invoke-WebRequest 'https://github.com/microsoft/winget-cli/releases/download/v1.4.11071/Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.msixbundle' `
    -OutFile 'C:/temp/winget-cli/winget.zip' -UseBasicParsing; `
Expand-Archive -LiteralPath 'C:/temp/winget-cli/winget.zip' -DestinationPath 'C:/temp/winget-cli' -Force; `
Move-Item -Path 'C:/temp/winget-cli/AppInstaller_x64.msix' -Destination 'C:/temp/winget-cli/AppInstaller_x64.zip'; `
Expand-Archive -LiteralPath 'C:/temp/winget-cli/AppInstaller_x64.zip' -DestinationPath 'C:/temp/winget-cli' -Force; `
New-Item -Force -ItemType 'directory' -Name 'winget-cli' -Path 'C:/'; `
Move-Item -Path 'C:/temp/winget-cli/winget.exe' -Destination 'C:/winget-cli/winget.exe'; `
Move-Item -Path 'C:/temp/winget-cli/WindowsPackageManager.dll' -Destination 'C:/winget-cli/WindowsPackageManager.dll'; `
Move-Item -Path 'C:/temp/winget-cli/resources.pri' -Destination 'C:/winget-cli'; `
[Environment]::SetEnvironmentVariable('PATH', [Environment]::GetEnvironmentVariable('PATH') + ';C:/winget-cli', 'Machine')
Yiwei-Ding commented 4 months ago

Thanks @jwillikers and @ItzLevvie . VCRedist is also required in my case.

Here's my PowerShell:

New-Item -Force -ItemType 'directory' -Name 'winget-cli' -Path 'C:/temp'
Invoke-WebRequest 'https://aka.ms/vs/16/release/vc_redist.x64.exe' -OutFile 'C:/temp/vc_redist.x64.exe' -UseBasicParsing
powershell -c C:/temp/vc_redist.x64.exe /install /quiet /norestart
Invoke-WebRequest 'https://aka.ms/getwinget' -OutFile 'C:/temp/winget-cli/winget.zip' -UseBasicParsing
Expand-Archive -LiteralPath 'C:/temp/winget-cli/winget.zip' -DestinationPath 'C:/temp/winget-cli' -Force
Move-Item -Path 'C:/temp/winget-cli/AppInstaller_x64.msix' -Destination 'C:/temp/winget-cli/AppInstaller_x64.zip'
Expand-Archive -LiteralPath 'C:/temp/winget-cli/AppInstaller_x64.zip' -DestinationPath 'C:/temp/winget-cli' -Force
New-Item -Force -ItemType 'directory' -Name 'winget-cli' -Path 'C:/'
Move-Item -Path 'C:/temp/winget-cli/winget.exe' -Destination 'C:/winget-cli/winget.exe'
Move-Item -Path 'C:/temp/winget-cli/WindowsPackageManager.dll' -Destination 'C:/winget-cli/WindowsPackageManager.dll'
Move-Item -Path 'C:/temp/winget-cli/resources.pri' -Destination 'C:/winget-cli'

[Environment]::SetEnvironmentVariable('PATH', [Environment]::GetEnvironmentVariable('PATH') + ';C:/winget-cli', 'Machine')