Эта статья является логическим продолжением моей предыдущей статьи. Развивая тему добавления (установки/интеграции) пакетов обновлений в образ Windows Я решил написать скрипт оперирующий командами DISM, который автоматизирует процесс и избавляет системных администраторов от рутинных действий. Универсальность скрипта состоит в том, что с его помощью можно установить пакеты обновления на «живую» систему, либо интегрировать в образ Windows — файл install.wim. Гибкость скрипта состоит в том, что его работу можно настроить изменив значение нескольких переменных в начале всего кода.

Как и в предыдущей статье, для примера, мы будем добавлять к образу Windows так называемое Convenience rollup update (KB3125574), а также необходимое Servicing stack update (KB3177467). В ходе работы над скриптом выяснилось, что после интеграции в образ KB3177467, он (образ — install.wim), становится непригодным для дальнейших интеграций. Если устанавливать KB3177467 на «живую» ОС то проблем не возникает. У данной проблемы есть два решения: 1) интегрировать KB3177467 последним 2) заменить «проблемное» обновление его предыдущей версией — KB3020369. Я выбрал второй вариант, реализовав в скрипте ветвление по условию.

Скрипт


@echo off
Title Convenience Rollup - most important updates after SP1

set _arch=x64
set _file=install.wim
set _img=Online
set _mnt=mount
set _lev=2

:pre_menu
cls
dism /Get-WimInfo /LogLevel:%_lev% /WimFile:%_file%
echo -------------------------------------------------------------------------------
if %ERRORLEVEL% NEQ 0 if %ERRORLEVEL% EQU 2 (goto :bit) else (pause & exit)
set /p _ind=Input index or press [Enter] for quit: || exit
if %_ind% EQU 0 goto :bit
if %_ind% GTR 0 if %_ind% LEQ 24 goto :ind_menu
goto :pre_menu

:ind_menu
cls
dism /Get-WimInfo /LogLevel:%_lev% /WimFile:%_file% /Index:%_ind%
echo -------------------------------------------------------------------------------
if %ERRORLEVEL% NEQ 0 pause & goto :pre_menu
choice /c abcdefghijklmnopqrstuvwxyz /n /m "Mount selected image? [m] "
if %ERRORLEVEL% EQU 13 goto :mount
goto :pre_menu

:bit
if %_img%==Online (if "%PROCESSOR_ARCHITECTURE%" == "x86" if not defined PROCESSOR_ARCHITEW6432 set _arch=x86)^
else (dism /Get-WimInfo /LogLevel:%_lev% /WimFile:%_file% /Index:%_ind% /English | find "Architecture : x86" > nul && set _arch=x86)
goto :add

:add
cls
echo Getting packages list. Please wait...
dism /%_img% /Get-Packages /LogLevel:%_lev% /English > %TEMP%\packages.txt
echo -------------------------------------------------------------------------------
if not %_img%==Online (
echo Add: Servicing stack update KB3020369
call :exist .\%_arch%\Windows6.1-KB3020369-%_arch%.cab ||^
dism /%_img% /Add-Package /LogLevel:%_lev% /PackagePath:.\%_arch%\Windows6.1-KB3020369-%_arch%.cab /NoRestart
echo -------------------------------------------------------------------------------
) else (
echo Add: Servicing stack update KB3177467
call :exist .\%_arch%\Windows6.1-KB3177467-%_arch%.cab ||^
dism /%_img% /Add-Package /LogLevel:%_lev% /PackagePath:.\%_arch%\Windows6.1-KB3177467-%_arch%.cab /NoRestart
echo -------------------------------------------------------------------------------
)
echo Add: Convenience rollup update KB3125574
call :exist .\%_arch%\Windows6.1-KB3125574-v4-%_arch%.cab ||^
dism /%_img% /Add-Package /LogLevel:%_lev% /PackagePath:.\%_arch%\Windows6.1-KB3125574-v4-%_arch%.cab /NoRestart
echo -------------------------------------------------------------------------------
del %TEMP%\packages.txt
if not exist %_file% exit
pause
goto :unmount

:exist
dism /%_img% /Get-PackageInfo /LogLevel:%_lev% /PackagePath:%1 /English | find "Package Identity" | findstr /g:/ %TEMP%\packages.txt > nul
exit /b

:mount
cls
md %_mnt%
dism /Mount-Wim /LogLevel:%_lev% /WimFile:%_file% /Index:%_ind% /MountDir:%_mnt%
if %ERRORLEVEL% NEQ 0 rd %_mnt% & pause & exit
set _img=Image:%_mnt%
goto :bit

:unmount
cls
if not %_img%==Online (
dism /Unmount-Wim /LogLevel:%_lev% /MountDir:%_mnt% /Commit
rd %_mnt%
)
set _arch=x64
set _img=Online
goto :pre_menu

Файлы и папки


Файлы пакетов обновлений здесь не прилагаю, так как указанные в скрипте взяты для образца. По месту нахождения скрипта должны быть созданы папки x64 и x86 в которые нужно разместить нужные пакеты обновлений. Сам файл скрипта можно сохранить в кодировке ANSI если не использовать кириллицу для вывода информационных сообщений. А если хочется видеть русский текст, то нужно cmd-файл сохранить в кодировке OEM 866.

Использование


Как уже отмечалось, скрипт может установить обновления или интегрировать их. Если в папке запуска отсутствует файл образа — install.wim, то скрипт выполняет установку обновлений в полностью автоматическом режиме. Если в папке запуска присутствует файл образа — install.wim, то скрипт выполняет считывание из него информацию об имеющихся «индексах» и предлагает ввести номер. После этого отображается расширенная информация о выбранном «индексе» выдаётся запрос на монтирование. Нажатие любой клавиши приводит к возврату, а нажатие клавиши [m] запускает следующую цепочку действий: монтирование образа, интеграция обновлений, размонтирование образа, возврат в меню выбора «индеска». После чего можно выбрать другой «индекс» для интеграции обновлений. Выбор «индекса» под номером 0 запускает установку обновлений на «живую» ОС.

Разбор кода


Вначале командой set происходит установка переменных. Можно изменить предполагаемое имя файла образа install.wim (например, на install.esd). Можно изменить имя папки монтирования или задать путь, если папка монтирования должна находится за пределами папки запуска. Можно изменить «уровень» логирования, для исключения информационных сообщений из файла лога системы DISM.

:pre_menu


Предварительное меню. Получение основной информации о wim-файле с контролем ошибок. Если ошибка 2 — отсутствует wim-файл, то запуск в режиме Online. Не нашел информацию о максимальном количестве «индексов» в одном образе и установил значение 24.

:ind_menu


Индексное меню. Получение расширенной информации о выбранном «индексе» в wim-файле с контролем ошибок. Предложение смонтировать «индекс».

:bit


Определение разрядности ОС. Для интерактивного обслуживания считываются системные переменные среды, а для автономного обслуживания из образа запрашивается необходимая информация и в ней ищется ключевая строка.

:add


Добавление пакетов. Чтобы не делать лишней работы вначале происходит запрос списка уже добавленных (установленных или интегрированных) пакетов, а потом перед каждой командой запуска осуществляется вызов псевдофункции для проверки.

:exist


Псевдофункция проверки. Работа описана в статье Проверка присутствия пакета обновления в системе перед установкой. Код слегка подправлен.

:mount


Монтирование образа. Предварительно создаётся папка монтирования. Контроль ошибок. Изменяется переменная определяющая спецификацию образа, теперь указывает на путь к автономному образу.

:unmount


Размонтирование образа. Если выполнялось интерактивное обслуживание (/Online), то размонтировать не нужно. Возвращение переменных к исходным значениям.

Совместимость


Работа данного скрипта тестировалась на ОС Windows 7 со встроенной утилитой dism.exe версии 6.1.7600.16385. В версиях ОС Windows 8, 8.1, 10 утилита dism.exe системы DISM имеет более высокую версию. Думаю, обратная совместимость сохранена, и скрипт будет также работоспособен. К тому же появится возможность работать с esd-файлами.

Комментарии (4)


  1. navion
    24.11.2017 19:22

    он (образ — install.wim), становится непригодным для дальнейших интеграций

    А в чём это выражается? Новые патчи зависают в состоянии pending install или просто не добавляются?


    1. Ostan Автор
      24.11.2017 20:30

      После интеграции KB3177467 дальнейшие попытки интегрировать другие обновления заканчиваются ошибкой 0x800f082f. Предполагаю, он (образ) «хочет» перезагрузиться, но не может — потому что он образ.


  1. pvs043
    25.11.2017 10:29

    Да уж, у Windows 7 SP1, установленной с оригинального ISO проблемы с обновлениями начались ещё в начале 2016 (клиенту WUA не хватает памяти).
    Но зачем же издеваться над install.wim сегодня, в 2017?

    Для сборки «золотых» образов Windows надо всего лишь поработать ручками по инструкции от Johan Arwidmark (https://deploymentresearch.com/Research/Post/521/Back-to-Basics-Building-a-Windows-7-SP1-Reference-Image-using-MDT-2013-Update-2)
    … или сделать всё автоматически: github.com/pvs043/cMDTBuildLab/wiki


  1. devop-su
    27.11.2017 09:56

    Если не на коленке, а в промышленном окружении,
    то там DSC, MDT и WSUS


    Но вообще, вместо костылевелосипедостроения
    лучше изучать общепринятые инструменты:


    Для работы с образами:
    https://gallery.technet.microsoft.com/scriptcenter/PowerShell-Image-Factory-d6c133b9


    Для работы с обновлениями:
    https://gallery.technet.microsoft.com/scriptcenter/2d191bcd-3308-4edd-9de2-88dff796b0bc