Desinstalar Office en modo silencioso cuando SaRACmd.exe aparece “expirado”

Si al intentar desinstalar Microsoft Office por línea de comandos con SaRACmd.exe recibes “Your version of SaRACmd.exe has expired … exit code: [11]”, aquí tienes un procedimiento probado para completar la desinstalación en modo silencioso y estandarizarla para futuras ejecuciones remotas.

Índice

Contexto y síntoma

Durante una desinstalación no interactiva se invoca Microsoft Support and Recovery Assistant Command Line (SaRACmd.exe) y aparece el mensaje de expiración con código de salida 11. El objetivo habitual es una limpieza total (“scrubbing”) de Office en equipos remotos (SCCM/ConfigMgr, Intune, PS Remoting, PDQ Deploy, etc.) sin intervención del usuario.

Your version of SaRACmd.exe has expired.
Exit code: [11]

Causa probable

Algunas compilaciones de SaRA caducan por diseño pasado cierto tiempo. Aunque descargues desde el origen oficial, es posible que la build concreta que estás usando ya no sea válida. El resultado: el ejecutable no arranca escenarios y devuelve 11, bloqueando tu flujo de desinstalación silenciosa.

Ruta de solución recomendada (resumen)

  • Solución A (rápida y efectiva): ejecutar un script de PowerShell (p. ej., saracmd.ps1) con un escenario propio de “office scrubbing” (limpieza completa). Este enfoque ha funcionado en campo para sortear el error y completar la desinstalación en modo silencioso.
  • Solución B (estándar para automatización): usar Office Deployment Tool (ODT) con un XML de Remove All, totalmente silencioso. Es la opción más consistente para producciones masivas y pipelines de gestión.
  • Solución C (manual): usar la GUI de SaRA “Uninstall Office” cuando no se requiere silencioso. Útil como plan B bajo intervención.

Solución A: saracmd.ps1 — “Office scrubbing” sin intervención

Qué hace: invoca SaRACmd con un escenario de limpieza total de Office, registra el resultado y, si detecta expiración (11), aplica un fallback automático con ODT para garantizar que el equipo queda limpio. Este patrón “try–catch–fallback” permite usar SaRA cuando está disponible y válido, pero no fracasar si su build caducó.

Estructura del script

Guarda SaRACmd.exe y el script saracmd.ps1 en la misma carpeta (o ajusta la variable $SaRAPath). El script intenta el scrubbing y si devuelve 11 (expirado) ejecuta ODT con un XML de Remove All. También fuerza el cierre de apps y permite reinicio diferido.

# saracmd.ps1
Limpieza silenciosa de Office con SaRA; fallback automático a ODT si SaRA está expirado (exit code 11).
Ejecutar con permisos de administrador.

param(
  [string]$WorkingDir = "$PSScriptRoot",
  [string]$LogDir = "$PSScriptRoot\logs",
  [switch]$VerboseLog
)

Rutas esperadas
$SaRAPath = Join-Path $WorkingDir "SaRACmd.exe"
$ODTSetup = Join-Path $WorkingDir "setup.exe"
$ODTRemoveXml = Join-Path $WorkingDir "remove.xml"

Preparar logging
New-Item -ItemType Directory -Force -Path $LogDir | Out-Null
$Transcript = Join-Path $LogDir ("saracmd{0:yyyyMMddHHmmss}.log" -f (Get-Date))
Start-Transcript -Path $Transcript -Force | Out-Null

Función: invocar proceso y capturar salida/exit code
function Invoke-Proc {
  param(
    [string]$FilePath,
    [string[]]$Args
  )
  Write-Host "Invocando: $FilePath $($Args -join ' ')"
  $p = Start-Process -FilePath $FilePath -ArgumentList $Args -Wait -PassThru -WindowStyle Hidden
  return $p.ExitCode
}

1) Intento con SaRA (si está disponible)
$exit = 9999
if (Test-Path $SaRAPath) {
  Write-Host "SaRACmd encontrado en $SaRAPath. Intentando escenario de scrubbing..."
  # NOTA: Los parámetros/escenario pueden variar entre builds de SaRA.
  # Ajusta 'OfficeScrubScenario' y switches si tu versión usa nomenclaturas diferentes.
  $args = @(
    "-S","OfficeScrubScenario",        # nombre del escenario de limpieza completa
    "-AcceptEula",                     # aceptar EULA en modo no interactivo
    "-Quiet",                          # ejecución silenciosa
    "-LogFolder",$LogDir               # carpeta de logs
  )
  $exit = Invoke-Proc -FilePath $SaRAPath -Args $args
  Write-Host "SaRACmd devolvió exit code: $exit"
} else {
  Write-Warning "SaRACmd.exe no encontrado; saltando a ODT..."
}

2) Si SaRA expiró (11) o no existe, usar ODT como fallback
if (($exit -eq 11) -or (-not (Test-Path $SaRAPath))) {
  if (-not (Test-Path $ODTSetup)) { throw "setup.exe (ODT) no está en $WorkingDir" }
  if (-not (Test-Path $ODTRemoveXml)) {
    # Crear un remove.xml mínimo si no existe
    @'
<Configuration>
  <Remove All="TRUE" />
  <Display Level="None" AcceptEULA="TRUE" />
  <Property Name="FORCEAPPSHUTDOWN" Value="TRUE" />
</Configuration>
'@ | Set-Content -LiteralPath $ODTRemoveXml -Encoding UTF8
  }

  Write-Host "Ejecutando ODT /configure remove.xml"
  $odtExit = Invoke-Proc -FilePath $ODTSetup -Args @("/configure", "`"$ODTRemoveXml`"")
  Write-Host "ODT devolvió exit code: $odtExit"

  # Propaga exit code de ODT si SaRA fracasó por expiración
  Stop-Transcript | Out-Null
  exit $odtExit
}

3) Si SaRA funcionó, finalizar
Stop-Transcript | Out-Null
exit $exit

Notas clave:

  • El nombre del escenario (OfficeScrubScenario) y algunos parámetros pueden variar entre versiones de SaRA. Si tu build usa otro identificador/switch, cámbialo en el array $args.
  • El script genera un transcript con todos los pasos y crea remove.xml en caliente si no lo encuentra.
  • Si SaRACmd.exe devuelve 11 (expirado), aplica automáticamente ODT, lo que evita bloqueos en despliegues masivos.

Cómo distribuirlo de forma remota

Empaqueta en una misma carpeta:

  1. saracmd.ps1
  2. SaRACmd.exe (opcional si solo deseas ODT; el script se adapta)
  3. setup.exe (ODT)
  4. remove.xml (si no lo incluyes, el script lo crea)

Después distribúyelo por tu herramienta de gestión (SCCM, Intune, PDQ, etc.) y ejecuta:

powershell.exe -ExecutionPolicy Bypass -File ".\saracmd.ps1"

Solución B: Office Deployment Tool (ODT) — desinstalación 100% silenciosa

ODT es la forma más estable y repetible de quitar Office (Click-to-Run) en flujos CI/CD de administración. Es idóneo como fallback del script anterior o como método principal si ya estandarizaste tu pipeline con ODT.

XML mínimo para quitar todo Office

<Configuration>
  <Remove All="TRUE" />
  <Display Level="None" AcceptEULA="TRUE" />
  <Property Name="FORCEAPPSHUTDOWN" Value="TRUE" />
</Configuration>

Ejecuta en el equipo destino (con privilegios de admin):

setup.exe /configure remove.xml

Variantes útiles:

  • Quitar también instalaciones MSI antiguas (si detectas herencia de versiones 2010/2013/2016 MSI):
<Configuration>
  <Remove All="TRUE" />
  <RemoveMSI />
  <Display Level="None" AcceptEULA="TRUE" />
  <Property Name="FORCEAPPSHUTDOWN" Value="TRUE" />
</Configuration>
  • Quitar productos concretos (en lugar de “All”):
<Configuration>
  <Remove>
    <Product ID="O365ProPlusRetail" />
    <Product ID="VisioProRetail" />
    <Product ID="ProjectProRetail" />
  </Remove>
  <Display Level="None" AcceptEULA="TRUE" />
  <Property Name="FORCEAPPSHUTDOWN" Value="TRUE" />
</Configuration>

Ventajas: salida silenciosa predecible, integración sencilla con cualquier orquestador y logging claro en directorios de Click‑to‑Run.


Solución C: SaRA (GUI) “Uninstall Office”

Si no necesitas modo silencioso, la interfaz gráfica de SaRA incluye la opción “Uninstall Office” que guía el scrubbing interactivo. Es útil para tareas puntuales o asistencia remota con presencia del usuario. Para automatización a escala, sigue siendo preferible ODT.


Buenas prácticas para ejecución remota

  • Forzar cierre de aplicaciones con FORCEAPPSHUTDOWN=TRUE en ODT para evitar diálogos que rompan el silencioso.
  • Rearranque: registra el código de salida y, si corresponde (3010), programa un reinicio controlado fuera del horario laboral.
  • Versión más reciente: renueva periódicamente tus binarios de ODT y, si insistes en SaRA, su ejecutable para prevenir nuevas expiraciones.
  • Idempotencia: ejecutar dos veces el XML de Remove All debe ser inocuo; aprovéchalo en correcciones masivas.
  • Telemetría mínima y auditoría: centraliza los logs en un recurso compartido o SIEM, usando nombre del equipo y marca temporal.

Ejemplos de empaquetado y comandos

SCCM/ConfigMgr

CampoValor recomendado
Programa (Command line)powershell.exe -ExecutionPolicy Bypass -File saracmd.ps1
ComportamientoEjecutar con privilegios de administrador; oculto
DetecciónAusencia de OfficeClickToRun.exe y claves de C2R (ver más abajo)

Microsoft Intune (Win32 app)

  1. Empaqueta la carpeta (script, SaRACmd opcional, ODT, XML) en un .intunewin.
  2. Comando de instalación: powershell.exe -ExecutionPolicy Bypass -File .\saracmd.ps1
  3. Regla de detección (script PowerShell):
# Detecta Office C2R instalado (devuelve exit code 0 si está instalado; 1 si NO)
$exe = "${env:ProgramFiles}\Common Files\Microsoft Shared\ClickToRun\OfficeClickToRun.exe"
if (Test-Path $exe) { exit 0 } else { exit 1 }

Para una detección más estricta, añade comprobaciones de claves en:

  • HKLM\SOFTWARE\Microsoft\Office\ClickToRun\Configuration
  • HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall (y su equivalente en WOW6432Node)

PDQ Deploy

Crea un paso “PowerShell” con:

powershell.exe -ExecutionPolicy Bypass -File ".\saracmd.ps1"

Verificación tras la desinstalación

  • Servicios y procesos: confirma que no quede activo OfficeClickToRun.exe.
  • Directorios vaciados:
    • %ProgramFiles%\Microsoft Office (x64)
    • %ProgramFiles(x86)%\Microsoft Office (x86)
    • %ProgramFiles%\Common Files\Microsoft Shared\ClickToRun
  • Entrada de Programas y características: ausente o limpiada.
  • Licencias de usuario: si usas Shared Computer Activation, borra perfiles huérfanos si procede.

Rutas de log útiles

  • C:\ProgramData\Microsoft\ClickToRun\Log\
  • %temp% del usuario y del sistema (revisa TXT/ETL relacionados con Click‑to‑Run)
  • Carpeta logs que crea el propio saracmd.ps1

Tabla de códigos de salida frecuentes

CódigoOrigenSignificadoAcción sugerida
0SaRA/ODTÉxitoMarcar como desinstalado
11SaRACompilación expiradaEjecutar fallback con ODT (como en saracmd.ps1)
3010Windows Installer / Click‑to‑RunÉxito con reinicio requeridoProgramar reinicio controlado
1603Windows Installer (genérico)Error fatalRevisar logs de C2R y permisos; reintentar con FORCEAPPSHUTDOWN

Problemas habituales y su tratamiento

  • Archivos bloqueados: Outlook/Excel/Word abiertos impiden desinstalar. Solución: FORCEAPPSHUTDOWN=TRUE + comunica ventana de mantenimiento; si persiste, mata procesos antes de ejecutar.
  • Instalaciones mixtas C2R y MSI: añade <RemoveMSI /> para limpiar residuos MSI heredados.
  • Pérdida de conectividad: ODT puede requerir acceso a fuentes; usa un content cache o ejecuta en red donde tus endpoints alcancen los orígenes.
  • Time‑outs de herramientas de despliegue: la limpieza profunda puede tardar. Aumenta el tiempo máximo del paso en SCCM/Intune/PDQ.
  • Diferencias de arquitectura: valida si el equipo es x64 o x86 y usa el ODT adecuado; el XML anterior es agnóstico si pides Remove All.

Checklist operativa

  1. Empaqueta saracmd.ps1, setup.exe (ODT) y opcionalmente SaRACmd.exe.
  2. Verifica permisos de administrador y execution policy.
  3. Forzar cierre de apps (propiedad ODT o precierre de procesos).
  4. Ejecuta el script y captura exit code + logs.
  5. Si el resultado es 11, comprueba que el fallback ODT se disparó correctamente.
  6. Valida la desinstalación (servicios, rutas, entradas de desinstalación).
  7. Si hay reinicio requerido (3010), prográmalo.

Preguntas frecuentes

¿Por qué preferir ODT frente a SaRA para automatización?
ODT es estable, no caduca, se integra fácilmente con pipelines y ofrece una sintaxis declarativa (XML). SaRA es excelente para diagnósticos y limpiezas puntuales, pero sus builds pueden expirar.

¿Puedo mezclar SaRA y ODT en el mismo flujo?
Sí; de hecho, el patrón recomendado es: “intenta SaRA para scrubbing profundo, y si falla por expiración, usa ODT”. Así obtienes lo mejor de ambos mundos sin romper el silencioso.

¿Qué pasa si el usuario tiene Visio/Project independientes?
Si los productos son C2R, el XML de Remove All los elimina. Si necesitases granularidad, usa el bloque <Remove><Product ID="..." /></Remove> listando cada producto.

¿Puedo registrar más detalles del proceso?
Sí; guarda el transcript de PowerShell, los logs de Click‑to‑Run (C:\ProgramData\Microsoft\ClickToRun\Log) y, si usas SaRA, su carpeta de logs. Etiqueta con el nombre del equipo y hora.

¿Cómo minimizo el impacto al usuario?
Programa la tarea fuera de horario, añade FORCEAPPSHUTDOWN y comunica una ventana de mantenimiento. En puestos críticos, crea una tarea escalonada para evitar picos.


Plantillas listas para copiar

remove.xml (estándar “Remove All”)

&lt;Configuration&gt;
  &lt;Remove All="TRUE" /&gt;
  &lt;Display Level="None" AcceptEULA="TRUE" /&gt;
  &lt;Property Name="FORCEAPPSHUTDOWN" Value="TRUE" /&gt;
&lt;/Configuration&gt;

remove.xml con MSI

&lt;Configuration&gt;
  &lt;Remove All="TRUE" /&gt;
  &lt;RemoveMSI /&gt;
  &lt;Display Level="None" AcceptEULA="TRUE" /&gt;
  &lt;Property Name="FORCEAPPSHUTDOWN" Value="TRUE" /&gt;
&lt;/Configuration&gt;

Comando de ejecución

setup.exe /configure remove.xml

Conclusión

Cuando SaRACmd.exe devuelve “expired” (11), no te quedes bloqueado: usa un script de PowerShell con escenario de office scrubbing y fallback automático a ODT. La experiencia de campo confirma que este enfoque completa la desinstalación silenciosa sin interacción del usuario, a la vez que proporciona un camino estandarizado y repetible para futuros despliegues remotos. Para normalizar el proceso a largo plazo, adopta ODT con un XML de “Remove All” y orquéstralo desde tu gestor de endpoints. Así garantizas resultados consistentes, logging centralizado y control fino del reinicio.


Resumen ejecutivo

  • Síntoma: SaRACmd.exe “expirado” (exit code 11) impide desinstalación silenciosa.
  • Solución efectiva reportada: saracmd.ps1 con escenario de office scrubbing; si SaRA falla por expiración, ODT toma el relevo.
  • Alternativas: GUI de SaRA (manual), ODT como método principal para automatización.
  • Buenas prácticas: FORCEAPPSHUTDOWN=TRUE, captura de códigos de salida, reinicio controlado y binarios actualizados.

Apéndice: script de ejemplo para cerrar procesos de Office antes de desinstalar

Si prefieres garantizar el cierre de aplicaciones sin depender de ODT:

$officeProcs = @('winword','excel','powerpnt','outlook','onenote','onenotem','mspub','visio','msaccess','lync','teams')
foreach ($p in $officeProcs) {
  Get-Process $p -ErrorAction SilentlyContinue | ForEach-Object {
    Write-Host "Cerrando $($.ProcessName) (PID=$($.Id))"
    $_.CloseMainWindow() | Out-Null
    Start-Sleep -Seconds 3
    if (-not $.HasExited) { $.Kill() }
  }
}

Úsalo justo antes de ejecutar saracmd.ps1 o setup.exe /configure remove.xml.


Apéndice: eliminación defensiva de rastros residuales

Para entornos con herencias complejas, añade un paso final opcional (solo si tu política lo permite) para limpiar directorios residuales una vez completada la desinstalación y validado el éxito:

$paths = @(
  "$env:ProgramFiles\Microsoft Office",
  "$env:ProgramFiles(x86)\Microsoft Office",
  "$env:ProgramFiles\Common Files\Microsoft Shared\ClickToRun"
)
foreach ($path in $paths) {
  if (Test-Path $path) {
    Write-Host "Eliminando $path"
    Remove-Item -LiteralPath $path -Recurse -Force -ErrorAction SilentlyContinue
  }
}

Revisa que no existan dependencias empresariales sobre estos directorios antes de purgarlos.


Valor añadido: patrón de robustez “try SaRA → fallback ODT”

El patrón que combina ambos enfoques te da resiliencia:

  1. Intenta el scrubbing con SaRA (si la build es válida, obtendrás la limpieza más exhaustiva).
  2. Si SaRA está expirado (11) o ausente, ODT elimina todos los productos Office de forma silenciosa.
  3. En ambos casos, guardas logs, capturas el exit code y dejas el endpoint listo para reinstalar o estandarizar versiones.

Este enfoque fue el que resolvió el problema reportado: al usar el script de PowerShell con escenario de office scrubbing, la desinstalación silenciosa se completó con éxito. Para industrializarlo, adopta ODT con XML de “Remove All” y distribúyelo por tu herramienta de gestión.

Índice