Как использовать PowerShell для массовой переустановки приложений

Представьте ситуацию: на корпоративных компьютерах сломалось обновление, версия ПО устарела, или после миграции на новый сервер часть приложений просто перестала запускаться. Перестанавливать вручную десятки, а то и сотни машин — это потерянные часы. PowerShell позволяет автоматизировать этот процесс: написать один скрипт, запустить его на нужных компьютерах и получить чистую, актуальную версию со всеми настройками. Ниже — практическое руководство, как это сделать без лишней теории и с пониманием подводных камней.

Когда массовая переустановка действительно нужна

Не стоит хвататься за скрипт ради скрипта. Массовая переустановка приложений через PowerShell оправдана в нескольких случаях:

  • Необходимо обновить версию ПО на большом парке машин до конкретной сборки.
  • Приложение повреждено после обновления ОС или другого ПО, и обычный repair не помогает.
  • Требуется сменить версию с изменением параметров установки (другой путь, новые компоненты).
  • Происходит миграция с одного дистрибутива на другой, и старый нужно полностью удалить перед установкой нового.
  • В домене нет SCCM / Intune, но есть централизованный доступ к компьютерам через WinRM.

Если у вас 2–3 компьютера, проще переустановить вручную. Если 10 и больше — автоматизация начинает экономить реальное время.

Что нужно перед запуском скрипта

Прежде чем писать скрипт, убедитесь, что выполнены подготовительные условия. Без этого скрипт либо не сработает, либо приведёт к неожиданным результатам.

  1. Права администратора. Для удаления и установки приложений скрипт должен запускаться с повышенными привилегиями. На удалённых машинах — через учётную запись с локальными правами admin или через систему управления доступом (LAPS, gMSA).
  2. Доступ к сетевой папке с дистрибутивами. Установочные файлы (.msi, .exe) должны быть доступны с каждого целевого компьютера. Лучше всего — общая SMB-шара с правами на чтение для учётной записи, под которой выполняется скрипт.
  3. WinRM включён и настроен. Если вы планируете запускать скрипт удалённо через Invoke-Command, убедитесь, что WinRM запущен на целевых машинах и разрешён в брандмауэре.
  4. Список целевых компьютеров. Соберите список машин — из Active Directory, из CSV-файла или из текстового файла. Проверьте, что все они в сети и доступны.
  5. Тестовый запуск на одной машине. Никогда не запускайте массовую переустановку сразу на всех. Сначала проверьте на тестовом компьютере.

Как найти точное имя приложения в системе

Это один из самых важных и самых недооценённых шагов. Если вы неправильно укажете имя приложения, скрипт либо не найдёт его, либо удалит не то, либо вообще не сработает.

Есть несколько способов получить точное имя:

  • Реестр. Откройте regedit и перейдите в HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall. Просмотрите подразделы — в параметре DisplayName будет точное имя приложения.
  • Командная строка. Выполните wmic product get name — получите список всех приложений, установленных через MSI. Минус: работает медленно и запускает проверку всех пакетов.
  • PowerShell. Команда Get-ItemProperty HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\* | Select-Object DisplayName даст список установленных программ с отображением имён.

Для приложений, установленных через MSI, также важен ProductCode — GUID пакета. Его можно найти в том же разделе реестра, в параметре PSChildName или через Get-ItemProperty с фильтром по имени.

Базовый скрипт: удаление и установка

Вот минимальный, но рабочий пример скрипта, который удаляет приложение и устанавливает его заново:

# Параметры
$AppName = "Имя Приложения"
$InstallerPath = "\\server\share\application.msi"
$ComputerName = "COMPUTER01"

# Удаление
Invoke-Command -ComputerName $ComputerName -ScriptBlock {
    param($AppName)
    $app = Get-ItemProperty HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\* |
           Where-Object { _.DisplayName -eqAppName }
    if ($app) {
        msiexec.exe /x $app.PSChildName /qn /norestart
        Write-Host "Приложение удалено"
    } else {
        Write-Host "Приложение не найдено"
    }
} -ArgumentList $AppName

# Установка
Invoke-Command -ComputerName $ComputerName -ScriptBlock {
    param($InstallerPath)
    msiexec.exe /i $InstallerPath /qn /norestart
    Write-Host "Установка завершена"
} -ArgumentList $InstallerPath

Разберём, что здесь происходит:

  • /qn — тихая установка без интерфейса.
  • /norestart — предотвращает автоматическую перезагрузку (иначе скрипт может прерваться).
  • Invoke-Command с параметром -ComputerName выполняет команды удалённо через WinRM.
  • /x — удаление по ProductCode (GUID), что надёжнее, чем по имени.

Массовый запуск на нескольких компьютерах

Чтобы не вызывать скрипт для каждой машины отдельно, используйте цикл по списку компьютеров:

$Computers = Get-Content "C:\temp\computers.txt"
$AppName = "Имя Приложения"
$InstallerPath = "\\server\share\application.msi"

foreach (Computer inComputers) {
    Write-Host "Обработка $Computer..." -ForegroundColor Cyan

    try {
        result = Invoke-Command -ComputerNameComputer -ScriptBlock {
            param(AppName,InstallerPath)

            # Удаление
            $app = Get-ItemProperty HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\* |
                   Where-Object { _.DisplayName -eqAppName } -ErrorAction SilentlyContinue

            if ($app) {
                process = Start-Process msiexec.exe -ArgumentList "/x",app.PSChildName, "/qn", "/norestart" -Wait -PassThru
                if ($process.ExitCode -ne 0) {
                    Write-Warning "Ошибка удаления: код (process.ExitCode)"
                }
            }

            # Установка
            installProcess = Start-Process msiexec.exe -ArgumentList "/i",InstallerPath, "/qn", "/norestart" -Wait -PassThru
            return $installProcess.ExitCode

        } -ArgumentList AppName,InstallerPath -ErrorAction Stop

        if ($result -eq 0) {
            Write-Host "Успешно на $Computer" -ForegroundColor Green
        } else {
            Write-Warning "Проблема на Computer, код:result"
        }
    } catch {
        Write-Error "Не удалось подключиться к $_"
    }
}

Обратите внимание на использование Start-Process с параметром -Wait вместо прямого вызова msiexec.exe. Это позволяет дождаться завершения установки перед переходом к следующему шагу и получить код возврата для диагностики.

Работа с .exe-установщиками

Не все приложения ставятся через MSI. Для .exe-установщиков нужно знать ключи тихой установки. Вот основные варианты:

Тип установщика Ключ тихой установки Ключ удаления Примечание
InstallShield /s /v/qn /s /x Иногда требуется /sms для ожидания завершения
Inno Setup /VERYSILENT /SUPPRESSMSGBOXES /VERYSILENT /SUPPRESSMSGBOXES /uninstall Можно добавNORESTART для подавления перезагрузки
NSIS /S /S _?="путь_к_папке_установки" Удаление может не поддерживаться через ключ
WiX Burn /q /norestart /x /q /norestart Аналогично MSI-пакетам

Если вы не знаете ключи тихой установки для конкретного .exe, попробуйте запустить setup.exe /? — часто выводится справка по ключам. Также полезный ресурс — silentinstall.org и документация вендора.

Обработка ошибок и логирование

При массовой переустановке критически важно вести журнал событий. Что пошло не так на машине №14 из 50 — без логов вы не узнаете.

LogFile = "C:tempapp_reinstall_log_(Get-Date -Format 'yyyyMMdd_HHmmss').log"

function Write-Log {
    param(Message,Level = "INFO")
    $timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
    entry = "[timestamp] [Level]Message"
    Add-Content -Path LogFile -Valueentry
    switch ($Level) {
        "ERROR"   { Write-Host $entry -ForegroundColor Red }
        "WARNING" { Write-Host $entry -ForegroundColor Yellow }
        default   { Write-Host $entry }
    }
}

# Использование в основном скрипте
foreach (Computer inComputers) {
    Write-Log "Начинаем обработку $Computer"
    try {
        # ... основной код ...
        Write-Log "Успешно на $Computer"
    } catch {
        Write-Log "Ошибка на Computer :_" -Level "ERROR"
    }
}

Также полезно проверять коды возврата msiexec. Основные варианты:

  • 0 — успешно.
  • 3010 — успешно, но требуется перезагрузка.
  • 1602 — пользователь отменил установку (может означать проблему с правами).
  • 1603 — фатальная ошибка при установке (повреждённый пакет, конфликт, нет места на диске).
  • 1618 — другая установка уже выполняется (конфликт с другим процессом).

Частые ошибки и как их избежать

Вот реальные проблемы, с которыми сталкиваются при массовой переустановке через PowerShell:

  • Приложение не находится по имени. Имя в реестре может отличаться от того, что вы видите в «Программы и компонентах». Используйте фильтр по реестру и проверяйте точное написание, включая пробелы и знаки препинания.
  • WinRM не работает на целевых машинах. Проверьте: служба WinRM запущена (Get-Service WinRM), в брандмауэре разрешён порт 5985 (HTTP) или 5986 (HTTPS), и выполнен Enable-PSRemoting -Force.
  • Установка запускается, но не дожидается завершения. Без параметра -Wait в Start-Process скрипт переходит к следующему шагу мгновенно. Всегда используйте -Wait для установщиков.
  • Двойная аутентификация (double-hop). Когда скрипт подключается к удалённому компьютеру, а оттуда обращается к сетевой папке — возникает ошибка доступа. Решение: используйте CredSSP, либо копируйте дистрибутив локально на целевую машину перед запуском установки.
  • Скрипт удаляет приложение, но не может установить заново. Проверьте, не блокирует ли антивирус запуск установщика. Также убедитесь, что предыдущая версия полностью удалена — иногда требуется перезагрузка между удалением и установкой.
  • Нет места на диске. Перед установкой имеет смысл проверить свободное место на системном диске: Get-PSDrive C | Select-Object Free.

Сценарии в зависимости от ситуации

Ситуация 1: У вас есть SCCM или Intune. В этом случае PowerShell — не лучший выбор для массовой переустановки. Используйте встроенные инструменты развёртывания: в SCCM — задачу переустановки приложения, в Intune — назначение приложения с обязательной переустановкой. PowerShell здесь полезен только как вспомогательное средство для проверки состояния.

Ситуация 2: Домен без централизованного управления, есть доступ к сетевой папке. Используйте PowerShell с Invoke-Command и списком компьютеров из текстового файла. Это самый распространённый сценарий для небольших и средних организаций.

Ситуация 3: Приложение установлено не на всех компьютерах. Добавьте проверку: если приложение не найдено — пропускаем удаление и сразу ставим. Если найдено — удаляем и ставим. Это универсальный подход, который работает и для «чистой» установки, и для переустановки.

Ситуация 4: Нужна переустановка с сохранением пользовательских настроек. Здесь всё зависит от конкретного приложения. Некоторые поддерживают ключ /qn REBOOT=ReallySuppress PRESERVECONFIG=1 или аналогичные. Другие требуют экспорта настроек перед удалением и импорта после. Изучите документацию приложения — универсального решения нет.

Как проверить результат

После выполнения скрипта не полагайтесь на то, что «ошибок не было — значит, всё прошло». Проверьте результат:

# Проверка на списке компьютеров
$Computers = Get-Content "C:\temp\computers.txt"
$AppName = "Имя Приложения"

results = Invoke-Command -ComputerNameComputers -ScriptBlock {
    param($AppName)
    $app = Get-ItemProperty HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\* |
           Where-Object { _.DisplayName -eqAppName } -ErrorAction SilentlyContinue
    if ($app) {
        [PSCustomObject]@{
            Computer   = $env:COMPUTERNAME
            Installed  = $true
            Version    = $app.DisplayVersion
            Status     = "OK"
        }
    } else {
        [PSCustomObject]@{
            Computer   = $env:COMPUTERNAME
            Installed  = $false
            Version    = $null
            Status     = "NOT FOUND"
        }
    }
} -ArgumentList $AppName

$results | Format-Table -AutoSize
results | Where-Object_.Status -eq "NOT FOUND" } | Format-Table -AutoSize

Этот скрипт покажет, на каких компьютерах приложение установлено и с какой версией. Отфильтруйте те, где статус «NOT FOUND» — это машины, на которых что-то пошло не так.

Рекомендации по организации процесса

  • Ведите версионность скриптов. Храните скрипты в Git или хотя бы с датами в именах файлов. Когда через месяц понадобится повторить процедуру, вы скажете себе спасибо.
  • Используйте параметризованные скрипты. Выносите имя приложения, путь к установщику и список компьютеров в переменные или параметры скрипта. Не хардкодьте значения внутри кода.
  • Делайте бэкап перед массовым удалением. Если переустановка идёт на продакшен-серверах, убедитесь, что у вас есть снимок системы или резервная копия. Откат должен быть возможен.
  • Уведомляйте пользователей. Если приложение переустанавливается на рабочих станциях людей, предупредите их заранее. Тихая переустановка может прервать работу, если приложение было запущено.
  • Тестируйте на группе из 3–5 машин. Запустите скрипт сначала на тестовой группе, проверьте результат, и только потом масштабируйте на весь парк.

Итог

PowerShell — удобный и доступный инструмент для массовой переустановки приложений, особенно когда у вас нет корпоративных систем управления вроде SCCM или Intune. Ключевые шаги: подготовить список компьютеров, убедиться в доступности дистрибутивов и WinRM, написать скрипт с обработкой ошибок и логированием, протестировать на нескольких машинах и только потом запускать массово.

Главное правило — не торопиться. Лучше потратить лишние 30 минут на проверку и тестирование, чем потом разбираться, почему на 20 компьютерах из 100 приложение не запускается. Начните с простого скрипта на одной машине, убедитесь, что он работает корректно, и только потом масштабируйте.

Vsenotebooki.ru