Скрипт получения информации из образа Windows

    Имею серию статей посвящённых теме обслуживания образов Windows командами системы DISM. В моих статьях приводились примеры скриптов на языке интерпретатора командной строки cmd.exe. В результате работы исходный образ Windows (живая система или автономный файл *.wim) изменялся — в него интегрировались обновления, отключались системные компоненты, удалялись универсальные приложения. Но как увидеть внесённые изменения в образ? В данной статье Я представляю скрипт, который используя команды системы DISM извлекает из образа Windows различную информацию и показывает её пользователю на экран, либо экспортирует в файл.

    Данный скрипт будет полезен системным администраторам создающим свои «сборки», либо тестирующим чужие. Иногда может возникнуть необходимость посмотреть некоторую информацию об установленной ОС — в этом случае также пригодиться данный скрипт. Все команды DISM для получения информации из образа Windows реализованы в данном скрипте. Информация из образа, которую можно получить, используя данный скрипт:

    • Драйвера устройств (наличие);
    • Пакеты обновлений (наличие);
    • Системные компоненты (состояние);
    • Языковая поддержка (состояние);
    • Редакции Windows (состояние);
    • Классические приложения (наличие);
    • Универсальные приложения (наличие);
    • Ассоциации файлов (состояние).

    В скобках указан аспект информации. Если некий тип объектов может быть добавлен или удалён из образа, то информация будет показывать наличие объектов данного типа в образе. Если некоторое свойство операционной системы может быть переключено в образе (например разрешено/запрещено), то информация будет отображать состояние данного свойства. Два последних пункта в списке доступны только на ОС начиная с Windows 8. Я назвал данный скрипт GetWimInfo.cmd, вот он:

    Скрипт


    @echo off
    title Getting information from Windows image
    
    set _file=install.wim
    set _img=Online
    set _mnt=mount
    set _tool=7
    set _word=Wim
    
    ver | find "6.1" > nul || set _tool=8
    if %_tool% GTR 7 set _word=Image
    
    :pre_menu
    cls
    if not exist %_file% goto :adv_menu
    dism /English /LogLevel:1 /Get-%_word%Info /%_word%File:%_file%
    echo -------------------------------------------------------------------------------
    if %ERRORLEVEL% NEQ 0 pause & exit
    set /p _ind=Input index or press [Enter] for quit: || exit
    if %_ind% EQU 0 goto :adv_menu
    if %_ind% GTR 0 if %_ind% LEQ 24 goto :ind_menu
    goto :pre_menu
    
    :ind_menu
    cls
    dism /English /LogLevel:1 /Get-%_word%Info /%_word%File:%_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
    
    :adv_menu
    cls
    if %_img%==Online (echo DISM: Online Servicing)^
    else (dism /English /LogLevel:1 /Get-Mounted%_word%Info)
    echo -------------------------------------------------------------------------------
    echo ~~~~Menu~~~~
    echo [d] drivers ([D] - export)
    echo [p] packages ([P] - export)
    echo [f] features ([F] - export)
    echo [l] languages
    echo [e] editions
    echo [a] app
    if %_tool% GTR 7 echo [x] appx ([X] - export)
    if %_tool% GTR 7 echo [s] assoc ([S] - export)
    echo [q] quit (unmount)
    echo -------------------------------------------------------------------------------
    choice /c dDpPfFleaxXsSq /n /cs /m "Your choice: "
    if %ERRORLEVEL% EQU 1 goto :drivers
    if %ERRORLEVEL% EQU 2 goto :drivers-export
    if %ERRORLEVEL% EQU 3 goto :packages
    if %ERRORLEVEL% EQU 4 goto :packages-export
    if %ERRORLEVEL% EQU 5 goto :features
    if %ERRORLEVEL% EQU 6 goto :features-export
    if %ERRORLEVEL% EQU 7 goto :languages
    if %ERRORLEVEL% EQU 8 goto :editions
    if %ERRORLEVEL% EQU 9 goto :app
    if %ERRORLEVEL% EQU 10 if %_tool% GTR 7 (goto :appx) else (goto :adv_menu)
    if %ERRORLEVEL% EQU 11 if %_tool% GTR 7 (goto :appx-export) else (goto :adv_menu)
    if %ERRORLEVEL% EQU 12 if %_tool% GTR 7 (goto :assoc) else (goto :adv_menu)
    if %ERRORLEVEL% EQU 13 if %_tool% GTR 7 (goto :assoc-export) else (goto :adv_menu)
    goto :unmount
    
    :drivers
    cls
    dism /%_img% /English /LogLevel:1 /Get-Drivers /All | more
    echo -------------------------------------------------------------------------------
    choice /c b /n /m "Back [b] "
    goto :adv_menu
    
    :drivers-export
    cls
    if exist drivers%_numd%.txt set /a _numd+=1 & goto :drivers-export
    echo Getting list of drivers. Please wait...
    dism /%_img% /English /LogLevel:1 /Get-Drivers /All /Format:Table > drivers%_numd%.txt
    goto :adv_menu
    
    :packages
    cls
    dism /%_img% /English /LogLevel:1 /Get-Packages | more
    echo -------------------------------------------------------------------------------
    choice /c b /n /m "Back [b] "
    goto :adv_menu
    
    :packages-export
    cls
    if exist packages%_nump%.txt set /a _nump+=1 & goto :packages-export
    echo Getting list of packages. Please wait...
    dism /%_img% /English /LogLevel:1 /Get-Packages /Format:Table > packages%_nump%.txt
    goto :adv_menu
    
    :features
    cls
    dism /%_img% /English /LogLevel:1 /Get-Features | more
    echo -------------------------------------------------------------------------------
    choice /c b /n /m "Back [b] "
    goto :adv_menu
    
    :features-export
    cls
    if exist features%_numf%.txt set /a _numf+=1 & goto :features-export
    echo Getting list of features. Please wait...
    dism /%_img% /English /LogLevel:1 /Get-Features /Format:Table > features%_numf%.txt
    goto :adv_menu
    
    :languages
    cls
    dism /%_img% /English /LogLevel:1 /Get-Intl
    echo -------------------------------------------------------------------------------
    choice /c b /n /m "Back [b] "
    goto :adv_menu
    
    :editions
    cls
    dism /%_img% /English /LogLevel:1 /Get-CurrentEdition
    echo -------------------------------------------------------------------------------
    dism /%_img% /English /LogLevel:1 /Get-TargetEditions
    echo -------------------------------------------------------------------------------
    choice /c b /n /m "Back [b] "
    goto :adv_menu
    
    :app
    cls
    if %_img%==Online goto :adv_menu
    dism /%_img% /English /LogLevel:1 /Get-Apps
    echo -------------------------------------------------------------------------------
    dism /%_img% /English /LogLevel:1 /Get-AppPatches
    echo -------------------------------------------------------------------------------
    choice /c b /n /m "Back [b] "
    goto :adv_menu
    
    :appx
    cls
    dism /%_img% /English /LogLevel:1 /Get-ProvisionedAppxPackages | more
    echo -------------------------------------------------------------------------------
    choice /c b /n /m "Back [b] "
    goto :adv_menu
    
    :appx-export
    cls
    if exist appxes%_numx%.txt set /a _numx+=1 & goto :appx-export
    echo Getting list of appx. Please wait...
    dism /%_img% /English /LogLevel:1 /Get-ProvisionedAppxPackages > appxes%_numx%.txt
    goto :adv_menu
    
    :assoc
    cls
    dism /%_img% /English /LogLevel:1 /Get-DefaultAppAssociations | more
    echo -------------------------------------------------------------------------------
    choice /c b /n /m "Back [b] "
    goto :adv_menu
    
    :assoc-export
    cls
    if exist associat%_nums%.txt set /a _nums+=1 & goto :assoc-export
    echo Getting list of assoc. Please wait...
    dism /%_img% /English /LogLevel:1 /Get-DefaultAppAssociations > associat%_nums%.txt
    goto :adv_menu
    
    :mount
    cls
    md %_mnt%
    dism /English /LogLevel:1 /Mount-%_word% /%_word%File:%_file% /Index:%_ind% /MountDir:%_mnt% /ReadOnly
    if %ERRORLEVEL% NEQ 0 rd %_mnt% & pause & exit
    set _img=Image:%_mnt%
    goto :adv_menu
    
    :unmount
    cls
    if not exist %_file% exit
    if not %_img%==Online (
    dism /English /LogLevel:1 /Unmount-%_word% /MountDir:%_mnt% /Discard
    rd %_mnt%
    )
    set _img=Online
    goto :pre_menu
    

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


    Если в папке запуска скрипта присутствует автономный образ операционной системы Windows — файл install.wim, то из него запрашивается информация об имеющихся индексах и пользователю предлагается ввести номер с которым будет вестись работа. В следующем подменю о выбранном индексе отображается расширенная информация и пользователю предлагается смонтировать данный образ для продолжения работы. После монтирования образа на экране отображается основное меню скрипта. Если в папке запуска скрипта отсутствует файл install.wim, то сразу происходит переход в основное меню, а запросы информации будут направлены к текущей ОС. Работать с основным меню очень просто — достаточно нажать соответствующую клавишу для вывода информации на экран. По некоторым пунктам объём данных может быть большим, поэтому добавлены пункты для экспорта информации в создаваемый текстовый файл в папке запуска скрипта. Экспорт в файл — буква в верхнем регистре.

    Разбор кода


    Вначале командой set происходит установка переменных. Можно изменить предполагаемое имя файла образа install.wim (например, на install.esd). Можно изменить имя папки монтирования (по-умолчанию mount) или задать путь, если папка монтирования должна находится за пределами папки запуска.
    Также вначале определяется версия ОС, на которой запущен скрипт, по логике — если не Windows 7, то что-то новее. Исходя из этого, делается вывод о том, какая версия системы DISM будет принимать команды скрипта, что влияет на доступность последних двух пунктов меню.

    :pre_menu


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

    :ind_menu


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

    :adv_menu


    Основное (расширенное) меню скрипта. После нажатия клавиши соответствующей выбранному пункту происходит переход к соответствующей метке в теле скрипта с последующим выполнением требуемых команд и возврат в данное меню. Все пункты вывода информации на экран однотипны и включают некоторую команду DISM. Нет необходимости их разбирать. Чем отображение информации на экране больший интерес представляет экспорт в текстовый файл. Информация записывается в табличной форме, что удобно для восприятия и сравнения. Для каждого типа информации — текстовый файл с определённым именем. Повторный экспорт по некоторому пункту не заменяет файл, а создаёт новый, добавляя числовой индекс к имени. Это удобно когда происходит сбор информации с нескольких разных индексов образа, например.

    :mount


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

    :unmount


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

    Размонтирование с ключом /Discard, так как монтирование осуществлялось только для чтения. Отсутствие ключа неприемлемо.

    Заключение


    Данный скрипт является логическим дополнением к коллекции скриптов представленных мной в предыдущих статьях. Хотя, по правде, всё это было написано более трёх месяцев назад, а данный скрипт был у меня первый. Просто постепенно раскрываю карты. Конечно, многие системные администраторы давно написали для себя подобные решения и у каждого они свои. Чужие наработки мне показались неудобными, в некоторых случаях громоздкими. Кто то пытался реализовать все возможности системы DISM в одном «мега»-скрипте, Я же решил сделать несколько скриптов, каждый под определённую задачу. Наверно не очень хорошо, что некоторый код повторяется, потому что при реализации некоторых идей и/или исправлении ошибок мне приходилось редактировать все файлы сразу. Рекламисты PowerShell проходят мимо. Я писал этот скрипт для себя и решил поделиться им с вами, таким какой он есть. Надеюсь многим он будет полезен — и для работы и как пример в учёбе.
    • +14
    • 7,4k
    • 6
    Поделиться публикацией
    Ой, у вас баннер убежал!

    Ну. И что?
    Реклама
    Комментарии 6
    • 0

      На ХР работает?

      • +1
        wim файлы появились после неё.
        • 0
          Если вы про применение на дистрибутиве XP, то нет. Хотя некоторые версии XP устанавливаются из WIM, но там свой, особо устаревший формат, и нет поддержки обслуживания через DISM. Кстати, мне формат WIM для Windows Fundamentals For Legacy PC нравится больше, чем новые. Там вместо нескольких полных образов ОС используется один базовый и несколько образов в отдельными компонентами, которые можно выбрать при установке. Даёт намного более широкий выбор, чем несколько редакций в висте и выше.
          А если вы про работу скрипта на XP для изменения образа семёрки, то это теоретически возможно.
      • –1
        /me при виде полотенец для cmd издает шипяще-стонущий крик вампира тающего в лучах солнца.
        • 0
          1. Раздел — «Разбор кода» можно выбросить. И это наблюдается в каждой статье. Комментарии лучше вставить в соответствующие места скрипта. Код должен быть самодокументированным!.
          2. Для работы c WIM существует библиотека wimlib, которую можно установить через менеджер пакетов Chocolatey чтобы установить в систему для запуска с любого места.
          Команда соответствующая названию статьи:
          wiminfo WIMFILE [IMAGE [NEW_NAME [NEW_DESC]]] [OPTION...]

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

          Самое читаемое