Mostrando las entradas con la etiqueta mantenimiento. Mostrar todas las entradas
Mostrando las entradas con la etiqueta mantenimiento. Mostrar todas las entradas

martes, 15 de septiembre de 2026

Un actualizador de WinGet y NPM para Windows 11, y los comandos que hay detrás



Una ventana con tres pestanas para el mantenimiento de siempre, que no esconde ni uno solo de los comandos que ejecuta.


-------------------------------------------------------------------------------

INTRODUCCION

-------------------------------------------------------------------------------


Mantener un Windows al día son siempre los mismos tres o cuatro comandos, repartidos en dos gestores  de paquetes distintos y en un par de herramientas de reparación que uno solo recuerda cuando ya hay un problema. Me canse de teclearlos y escribí una pequeña utilidad que los reúne en una ventana:

Actualizador WinGet + NPM.


No es un envoltorio que esconde lo que hace. Es justo lo contrario: ejecuta los comandos de verdad, los escribe en pantalla antes de lanzarlos y muestra su salida en vivo, tal cual la vería en una terminal. Si algún día no tengo la utilidad a mano, puedo escribir esos mismos comandos y obtener exactamente el mismo resultado. Al final del articulo los dejo todos.


-------------------------------------------------------------------------------

QUE ES

-------------------------------------------------------------------------------


Un ejecutable de unos 200 KB para Windows 10/11 de 64 bits, escrito en C# sobre .NET 8 (WinForms). No se instala: se copia y se abre con doble clic. La ventana tiene tres pestanas -WinGet, NPM y Sistema- y cada una con su propia consola negra donde aparece la salida del comando conforme se va produciendo, no al terminar.


Arriba, en la cabecera, hay tres botones que valen para toda la aplicacion:


  - Detener: cancela el comando en curso cerrando el proceso y todos sus hijos.

  - Reiniciar como administrador: relanza la ventana con UAC.

  - Acerca de.


El titulo de la ventana avisa con un [Administrador] cuando ya se esta ejecutando elevada.


-------------------------------------------------------------------------------

PESTANA WINGET

-------------------------------------------------------------------------------


Boton: Buscar actualizaciones

  Comando: winget upgrade


Boton: Ver instalados

  Comando: winget list


Boton: Actualizar todo

  Comando: winget upgrade --all + banderas de aceptacion


Boton: Actualizar marcados

  Comando: winget upgrade --id <Id> --exact, uno por paquete


Boton: Reparar marcados

  Comando: ... --uninstall-previous --force, y si falla winget install --force


Boton: Reparar todo

  Comando: winget upgrade --all --include-unknown --uninstall-previous --force


Los resultados no se quedan solo en la consola: la aplicacion interpreta la tabla que devuelve winget y la vuelca en una lista con casillas, de manera que se puede actualizar unicamente lo que interesa en lugar de lanzar un --all a ciegas.


Conviene distinguir los dos listados, porque no muestran lo mismo:


  - winget upgrade solo ensena los paquetes que tienen una version mas nueva disponible.

  - winget list ensena el inventario completo del equipo, incluidas las aplicaciones MSIX de la Store, que ni siquiera tienen a winget como origen.

    En ese listado completo la columna Disponible aparece rellena solo en los que si tienen actualizacion pendiente.


Hay ademas tres casillas:


  - --include-unknown: incluye los programas cuya version instalada winget no consigue determinar.

  - --silent: oculta la interfaz de los instaladores (ojo, que algunos paquetes fallan en modo silencioso).

  - Volver a buscar automaticamente al terminar.



POR QUE EXISTE UN BOTON "REPARAR"


Este es el motivo real por el que acabe escribiendo la utilidad. Tarde o temprano, winget upgrade --all deja algún paquete atrás con un error parecido a que no encuentra el instalador de la version que ya está instalada. La razon es que, para ciertos paquetes, winget necesita desinstalar la version anterior antes de poner la nueva, y para desinstalarla busca el instalador original en su cache. Si esa cache se limpió, o el paquete se instaló de otra forma, ahi se queda atascado.


La salida es --uninstall-previous, que le indica a winget que desinstale la version anterior usando la información del propio manifiesto en lugar del instalador cacheado, acompañado de --force para que continúe ante problemas no relacionados con la seguridad. Si ni con esas, "Reparar marcados" da un segundo paso: reinstalar el paquete desde cero con winget install --force, que se descarga el instalador nuevo completo.


-------------------------------------------------------------------------------

PESTANA NPM

-------------------------------------------------------------------------------


Boton: Listar globales

  Comando: npm ls -g --depth=0


Boton: Ver desactualizados

  Comando: npm outdated -g


Boton: Actualizar globales

  Comando: npm update -g


Un detalle de npm outdated: devuelve código de salida 1 cuando encuentra paquetes pendientes. Eso, para cualquier script, significa "ha fallado". La aplicación lo trata como lo que es, información, y no lo pinta como error.



EL DESCONCIERTO DE "NO HAY NADA QUE ACTUALIZAR" SEGUIDO DE 685 PAQUETES

CAMBIADOS


Esto me paso usando la propia utilidad y merece su apartado, porque es una de esas cosas que parecen un fallo y no lo son. La secuencia fue: npm outdated -g no devolvió ni una línea, señal de que todo estaba al dia. Acto seguido, npm update -g respondió esto:


    > npm outdated -g

    -- fin en 2,5 s, codigo 0 --


    > npm update -g

    npm warn deprecated inflight@1.0.6 ...

    npm warn deprecated rimraf@2.4.5 ...

    changed 685 packages in 2m


No hay contradicción: los dos comandos miran cosas distintas. npm outdated, por omisión, solo compara las dependencias de primer nivel, que en el ámbito global son exactamente los paquetes que salen en npm ls -g --depth=0. En mi caso eran cinco, y los cinco estaban en su última version. De ahi la salida vacía.


npm update, en cambio, recorre el arbol entero y sube cada dependencia transitiva a la version más nueva que permita el rango semver de su padre. Un paquete como eas-cli arrastra el solo varios cientos de dependencias anidadas, y ahi si había versiones nuevas. El número que informa al final, además, no son 685 actualizaciones: changed N packages cuenta los paquetes añadidos, eliminados y modificados al recalcular el arbol, y una reorganización de dependencias infla bastante esa cifra.


Para ver lo que update va a tocar de verdad hay que pedirle a outdated que mire también lo anidado:


    npm outdated -g --all


En mi equipo, ese comando seguía devolviendo 404 paquetes desactualizados justo después de actualizar. Al mirarlos uno por uno, todos tenían la columna Wanted igual a Latest y por encima de Current: son saltos de version mayor (Babel 7 a 8, Expo 55 a 57) que el rango declarado por el paquete padre no admite. npm update respeta semver y nunca cruza un mayor por su cuenta; eso solo se arregla cuando el autor del paquete de arriba publica una version nueva. Y de ahi vienen también los avisos de deprecated que reaparecen en cada actualización: son dependencias viejas clavadas dentro de cadenas ajenas, no algo que uno haya instalado.


-------------------------------------------------------------------------------

PESTANA SISTEMA (DISM . SFC)

-------------------------------------------------------------------------------


Boton: 1. Comprobar

  Comando: DISM /Online /Cleanup-Image /CheckHealth


Boton: 2. Analizar

  Comando: DISM /Online /Cleanup-Image /ScanHealth


Boton: 3. Reparar

  Comando: DISM /Online /Cleanup-Image /RestoreHealth


Boton: 4. Archivos de sistema

  Comando: sfc /scannow


Boton: Secuencia completa

  Comando: Los cuatro anteriores, en ese orden


El orden no es capricho. SFC repara los archivos del sistema tomándolos del almacén de componentes, así que lo sensato es que DISM haya dejado sano ese almacén antes de lanzar SFC; al revés, SFC puede estar copiando archivos de un origen que también esta dañado. Y RestoreHealth descarga los archivos correctos desde Windows Update, de modo que necesita conexión a internet.


Los cuatro exigen permisos de administrador. Si la ventana no está elevada, aparece un aviso que ofrece reiniciarla con UAC, ejecutar de todos modos -fallara con el error 740- o cancelar. Como ScanHealth, RestoreHealth y sfc /scannow tardan varios minutos, la barra de estado va mostrando el tiempo transcurrido para saber que aquello sigue vivo.


Codigos de salida que conviene reconocer:


    0     correcto

    740   faltan permisos de administrador

    3010  correcto pero hay que reiniciar


El detalle completo queda, como siempre, en:


    %WinDir%\Logs\CBS\CBS.log     para SFC

    %WinDir%\Logs\DISM\dism.log   para DISM


-------------------------------------------------------------------------------

LOS MISMOS COMANDOS, A MANO

-------------------------------------------------------------------------------


La utilidad no hace nada que no se pueda hacer en una terminal, y ese fue un requisito desde el principio. Cada vez que se pulsa un botón, la consola escribe primero la línea completa del comando -en azul- y después su salida. Asi que siempre se puede leer que se ejecutó, copiarlo y repetirlo a mano. 


SI QUIERES USAR LA APLICACIÓN LA PUEDES DESCARGAR AQUÍ


Aqui está el repertorio completo, por si alguien quiere quedarse solo con esta parte del artículo:


# --- WinGet -------------------------------------------------

winget upgrade                       # lo que tiene version mas nueva

winget list                          # inventario completo del equipo

winget upgrade --all --include-unknown --accept-package-agreements --accept-source-agreements


# un paquete concreto (el Id sale en la segunda columna del listado)

winget upgrade --id Microsoft.PowerShell --exact --accept-package-agreements --accept-source-agreements


# reparacion: desinstalar la version previa antes de instalar la nueva

winget upgrade --id <Id> --exact --uninstall-previous --force --accept-package-agreements --accept-source-agreements

winget install --id <Id> --exact --force --accept-package-agreements --accept-source-agreements


# --- NPM global ---------------------------------------------

npm ls -g --depth=0                  # que tengo instalado

npm outdated -g                      # desactualizados de primer nivel

npm outdated -g --all                # incluyendo dependencias anidadas

npm update -g                        # actualizar respetando semver


# --- Sistema (consola COMO ADMINISTRADOR) -------------------

DISM /Online /Cleanup-Image /CheckHealth

DISM /Online /Cleanup-Image /ScanHealth

DISM /Online /Cleanup-Image /RestoreHealth

sfc /scannow


-------------------------------------------------------------------------------

DOS DETALLES DE IMPLEMENTACION

-------------------------------------------------------------------------------


Aprovecho para dejar constancia de lo que más trabajo dio, que no fue la interfaz sino leer bien la salida de los programas.


1. Cada herramienta escribe en una codificación distinta. winget y npm usan UTF-8, sfc.exe escribe en UTF-16LE y dism.exe lo hace en la página de códigos OEM de la consola (850, 437... según el idioma de Windows). Si se decodifica todo como UTF-8, los acentos salen corruptos y, en el caso de SFC, directamente no se ve nada: la consola aparece vacía y uno cree que el comando no arranco.


2. Las barras de progreso no son texto normal. Estas herramientas se reescriben la linea a base de retornos de carro y codigos de color ANSI. Hay que limpiar esas secuencias para que la salida se lea igual que en una terminal. Y cuidado con sfc.exe, que termina sus lineas con \r\r\n: si se interpreta cada  retorno de carro como "reescribe la linea anterior", el resultado es una consola en blanco.


-------------------------------------------------------------------------------

REQUISITOS

-------------------------------------------------------------------------------


  - Windows 10 u 11 de 64 bits.

  - .NET 8 Desktop Runtime, para la version pequena de ~200 KB. Tambien se puede

    compilar autonoma, de unos 150 MB, que no necesita nada instalado.

  - winget (viene con el Instalador de aplicaciones) y Node.js, según la pestana

    que se use.


Nada más. Es una herramienta pequeña y deliberadamente aburrida: su gracia esta en que no oculta nada de lo que hace por debajo.