Cómo eliminar el bloatware de Microsoft de forma eficaz mediante un script PowerShell

En el panorama informático, el bloatware suele suponer un reto importante tanto para los usuarios de forma general como para los profesionales de TI que gestionan múltiples sistemas. El bloatware hace referencia al software no deseado preinstalado en un ordenador nuevo, que puede ralentizar el rendimiento y saturar el sistema.

Resolver este problema de forma eficaz es crucial, y los scripts de PowerShell ofrecen una potente solución. Este post profundizará en un script PowerShell específico diseñado para eliminar el bloatware común, proporcionando un desglose detallado, casos de uso, comparaciones, preguntas frecuentes y buenas prácticas.

Backgroundb

El bloatware, también conocido como software preinstalado, suele incluir versiones de prueba de programas, herramientas promocionales y otras aplicaciones innecesarias que consumen valiosos recursos.

Para los proveedores de servicios gestionados (MSP) y los profesionales de TI, eliminar estas aplicaciones en numerosos dispositivos puede resultar laborioso y tedioso. Este script de PowerShell automatiza la eliminación del bloatware común, agilizando el proceso y garantizando un sistema más limpio y eficiente.

El script para eliminar el bloatware

#Requires -Version 5.1

<#
.SYNOPSIS
    Removes common bloatware that is often pre-installed on a PC.
.DESCRIPTION
    Removes common bloatware that is often pre-installed on a PC.
.EXAMPLE
    -AppsToRemove "Amazon.com.Amazon, AmazonVideo.PrimeVideo, Clipchamp.Clipchamp, Disney.37853FC22B2CE, DropboxInc.Dropbox, Facebook.Facebook, Facebook.InstagramBeta, king.com.BubbleWitch3Saga, king.com.CandyCrushSaga, king.com.CandyCrushSodaSaga, 5A894077.McAfeeSecurity, 4DF9E0F8.Netflix, SpotifyAB.SpotifyMusic, BytedancePte.Ltd.TikTok, 5319275A.WhatsAppDesktop"
    
    [Warn] Amazon.com.Amazon is not installed!
    Attempting to remove AmazonVideo.PrimeVideo...
    Successfully removed AmazonVideo.PrimeVideo.
    Attempting to remove Clipchamp.Clipchamp...
    Successfully removed Clipchamp.Clipchamp.
    Attempting to remove Disney.37853FC22B2CE...
    Successfully removed Disney.37853FC22B2CE.
    Attempting to remove DropboxInc.Dropbox...
    Successfully removed DropboxInc.Dropbox.
    Attempting to remove FACEBOOK.FACEBOOK...
    Successfully removed FACEBOOK.FACEBOOK.
    Attempting to remove Facebook.InstagramBeta...
    Successfully removed Facebook.InstagramBeta.
    [Warn] king.com.BubbleWitch3Saga is not installed!
    [Warn] king.com.CandyCrushSaga is not installed!
    [Warn] king.com.CandyCrushSodaSaga is not installed!
    Attempting to remove 5A894077.McAfeeSecurity...
    Successfully removed 5A894077.McAfeeSecurity.
    Attempting to remove 4DF9E0F8.Netflix...
    Successfully removed 4DF9E0F8.Netflix.
    Attempting to remove SpotifyAB.SpotifyMusic...
    Successfully removed SpotifyAB.SpotifyMusic.
    Attempting to remove BytedancePte.Ltd.TikTok...
    Successfully removed BytedancePte.Ltd.TikTok.
    Attempting to remove 5319275A.WhatsAppDesktop...
    Successfully removed 5319275A.WhatsAppDesktop.

PARAMETER: -AppsToRemove "AmazonVideo.PrimeVideo"
    A comma-separated list of Appx package names you would like to remove.

PARAMETER: -OverrideWithCustomField "ReplaceMeWithAmultilineCustomFieldName"
    Name of a multiline custom field to retrieve the 'Apps To Remove' list.

.NOTES
    Minimum OS Architecture Supported: Windows 10, Windows Server 2016
    Release Notes: Initial Release
By using this script, you indicate your acceptance of the following legal terms as well as our Terms of Use at https://www.ninjaone.com/terms-of-use.
    Ownership Rights: NinjaOne owns and will continue to own all right, title, and interest in and to the script (including the copyright). NinjaOne is giving you a limited license to use the script in accordance with these legal terms. 
    Use Limitation: You may only use the script for your legitimate personal or internal business purposes, and you may not share the script with another party. 
    Republication Prohibition: Under no circumstances are you permitted to re-publish the script in any script library or website belonging to or under the control of any other software provider. 
    Warranty Disclaimer: The script is provided “as is” and “as available”, without warranty of any kind. NinjaOne makes no promise or guarantee that the script will be free from defects or that it will meet your specific needs or expectations. 
    Assumption of Risk: Your use of the script is at your own risk. You acknowledge that there are certain inherent risks in using the script, and you understand and assume each of those risks. 
    Waiver and Release: You will not hold NinjaOne responsible for any adverse or unintended consequences resulting from your use of the script, and you waive any legal or equitable rights or remedies you may have against NinjaOne relating to your use of the script. 
    EULA: If you are a NinjaOne customer, your use of the script is subject to the End User License Agreement applicable to you (EULA).
#>

[CmdletBinding()]
param (
    [Parameter()]
    [String]$AppsToRemove = "Amazon.com.Amazon, AmazonVideo.PrimeVideo, Clipchamp.Clipchamp, Disney.37853FC22B2CE, DropboxInc.Dropbox, Facebook.Facebook, Facebook.InstagramBeta, king.com.BubbleWitch3Saga, king.com.CandyCrushSaga, king.com.CandyCrushSodaSaga, 5A894077.McAfeeSecurity, 4DF9E0F8.Netflix, SpotifyAB.SpotifyMusic, BytedancePte.Ltd.TikTok, 5319275A.WhatsAppDesktop",
    [Parameter()]
    [String]$OverrideWithCustomField
)

begin {
    # Replace parameters with dynamic script variables.
    if ($env:appsToRemove -and $env:appsToRemove -notlike "null") { $AppsToRemove = $env:appsToRemove }
    if ($env:overrideWithCustomFieldName -and $env:overrideWithCustomFieldName -notlike "null") { $OverrideWithCustomField = $env:overrideWithCustomFieldName }

    $AppList = New-Object System.Collections.Generic.List[string]

    function Get-NinjaProperty {
        [CmdletBinding()]
        Param(
            [Parameter(Mandatory = $True, ValueFromPipeline = $True)]
            [String]$Name
        )
    
        # We'll redirect error output to the success stream to make it easier to error out if nothing was found or something else went wrong.
        $NinjaPropertyValue = Ninja-Property-Get -Name $Name 2>&1
    
        # If we received some sort of error it should have an exception property and we'll exit the function with that error information.
        if ($NinjaPropertyValue.Exception) { throw $NinjaPropertyValue }
    
        if (-not $NinjaPropertyValue) {
            throw [System.NullReferenceException]::New("The Custom Field '$Name' is empty!")
        }
    
        $NinjaPropertyValue
    }

    if ($OverrideWithCustomField) {
        Write-Host "Attempting to retrieve uninstall list from '$OverrideWithCustomField'."
        try {
            $AppsToRemove = Get-NinjaProperty -Name $OverrideWithCustomField -ErrorAction Stop
        }
        catch {
            # If we ran into some sort of error we'll output it here.
            Write-Host "[Error] $($_.Exception.Message)"
            exit 1
        }
    }

    # Check if apps to remove are specified; otherwise, list all Appx packages and exit
    if (!$AppsToRemove) {
        Write-Host "[Error] Nothing given to remove? Please specify one of the below packages."
        Get-AppxPackage -AllUsers | Select-Object Name | Sort-Object Name | Out-String | Write-Host
        exit 1
    }

    # Regex to detect invalid characters in Appx package names
    $InvalidCharacters = "[#!@&$)(<>?|:;\/{}^%`"']+"

    # Process each app name after splitting the input string
    if ($AppsToRemove -match ",") {
        $AppsToRemove -split ',' | ForEach-Object {
            $App = $_.Trim()
            if ($App -match '^[-.]' -or $App -match '\.\.|--' -or $App -match '[-.]$' -or $App -match "\s" -or $App -match $InvalidCharacters) {
                Write-Host "[Error] Invalid character in '$App'. Appx package names cannot contain '#!@&$)(<>?|:;\/{}^%`"'', start with '.-', contain a space, or have consecutive '.' or '-' characters."
                $ExitCode = 1
                return
            }

            if ($App.Length -ge 50) {
                Write-Host "[Error] Appx package name of '$App' is invalid Appx package names must be less than 50 characters."
                $ExitCode = 1
                return
            }

            $AppList.Add($App)
        }
    }
    else {
        $AppsToRemove = $AppsToRemove.Trim()
        if ($AppsToRemove -match '^[-.]' -or $AppsToRemove -match '\.\.|--' -or $AppsToRemove -match '[-.]$' -or $AppsToRemove -match "\s" -or $AppsToRemove -match $InvalidCharacters) {
            Write-Host "[Error] Invalid character in '$AppsToRemove'. AppxPackage names cannot contain '#!@&$)(<>?|:;\/{}^%`"'', start with '.-', contain a space, or have consecutive '.' or '-' characters."
            Get-AppxPackage -AllUsers | Select-Object Name | Sort-Object Name | Out-String | Write-Host
            exit 1
        }

        if ($AppsToRemove.Length -ge 50) {
            Write-Host "[Error] Appx package name of '$AppsToRemove' is invalid Appx package names must be less than 50 characters."
            Get-AppxPackage -AllUsers | Select-Object Name | Sort-Object Name | Out-String | Write-Host
            exit 1
        }

        $AppList.Add($AppsToRemove)
    }

    # Exit if no valid apps to remove
    if ($AppList.Count -eq 0) {
        Write-Host "[Error] No valid apps to remove!"
        Get-AppxPackage -AllUsers | Select-Object Name | Sort-Object Name | Out-String | Write-Host
        exit 1
    }

    # Function to check if the script is running with Administrator privileges
    function Test-IsElevated {
        $id = [System.Security.Principal.WindowsIdentity]::GetCurrent()
        $p = New-Object System.Security.Principal.WindowsPrincipal($id)
        $p.IsInRole([System.Security.Principal.WindowsBuiltInRole]::Administrator)
    }

    if (!$ExitCode) {
        $ExitCode = 0
    }
}
process {
    # Check for Administrator privileges before attempting to remove any packages
    if (!(Test-IsElevated)) {
        Write-Host -Object "[Error] Access Denied. Please run with Administrator privileges."
        exit 1
    }

    # Attempt to remove each specified app
    foreach ($App in $AppList) {
        $AppxPackage = Get-AppxPackage -AllUsers | Where-Object { $_.Name -Like "*$App*" } | Sort-Object Name -Unique
        $ProvisionedPackage = Get-AppxProvisionedPackage -Online | Where-Object { $_.DisplayName -like "*$App*" } | Sort-Object DisplayName -Unique
        
        # Warn if the app is not installed
        if (!$AppxPackage -and !$ProvisionedPackage) {
            Write-Host "`n[Warn] $App is not installed!"
            continue
        }

        # Output an error if too many apps were selected for uninstall
        if ($AppxPackage.Count -gt 1) {
            Write-Host "[Error] Too many Apps were found with the name '$App'. Please re-run with a more specific name."
            Write-Host ($AppxPackage | Select-Object Name | Sort-Object Name | Out-String)
            $ExitCode = 1
            continue
        }
        if ($ProvisionedPackage.Count -gt 1) {
            Write-Host "[Error] Too many Apps were found with the name '$App'. Please re-run with a more specific name."
            Write-Host ($ProvisionedPackage | Select-Object DisplayName | Sort-Object DisplayName | Out-String)
            ExitCode = 1
            continue
        }

        # Output an error if two different packages got selected.
        if ($ProvisionedPackage -and $AppxPackage -and $AppxPackage.Name -ne $ProvisionedPackage.DisplayName) {
            Write-Host "[Error] Too many Apps were found with the name '$App'. Please re-run with a more specific name."
            Write-Host ($ProvisionedPackage | Select-Object DisplayName | Sort-Object DisplayName | Out-String)
            ExitCode = 1
            continue
        }

        try {
            # Remove the provisioning package first.
            if ($ProvisionedPackage) {
                Write-Host "`nAttempting to remove provisioning package $($ProvisionedPackage.DisplayName)..."
                Get-AppxProvisionedPackage -Online | Where-Object { $_.DisplayName -like "*$App*" } | Remove-AppxProvisionedPackage -Online -AllUsers | Out-Null
                Write-Host "Successfully removed provisioning package $($ProvisionedPackage.DisplayName)."
            }

            # Remove the installed instances.
            if ($AppxPackage) {
                Write-Host "`nAttempting to remove $($AppxPackage.Name)..."
                Get-AppxPackage -AllUsers | Where-Object { $_.Name -Like "*$App*" } | Remove-AppxPackage -AllUsers
                Write-Host "Successfully removed $($AppxPackage.Name)."
            }
        }
        catch {
            Write-Host "[Error] $($_.Exception.Message)"
            $ExitCode = 1
        }
    }

    exit $ExitCode
}
end {
    
    
    
}

 

Análisis detallado

Este script PowerShell está diseñado para eliminar el bloatware común que suele encontrarse en los nuevos PC con Windows. Aquí tienes una explicación paso a paso de cómo funciona el script:

1. Inicialización del script y definición de parámetros

El script para eliminar el bloatware comienza definiendo dos parámetros: $AppsToRemove y $OverrideWithCustomField. $AppsToRemove contiene una lista separada por comas de nombres de paquetes de aplicaciones que se van a eliminar, mientras que $OverrideWithCustomField se puede utilizar para especificar un nombre de campo personalizado que contenga la lista de aplicaciones que se van a eliminar.

2. Gestión dinámica de parámetros

El script para eliminar el bloatware comprueba si existen variables de entorno que puedan anular los parámetros iniciales, lo que garantiza la flexibilidad en diversos escenarios de despliegue.

3. Recuperación de campos personalizados

Si se especifica un campo personalizado, el script intenta recuperar la lista de aplicaciones a partir de él utilizando la función Get-NinjaProperty. De este modo, los profesionales de TI pueden ajustar dinámicamente la lista de aplicaciones a eliminar.

4. Validación y elaboración de listas

El script para eliminar el bloatware valida los nombres de las aplicaciones, comprobando si hay caracteres no válidos, longitud y formato. Los nombres de aplicaciones válidos se añaden a la lista $AppList.

5. Comprobación de privilegios de administrador

Antes de proceder a la eliminación, el script se asegura de que se está ejecutando con privilegios de administrador mediante la función Test-IsElevated.

6. Proceso de eliminación de la aplicación

El script para eliminar el bloatware itera a través de cada aplicación de la lista, intentando eliminar tanto las instancias provisionadas como las instaladas de la aplicación.

Posibles casos de uso

Estudio de un caso hipotético

Imagina a un profesional de TI que gestiona una flota de portátiles nuevos para un cliente corporativo. Cada portátil lleva preinstaladas varias aplicaciones bloatware que el cliente no necesita. Con este script de PowerShell para eliminar el bloatware, el profesional de TI puede eliminar rápidamente estas aplicaciones no deseadas de todos los portátiles en una fracción del tiempo que tardaría en hacerlo manualmente. El resultado es un sistema más limpio, rápido y listo para su despliegue.

Comparaciones

Eliminación manual vs. script PowerShell:

  • Eliminación manual: lleva mucho tiempo y es tedioso, especialmente en varios dispositivos.
  • Script PowerShell: automatizada, eficiente y capaz de gestionar operaciones masivas sin problemas.

Software de terceros vs. script PowerShell:

  • Software de terceros: a menudo requiere instalación, licencias y puede introducir gastos generales adicionales.
  • Script PowerShell: ligero, no requiere instalación adicional y es totalmente personalizable.

FAQ

P: ¿Este script puede eliminar alguna aplicación?

R: El script está diseñado para eliminar el bloatware común, pero puede personalizarse para eliminar cualquier aplicación ajustando el parámetro $AppsToRemove.

P: ¿Qué ocurre si el script encuentra una aplicación que no está instalada?

R: El script para eliminar el bloatware mostrará un mensaje de advertencia indicando que la aplicación no está instalada y continuará con la siguiente aplicación.

P: ¿Necesito privilegios de administrador para ejecutar este script?

R: Sí, el script para eliminar el bloatware comprueba si se dispone de privilegios de administrador y no procederá sin ellos.

Implicaciones

Eliminar el bloatware mejora el rendimiento del sistema, libera recursos y mejora la experiencia del usuario. Para la seguridad informática, la eliminación de aplicaciones innecesarias reduce las vulnerabilidades potenciales, lo que hace que los sistemas sean más seguros.

Recomendaciones

  • Haz pruebas en un entorno controlado: antes de desplegar el script para eliminar el bloatware en varios dispositivos, pruébalo en un entorno controlado para asegurarte de que se comporta como se espera.
  • Guarda una copia de seguridad: guarda siempre una copia de seguridad de los datos importantes antes de ejecutar el script para evitar cualquier pérdida accidental de datos.
  • Actualizaciones periódicas: actualiza periódicamente la lista de aplicaciones a eliminar, ya que pueden aparecer nuevos bloatware con las actualizaciones del sistema o los nuevos modelos de dispositivos.

Reflexiones finales

La gestión del bloatware es un aspecto crucial para mantener sistemas limpios, eficientes y seguros. Este script de PowerShell para eliminar el bloatware ofrece una solución potente y automatizada para profesionales de TI y MSP. Al integrar estas herramientas en tu flujo de trabajo, puedes agilizar la preparación del sistema, reducir el esfuerzo manual y mejorar el rendimiento general del sistema. Para soluciones integrales de gestión de TI, considera herramientas como NinjaOne que ofrecen funciones sólidas para el mantenimiento y la gestión del sistema.

Categorías:

Quizá también te interese…

×

¡Vean a NinjaOne en acción!

Al enviar este formulario, acepto la política de privacidad de NinjaOne.

Términos y condiciones de NinjaOne

Al hacer clic en el botón “Acepto” que aparece a continuación, estás aceptando los siguientes términos legales, así como nuestras Condiciones de uso:

  • Derechos de propiedad: NinjaOne posee y seguirá poseyendo todos los derechos, títulos e intereses sobre el script (incluidos los derechos de autor). NinjaOne concede al usuario una licencia limitada para utilizar el script de acuerdo con estos términos legales.
  • Limitación de uso: solo podrás utilizar el script para tus legítimos fines personales o comerciales internos, y no podrás compartirlo con terceros.
  • Prohibición de republicación: bajo ninguna circunstancia está permitido volver a publicar el script en ninguna biblioteca de scripts que pertenezca o esté bajo el control de cualquier otro proveedor de software.
  • Exclusión de garantía: el script se proporciona “tal cual” y “según disponibilidad”, sin garantía de ningún tipo. NinjaOne no promete ni garantiza que el script esté libre de defectos o que satisfaga las necesidades o expectativas específicas del usuario.
  • Asunción de riesgos: el uso que el usuario haga del script corre por su cuenta y riesgo. El usuario reconoce que existen ciertos riesgos inherentes al uso del script, y entiende y asume cada uno de esos riesgos.
  • Renuncia y exención: el usuario no hará responsable a NinjaOne de cualquier consecuencia adversa o no deseada que resulte del uso del script y renuncia a cualquier derecho o recurso legal o equitativo que pueda tener contra NinjaOne en relación con su uso del script.
  • CLUF: si el usuario es cliente de NinjaOne, su uso del script está sujeto al Contrato de Licencia para el Usuario Final (CLUF).