Winget es el administrador de paquetes de Windows: una orden en la consola que busca, instala, actualiza y desinstala programas sin abrir un navegador ni pulsar «Siguiente». Esta guía explica qué es, cómo instalar winget si no aparece, qué comandos se usan a diario, cómo sacarle partido desde PowerShell con el módulo oficial y qué hacer cuando winget no se reconoce. Además, lo que no sale de la documentación lo medimos el 30 de octubre de 2026 en un Windows 11 Pro 26H2, sin permisos de administrador, con Windows PowerShell 5.1 y con PowerShell 7.6.9.
La guía tiene dos niveles. Si solo quiere instalar y actualizar programas, lea los apartados de instalación y comandos. En cambio, si administra equipos o quiere automatizar, siga hasta el módulo de PowerShell, los fijados, los escenarios y los errores. Para un primer contacto con la consola, antes conviene leer nuestra guía de PowerShell.
Qué es winget
Winget es el cliente de línea de comandos del Administrador de paquetes de Windows (Windows Package Manager). Según la documentación de Microsoft, llega con el Instalador de aplicaciones (App Installer), un componente del sistema que se actualiza desde Microsoft Store. Por eso no suele hacer falta instalarlo: ya viene con Windows 11 y con las versiones modernas de Windows 10.
Por otra parte, winget no guarda los programas. Consulta un catálogo con la descripción de cada paquete, descarga el instalador del fabricante, comprueba su huella y lo ejecuta. De hecho, durante la prueba lo vimos en cada instalación: «Successfully verified installer hash». También avisa de algo que conviene recordar: «This application is licensed to you by its owner. Microsoft is not responsible for, nor does it grant any licenses to, third-party packages.»
Esto es lo que encontramos en el equipo de prueba:
| Dato | Valor medido |
|---|---|
| Versión de winget | v1.29.380, del 21 de septiembre de 2026 |
| Versiones estables en los últimos 12 meses | 8, según las publicaciones del proyecto en GitHub |
| Orígenes | msstore, winget y winget-font (este último, solo si se pide) |
| Programas instalados que ve | 146 identificadores distintos |
| Idioma de los mensajes | Inglés, con Windows en español (es-MX) |
Winget y PowerShell: dos formas de usarlo
Hay dos maneras de manejarlo desde PowerShell, y la diferencia importa en cuanto se escribe un script:
winget.exe | Módulo Microsoft.WinGet.Client | |
|---|---|---|
| Qué es | Programa de consola | Módulo oficial de PowerShell |
| Viene con Windows | Sí | No, se instala aparte |
| Qué devuelve | Texto | Objetos con propiedades |
| Cómo se sabe si funcionó | $LASTEXITCODE | Propiedad Status del resultado |
| Dónde sirve mejor | Trabajo a mano | Scripts e informes |
Para qué sirve winget: usos y beneficios
Instalar un programa a mano en un equipo es fácil. Sin embargo, hacerlo en veinte, mantenerlos al día y saber qué tiene cada uno ya no lo es. Ahí es donde winget ahorra tiempo:
- Preparar equipos nuevos: la misma lista de programas, instalada sin asistentes.
- Actualizar: ver de una vez qué programas tienen versión nueva y actualizarlos.
- Inventario: qué hay instalado, en qué versión y cuál se quedó atrás.
- Controlar versiones: fijar un programa para que una actualización general no lo toque.
- Trabajar sin conexión: descargar el instalador en un equipo y llevarlo a otro.
Frente a la instalación manual, además, tiene beneficios claros:
- Sale del catálogo: se evita buscar el instalador en páginas que imitan a la del fabricante.
- Comprueba la huella: si el archivo no coincide con el catálogo, winget se detiene.
- Se repite igual: el mismo script da el mismo resultado en todos los equipos.
- Queda escrito: el script documenta qué se instaló.
Instalar winget y comprobar que funciona
En primer lugar, abra una consola y escriba lo siguiente. Si responde con un número de versión, no tiene que instalar nada:
winget --version
winget --info
Por su parte, winget --info muestra dónde guarda sus registros y su configuración. Microsoft pide estos requisitos: Windows 10 1809 (compilación 17763) o posterior, Windows 11 o Windows Server 2025. Según el proyecto en GitHub, en Windows Server 2019 y 2022 solo funciona de forma experimental y sin soporte. Y un detalle que explica muchas consultas: winget no está disponible hasta que el usuario inicia sesión por primera vez, porque es entonces cuando Microsoft Store registra el componente.
Instalar o reparar winget con PowerShell
Si falta o está dañado, Microsoft propone reparar con su módulo, en una consola elevada:
Install-PackageProvider -Name NuGet -Force | Out-Null
Install-Module -Name Microsoft.WinGet.Client -Force -Repository PSGallery | Out-Null
Repair-WinGetPackageManager -Force -Latest
Además, para dejarlo disponible a todos los usuarios del equipo, añada -AllUsers a Repair-WinGetPackageManager. Si quiere ver antes si hace falta, Assert-WinGetPackageManager no devuelve nada cuando todo está bien, como ocurrió en la prueba.
Winget no se reconoce como un comando
El mensaje «winget no se reconoce como nombre de un cmdlet» o «como un comando interno o externo» tiene pocas causas, y conviene revisarlas en este orden:
| Causa | Cómo se comprueba | Qué hacer |
|---|---|---|
| El usuario acaba de iniciar sesión por primera vez | Equipo o perfil recién creado | Esperar a que Microsoft Store registre el componente |
| Falta el Instalador de aplicaciones | Get-AppxPackage Microsoft.DesktopAppInstaller no devuelve nada | Repararlo con el módulo, como arriba |
| La carpeta de alias no está en el PATH | Get-Command winget no encuentra nada | Comprobar que %LOCALAPPDATA%\Microsoft\WindowsApps esté en el PATH de usuario |
| Se ejecuta como SYSTEM | Tarea programada o herramienta de despliegue | Usar el módulo, como explicamos más abajo |
| Un administrador lo desactivó | HKLM:\SOFTWARE\Policies\Microsoft\Windows\AppInstaller tiene valores | Revisar la directiva |
| Windows Server anterior a 2025 | Get-ComputerInfo -Property OsName | No tiene soporte |
En el equipo de prueba, winget.exe era un alias de 0 bytes en %LOCALAPPDATA%\Microsoft\WindowsApps, y esa carpeta estaba en el PATH de usuario, no en el del sistema. Por eso una cuenta distinta o una tarea de otro usuario pueden no encontrarlo aunque usted sí lo vea.
Comandos de winget más comunes
Estos son los comandos de winget que se usan a diario. La lista completa sale con winget --help, y la de cada uno, con winget install --help:
| Comando | Para qué sirve |
|---|---|
winget search | Busca en el catálogo |
winget show | Muestra la ficha de un paquete y sus versiones |
winget install | Instala un paquete |
winget list | Lista lo instalado |
winget upgrade | Lista las actualizaciones, o actualiza |
winget uninstall | Desinstala |
winget pin | Fija un paquete para que no se actualice |
winget export y winget import | Guardan e instalan una lista de paquetes |
winget download | Descarga el instalador sin instalarlo |
winget source | Administra los orígenes |
winget settings | Abre la configuración |
winget error | Explica un código de error |
Buscar un programa
winget search powershell --source winget
winget show --id Microsoft.PowerShell --exact --source winget
winget show --id jqlang.jq --exact --source winget --versions
Sin embargo, winget search mira también las etiquetas, así que devuelve mucho: con «powershell» salieron 65 paquetes, y casi todos solo llevan esa palabra como etiqueta. Por eso conviene copiar el identificador de la columna Id y usarlo siempre.
Instalar un programa
La forma segura de instalar usa el identificador exacto y el origen:
winget install --id Microsoft.PowerShell --exact --source winget
Así no hay dudas sobre qué paquete se instala. En cambio, para un script, añada las opciones que evitan preguntas:
winget install --id jqlang.jq --exact --source winget --silent --accept-package-agreements --accept-source-agreements --disable-interactivity
Estas son las opciones que más se usan:
| Opción | Para qué sirve |
|---|---|
--id y --exact | Busca ese identificador, tal cual |
--source winget | Evita buscar también en Microsoft Store |
--silent | Instala sin ventanas, si el instalador lo permite |
--scope user o --scope machine | Solo para este usuario, o para todo el equipo |
--version | Instala una versión concreta |
--accept-package-agreements | Acepta la licencia del paquete |
--accept-source-agreements | Acepta las condiciones del origen |
--disable-interactivity | Nunca se queda esperando una respuesta |
--no-upgrade | Si ya está instalado, no intenta actualizar |
Probamos cada caso con jq, un programa pequeño que luego quitamos. Dos resultados sorprenden:
- Instalar lo que ya está actualiza. winget responde
Found an existing package already installed. Trying to upgrade the installed package...y sigue. Con--no-upgradese detiene con «A package version is already installed. Installation cancelled.» --versionno baja de versión. Con jq 1.8.2 instalado, pedir la 1.7.1 terminó en «No available upgrade found.» y la versión siguió igual. Para bajar, primero hay que desinstalar.
Por qué un programa recién instalado no aparece
Este comportamiento cambia según la consola, y lo medimos con jq:
| Dónde se instaló | ¿Lo ve la misma consola? |
|---|---|
winget install en PowerShell 7.6.9 | Sí |
winget install en Windows PowerShell 5.1 | No |
Install-WinGetPackage en cualquiera de las dos | No |
Aunque winget avisa «Path environment variable modified; restart your shell to use the new value», PowerShell 7 ya lo veía. En los otros casos, abra una consola nueva o recargue el PATH en la actual:
$env:Path = [Environment]::GetEnvironmentVariable('Path', 'Machine') + ';' + [Environment]::GetEnvironmentVariable('Path', 'User')
Además, jq es un paquete portátil, y winget lo copió a %LOCALAPPDATA%\Microsoft\WinGet\Packages y añadió esa carpeta al PATH de usuario, en lugar de crear un enlace en la carpeta Links. Por eso, cada programa portátil que se instala así alarga el PATH.
Actualizar programas con winget
winget upgrade
winget upgrade --id jqlang.jq --exact --source winget --silent --accept-package-agreements --disable-interactivity
winget upgrade --all --silent --accept-package-agreements --accept-source-agreements --disable-interactivity
En primer lugar, la primera orden solo lista, y no cambia nada. En el equipo de prueba dijo «22 upgrades available.», más un aviso: 1 package(s) have version numbers that cannot be determined. Use --include-unknown to see all results. Con --include-unknown subió a 23.
La tercera orden, winget upgrade --all, es cómoda y arriesgada, porque salta a la última versión sin distinguir. Entre esas 22 pendientes había cuatro cambios de versión mayor: Node.js LTS de la 24.19 a la 26.13, OpenSSL de la 3.6 a la 4.1, PDFgear de la 2.1 a la 3.0 y Adobe Creative Cloud de la 5.2 a la 6.11. Por lo tanto, un cambio así puede romper lo que depende de ese programa. Por eso no la ejecutamos, y por eso existen los fijados, que veremos a continuación.
Desinstalar y descargar
winget uninstall --id jqlang.jq --exact --silent --disable-interactivity
winget download --id jqlang.jq --exact --source winget -d C:\Temp\Instaladores --accept-package-agreements --disable-interactivity
winget download dejó dos archivos: el instalador y un archivo .yaml con la descripción del paquete. Es la forma de llevar un programa a un equipo sin salida a internet.
Fijar versiones con winget pin
Fijar impide que una actualización general toque un programa. Hay tres tipos de fijado, y el de fábrica protege menos de lo que parece:
| Tipo | Orden | Qué hace | Lo que medimos con jq |
|---|---|---|---|
| Normal | winget pin add --id jqlang.jq --exact | Lo saca de winget upgrade --all | winget upgrade --id lo actualizó igual, con código 0 |
| Bloqueo | winget pin add --id jqlang.jq --exact --blocking | Impide cualquier actualización | «A newer version was found, but the package has a pin that prevents from upgrading it.»; con --force, se actualizó |
| Por versión | winget pin add --id jqlang.jq --exact --version 1.8.* | Solo admite esa rama | No lo probamos |
Es decir, si quiere que un programa no se mueva, use --blocking. Con un fijado normal, además, el paquete desaparece de winget list --upgrade-available, que avisa con «1 package(s) have pins that prevent upgrade.»
winget pin list
winget pin remove --id jqlang.jq --exact
Winget con PowerShell: el módulo Microsoft.WinGet.Client
Se puede escribir winget dentro de un script de PowerShell, pero lo que devuelve es texto pensado para leerse en pantalla. El módulo oficial de la Galería, Microsoft.WinGet.Client, devuelve objetos, y eso lo cambia todo a la hora de filtrar o exportar. Se instala como cualquier otro módulo:
Install-Module -Name Microsoft.WinGet.Client -Scope CurrentUser -Repository PSGallery
Import-Module -Name Microsoft.WinGet.Client
Get-WinGetVersion
Por otro lado, si la instalación falla, la guía de módulos de PowerShell repasa los errores habituales. Medimos la versión 1.29.380, del 21 de septiembre de 2026, con 41 archivos y 53,4 MB. Trae 20 cmdlets y su firma es válida, a nombre de Microsoft Corporation. Cargó en 1,3 s en PowerShell 7 y en 0,1 s en la 5.1.
Ojo con una contradicción: el README del módulo pide «la última versión de PowerShell (no Windows PowerShell)», pero la Galería declara como mínimo la 5.1, y en nuestra prueba funcionó igual en las dos versiones.
| Cmdlet | Equivale a | Para qué sirve |
|---|---|---|
Find-WinGetPackage | winget search | Busca en el catálogo |
Get-WinGetPackage | winget list | Lista lo instalado |
Install-WinGetPackage | winget install | Instala |
Update-WinGetPackage | winget upgrade | Actualiza |
Uninstall-WinGetPackage | winget uninstall | Desinstala |
Export-WinGetPackage | winget download | Descarga el instalador |
Get-WinGetSource | winget source list | Lista los orígenes |
Get-WinGetUserSetting | winget settings | Lee la configuración del usuario |
Assert-WinGetPackageManager | Sin equivalente | Comprueba que winget funciona |
Repair-WinGetPackageManager | Sin equivalente | Instala o repara winget |
Buscar, listar y filtrar con objetos
Find-WinGetPackage -Id 'Microsoft.PowerShell' -MatchOption Equals -Source winget
Get-WinGetPackage | Where-Object IsUpdateAvailable | Select-Object Name, Id, InstalledVersion
Get-WinGetPackage | Where-Object Source -eq 'winget' | Measure-Object
Cada paquete instalado trae las propiedades Name, Id, InstalledVersion, IsUpdateAvailable, AvailableVersions y Source. Sin embargo, hay dos detalles que conviene conocer:
-Source wingetno filtra lo instalado.Get-WinGetPackage -Source wingetdevolvió los 146 paquetes, igual que sin el parámetro. Para quedarse con los de un origen, useWhere-Object, como arriba.- Si no encuentra nada, no avisa.
Find-WinGetPackageyGet-WinGetPackagecon un identificador que no existe devolvieron cero objetos y ningún error. Un script tiene que comprobarlo.
-WhatIf no simula: instala de verdad
Este es el hallazgo más importante de la guía. Los tres cmdlets que cambian algo aceptan -WhatIf, que en PowerShell significa «dime qué harías sin hacerlo». Pero, con la versión 1.29.380, no lo respetan. Lo descubrimos por accidente, y lo repetimos con jq en las dos versiones de PowerShell:
| Orden | Antes | Después | Status |
|---|---|---|---|
Install-WinGetPackage -WhatIf | No instalado | 1.8.2 instalado | Ok |
Update-WinGetPackage -WhatIf | 1.8.1 | 1.8.2 | Ok |
Uninstall-WinGetPackage -WhatIf | 1.8.2 | Desinstalado | Ok |
Tampoco sirve $WhatIfPreference = $true: jq se instaló igual. No hay aviso ni error, y Status dice Ok. Así que nunca use -WhatIf para probar estos cmdlets, y menos en un equipo en producción. Para ver qué pasaría, use las órdenes de lectura: Find-WinGetPackage, Get-WinGetPackage o winget upgrade. Solo lo probamos con un paquete portátil, así que no sabemos si ocurre igual con otros tipos de instalador; aun así, conviene asumir que sí.
Comprobar el resultado en un script
Con el módulo, el resultado está en Status, una cadena que conviene revisar siempre. Esto respondió en cada caso:
| Caso | Qué devolvió |
|---|---|
| Instalar un paquete nuevo | Status = Ok |
| Instalar uno que ya está | Status = Ok, sin avisar de que ya estaba |
| Actualizar sin versión nueva | Status = NoApplicableUpgrade |
| Instalar un identificador que no existe | Error «No packages matched the given input criteria.»; devuelve nulo y el script sigue |
Por eso, en un script conviene añadir -ErrorAction Stop dentro de un try/catch. Otros valores posibles de Status, leídos del propio módulo, son BlockedByPolicy, CatalogError, DownloadError, InstallError, ManifestError, NoApplicableInstallers y PackageAgreementsNotAccepted. El resultado trae además RebootRequired, InstallerErrorCode y ExtendedErrorCode.
Por qué no conviene leer el texto de winget
Muchos scripts capturan la salida de winget list y la cortan por columnas. Sin embargo, medimos tres problemas:
- Las tildes llegan rotas. winget escribe en UTF-8, y PowerShell lo lee con la codificación de la consola (
ibm850en el equipo de prueba, en las dos versiones). «Asistencia rápida» llegó comoAsistencia r├ípida, y una comparación con el nombre correcto dioFalse. - Las filas no son paquetes.
winget listdio 166 filas para 146 identificadores, porque repite algunos:Microsoft.WindowsAppRuntime.1.8salió seis veces. - Las columnas dependen del contenido. En
winget list, Version empezaba en la posición 147, y enwinget upgrade, mucho antes. Además, los mensajes están en inglés, así que cualquier cambio de versión puede romper el corte.
Si aun así necesita el texto, cambie antes la codificación. Así, la comparación dio True en las dos versiones:
$anterior = [Console]::OutputEncoding
[Console]::OutputEncoding = [Text.UTF8Encoding]::new($false)
$texto = winget list --disable-interactivity
[Console]::OutputEncoding = $anterior
Exportar e importar la lista de programas
winget export guarda en un JSON los paquetes instalados, y winget import los instala en otro equipo:
winget export -o "$env:USERPROFILE\Desktop\programas.json" --include-versions
winget import -i "$env:USERPROFILE\Desktop\programas.json" --accept-package-agreements --accept-source-agreements --ignore-unavailable --disable-interactivity
Pero un archivo exportado no es un inventario. En el equipo de prueba guardó 55 de los 146 paquetes (53 de winget y 2 de Microsoft Store), y avisó 91 veces con «Installed package is not available from any source». Entre los que se quedaron fuera estaban Aplicaciones de Microsoft 365 y RustDesk. Lo que winget no encuentra en un catálogo no se exporta. Para saber qué hay instalado, use Get-WinGetPackage. Además, --include-versions guarda la versión de cada paquete; sin esa opción, winget import instala la más reciente.
Configurar winget
La configuración de cada usuario vive en un archivo settings.json. winget settings lo abre con su editor, y winget settings export muestra la configuración vigente. En el equipo de prueba el archivo no existía: mientras no se cree, se aplican los valores de fábrica. Esta configuración hace que winget prefiera instalar para el usuario actual:
{
"$schema": "https://aka.ms/winget-settings.schema.json",
"installBehavior": {
"preferences": {
"scope": "user"
}
}
}
La referencia de Microsoft distingue dos niveles: preferences ordena las opciones disponibles, y requirements las filtra, así que puede terminar en un error si ninguna cumple. Lo que se pase en la línea de comandos manda sobre ambas.
Orígenes y registros
winget source list
winget source update
El origen winget es el catálogo de la comunidad, y msstore, Microsoft Store. Por su parte, los registros están en %LOCALAPPDATA%\Packages\Microsoft.DesktopAppInstaller_8wekyb3d8bbwe\LocalState\DiagOutputDir. Según Microsoft, se borran los que tienen más de 7 días o superan 128 MB en total; en el equipo de prueba había 155 archivos y 0,9 MB. Con --verbose-logs, el registro es más completo.
Directivas para empresas
Las directivas de Microsoft están en Configuración del equipo, ruta Windows Components > Desktop App Installer, y escriben en HKLM:\SOFTWARE\Policies\Microsoft\Windows\AppInstaller:
| Directiva | Para qué sirve |
|---|---|
EnableAppInstaller | Activa o desactiva el Instalador de aplicaciones |
EnableWindowsPackageManagerCommandLineInterfaces | Si se desactiva, nadie puede usar winget ni sus cmdlets |
EnableMicrosoftStoreSource | Permite o impide el origen de Microsoft Store |
EnableDefaultSource | Permite o impide el catálogo winget |
EnableAllowedSources | Limita qué orígenes se pueden agregar |
EnableAdditionalSources | Agrega orígenes propios de la empresa |
EnableHashOverride | Controla si se puede saltar la comprobación de la huella |
Winget como SYSTEM y en tareas programadas
Aquí está la limitación que más sorprende a quien automatiza. Según la guía de problemas de Microsoft, la línea de comandos de winget no se admite como SYSTEM, porque es una aplicación empaquetada y su registro es por usuario. En cambio, el módulo Microsoft.WinGet.Client sí se puede usar como SYSTEM, con aplicaciones instaladas para todo el equipo.
Por eso, en la práctica, esto lleva a tres reglas:
- Herramientas de despliegue y tareas como SYSTEM: use el módulo, instalado con
-Scope AllUsers, y paquetes con-Scope System. - Tareas con la cuenta de un usuario:
wingetfunciona, pero solo si esa cuenta ya inició sesión alguna vez. - Cualquier tarea: añada
--accept-package-agreements,--accept-source-agreementsy--disable-interactivity, porque nadie va a responder a las preguntas.
La forma de crearlas está en nuestra guía de tareas programadas con PowerShell. No lo probamos como SYSTEM, porque exige elevar.
Escenarios de winget con PowerShell
Los escenarios se pueden copiar tal cual. Salvo el tercero, los ejecutamos en PowerShell 5.1 y 7, con jq como paquete de prueba.
Escenario 1: preparar un equipo nuevo
Este bloque instala una lista de programas y deja un resultado por cada uno. Si un identificador está mal, sigue con el siguiente:
$programas = '7zip.7zip', 'Mozilla.Firefox', 'Notepad++.Notepad++'
$resultado = foreach ($id in $programas) {
try {
$r = Install-WinGetPackage -Id $id -MatchOption Equals -Source winget -Mode Silent -ErrorAction Stop
[pscustomobject]@{ Id = $id; Estado = $r.Status; Reinicio = $r.RebootRequired; Codigo = $r.InstallerErrorCode }
} catch {
[pscustomobject]@{ Id = $id; Estado = $_.Exception.Message; Reinicio = $false; Codigo = $null }
}
}
$resultado | Format-Table -AutoSize
Busque antes cada identificador con winget search, porque tiene que coincidir letra por letra.
Escenario 2: informe de programas desactualizados
Guarda un CSV que Excel abre con las tildes bien, en las dos versiones de PowerShell:
$lineas = Get-WinGetPackage | Where-Object IsUpdateAvailable |
Select-Object Name, Id, InstalledVersion, @{ n = 'Disponible'; e = { @($_.AvailableVersions)[0] } }, Source |
ConvertTo-Csv -NoTypeInformation -Delimiter ';'
[IO.File]::WriteAllLines("$env:USERPROFILE\Desktop\desactualizados.csv", [string[]]$lineas, [Text.UTF8Encoding]::new($true))
En el equipo de prueba listó 21 programas, y AvailableVersions traía primero la versión más reciente.
Escenario 3: actualizar todo, salvo lo delicado
Primero se bloquea lo que no debe moverse y, luego, se actualiza lo demás. No lo ejecutamos, porque habría actualizado todo el equipo de prueba:
winget pin add --id OpenJS.NodeJS.LTS --exact --blocking
winget pin add --id PostgreSQL.PostgreSQL.18 --exact --blocking
winget upgrade --all --silent --accept-package-agreements --accept-source-agreements --disable-interactivity
'Código de salida: 0x{0:X8}' -f $LASTEXITCODE
Escenario 4: actualizar solo una lista, comprobando cada paso
Cuando no quiere tocar nada más, recorra una lista corta y actualice solo lo que tenga versión nueva:
$lista = 'jqlang.jq', '7zip.7zip'
foreach ($id in $lista) {
$p = Get-WinGetPackage -Id $id -MatchOption Equals
if (-not $p) { "$id no está instalado"; continue }
if (-not $p.IsUpdateAvailable) { "$id ya está en $($p.InstalledVersion)"; continue }
$r = Update-WinGetPackage -Id $id -MatchOption Equals -Mode Silent
"$id -> $($r.Status) · reinicio: $($r.RebootRequired)"
}
Escenario 5: reaccionar al código de salida de winget.exe
$LASTEXITCODE llega en decimal y negativo, así que conviene pasarlo a hexadecimal:
winget install --id jqlang.jq --exact --source winget --silent --accept-package-agreements --accept-source-agreements --disable-interactivity
switch ('0x{0:X8}' -f $LASTEXITCODE) {
'0x00000000' { 'Instalado o ya estaba al día' }
'0x8A15002B' { 'Ya estaba instalado y no hay versión nueva' }
'0x8A150014' { 'No existe ese identificador' }
default { winget error ('0x{0:X8}' -f $LASTEXITCODE) }
}
Escenario 6: llevar un instalador a un equipo sin internet
En el equipo con salida a internet:
New-Item -ItemType Directory -Path 'C:\Temp\Instaladores' -Force | Out-Null
winget download --id jqlang.jq --exact --source winget -d C:\Temp\Instaladores --accept-package-agreements --disable-interactivity
Get-ChildItem -Path 'C:\Temp\Instaladores'
Después, copie la carpeta y ejecute el instalador en el otro equipo. El archivo .yaml dice qué opciones acepta el instalador para instalarse sin ventanas.
Errores frecuentes de winget
winget error explica un código. Acepta el valor en hexadecimal, pero el decimal solo con --input: winget error -1978335212 falla, y winget error --input -1978335212 funciona.
| Código | Mensaje | Qué significa | Qué hacer |
|---|---|---|---|
| 0x8A150014 | No package found matching input criteria. | No encontró ese paquete | Revisar el Id con winget search |
| 0x8A15002B | No available upgrade found. | Ya está en la última versión | Nada; en un script, no es un fallo |
| 0x8A150061 | A package version is already installed. Installation cancelled. | Ya estaba, y se pidió --no-upgrade | Nada |
| 0x8A150068 | A newer version was found, but the package has a pin that prevents from upgrading it. | Tiene un fijado de bloqueo | winget pin remove |
| 0x8A150002 | Argument name was not recognized for the current command | Opción mal escrita | Revisar con --help |
| 0x8A150011 | The installer file's hash does not match the manifest | La huella no coincide | No saltarla; reintentar más tarde |
| 0x8A150056 | The installer cannot be run from an administrator context. | El instalador no admite elevación | Usar una consola sin elevar |
| 0x8A150109 | Restart your PC to finish installation. | Falta reiniciar | Reiniciar |
Los cinco primeros los provocamos en la prueba. En cambio, el texto de los otros tres sale de winget error. Además, Microsoft documenta un error 403 Forbidden: ocurre si el fabricante no permite la descarga desde un gestor de paquetes, y entonces hay que bajar el instalador con el navegador.
Recomendaciones para usar winget
Estas son, en resumen, las prácticas que recomendamos tras la prueba:
- Use siempre
--id,--exacty--source: así instala lo que quiere y no lo que más se le parece. - Nunca confíe en
-WhatIfcon el módulo: no simula. - Revise la lista antes de
winget upgrade --ally bloquee lo que dependa de una versión mayor. - Use
--blockingsi un programa no debe moverse: el fijado normal deja actualizarlo con--id. - Para scripts, prefiera el módulo: da objetos, sin problemas de tildes ni de columnas.
- No tome el archivo de
winget exportcomo inventario: deja fuera lo que no está en un catálogo. - Recuerde que el catálogo es de terceros: la huella protege de un archivo alterado, pero no dice que el programa sea adecuado para su empresa. Limite los orígenes por directiva si hace falta.
- No use
--ignore-security-hash: Microsoft tampoco lo recomienda. - Vigile el PATH en equipos con muchos programas portátiles.
Lo que medimos y lo que no
Medimos en un Windows 11 Pro 26H2 en español, sin permisos de administrador, con Windows PowerShell 5.1.26100 y PowerShell 7.6.9:
- winget 1.29.380 y su módulo 1.29.380, descargado a una carpeta temporal;
- las órdenes de lectura, con sus tiempos y códigos de salida;
- un ciclo real con jq, un paquete portátil de 1 MB: instalar, fijar, actualizar, exportar, importar, descargar y desinstalar;
- el comportamiento de
-WhatIfy de$WhatIfPreference; - la codificación y las filas repetidas de la salida de texto.
Además, comprobamos los comandos y los parámetros del artículo contra el módulo en las dos versiones, y ejecutamos los escenarios 1, 2, 4, 5 y 6 con jq. Al terminar, jq se desinstaló y el equipo quedó como estaba.
En cambio, no ejecutamos winget upgrade --all ni probamos paquetes MSI o EXE, la instalación para todo el equipo, la ejecución como SYSTEM, Windows Server, winget configure, el fijado por versión ni una consola estrecha, donde winget podría recortar las columnas. Lo que no medimos sale de la documentación de Microsoft.
Preguntas frecuentes
¿Winget es gratis?
Sí. Winget y su módulo son gratuitos y vienen de Microsoft. Eso sí, cada programa tiene su propia licencia, y --accept-package-agreements acepta esa licencia en su nombre.
¿Winget necesita permisos de administrador?
No para funcionar. Instalamos, actualizamos y quitamos jq sin elevar. Sin embargo, según Microsoft, algunas aplicaciones piden elevación al instalarse, y Windows muestra entonces su aviso; si no se acepta, la instalación falla. En una consola elevada no aparece ese aviso, así que conviene ser prudente con lo que se instala.
¿Winget actualiza Windows?
No. Actualiza programas, no el sistema operativo. Para eso, tenemos una guía de Windows Update con PowerShell.
¿Funciona winget en Windows Server?
Microsoft da soporte en Windows Server 2025. En Windows Server 2019 y 2022, el proyecto dice que puede funcionar de forma experimental, sin soporte.
¿Por qué winget sale en inglés?
En el equipo de prueba, con Windows en español, todos sus mensajes salieron en inglés. Por eso, al buscar un error conviene hacerlo con el mensaje en inglés o con su código.
¿Es lo mismo winget que Microsoft Store?
No. Microsoft Store es uno de sus orígenes. El otro, winget, es un catálogo con programas de muchos fabricantes.
Winget en la empresa
Instalar un programa con winget es fácil. Lo difícil, en cambio, es que todos los equipos tengan los mismos programas, que nadie instale de más y que una actualización no rompa lo que depende de ella. En KHARONTE hacemos ese trabajo dentro de la instalación y estandarización de aplicaciones de nuestro soporte técnico para empresas, atendido desde nuestra mesa de ayuda TI y como parte de los servicios administrados de TI que prestamos. Si quiere conocer el resto de nuestros servicios de TI para empresas, escríbanos.




