19 февраля 2013 г.

Как создавались скрипты modify_WIN8x64 и addFira_in_ISO

    В этой статье я хочу поведать о том как создавались эти 2 скрипта (addFira_in_ISO и modify_WIN8x64 для модификации установочных дистрибутивов Windows. Особенность их состоит в том, что хоть они и выглядят как один исполняемый cmd-скрипт, а на самом деле являются cab-архивами, содержащими в себе несколько файлов. А это значит, что его можно открыть с помощью архиватора, и убедиться в этом:
    Примечание:
    Здесь и далее речь пойдет о скрипте addFira_in_ISO.



    В основе cab-архива лежит cmd-скрипт (addFira.cmd), который является обычным файлом сценария Windows и содержит определенные команды. В первую очередь он должен содержать команду для распаковки данного cab-архива, например в каталог Temp, путь до которого можно получить из переменной %TEMP%:
expand -r -f:* "%~0" "%TEMP%" > nul
    Распаковка производится с помощью стандартной утилиты Expand, встроенной в каждую современную ОС Windows. Информацию о ключах можете посмотреть тут.
    У меня же распаковка ведется после получения прав Администратора, которые получаются следующими строчками кода:
:: Get ADMIN Privs
:-------------------------------------
mkdir "%windir%\BatchGotAdmin"
if '%errorlevel%' == '0' (
  rmdir "%windir%\BatchGotAdmin" & goto gotAdmin
) else ( goto UACPrompt )

:UACPrompt
    echo Set UAC = CreateObject^("Shell.Application"^) > "%temp%\getadmin.vbs"
    echo UAC.ShellExecute %0, "", "", "runas", 1 >> "%temp%\getadmin.vbs"

    "%temp%\getadmin.vbs"
    exit /B

:gotAdmin
    if exist "%temp%\getadmin.vbs" ( del "%temp%\getadmin.vbs" )
    pushd "%CD%"    
    CD /D "%~dp0"
:-------------------------------------
:: End Get ADMIN Privs
   Помимо скрипта архив содержит программу для работы с ISO-образами, и сами файлы, которые будут добавлены в ISO-образ.
   В целом скрипт (addFira.cmd) выглядит следующим образом:
@Echo OFF
Title Add FiraDisk.cmd and winpeshl.ini in boot.wim (Windows Install ISO)
cls

:: Get ADMIN Privs
:-------------------------------------
mkdir "%windir%\BatchGotAdmin"
if '%errorlevel%' == '0' (
  rmdir "%windir%\BatchGotAdmin" & goto gotAdmin
) else ( goto UACPrompt )

:UACPrompt
    echo Set UAC = CreateObject^("Shell.Application"^) > "%temp%\getadmin.vbs"
    echo UAC.ShellExecute %0, "", "", "runas", 1 >> "%temp%\getadmin.vbs"

    "%temp%\getadmin.vbs"
    exit /B

:gotAdmin
    if exist "%temp%\getadmin.vbs" ( del "%temp%\getadmin.vbs" )
    pushd "%CD%"    
    CD /D "%~dp0"
:-------------------------------------
:: End Get ADMIN Privs

::Распаковка файлов из cab-архива в каталог "%TEMP%"
expand -r -f:* "%~0" "%TEMP%" > nul

::Проверим еще раз получили ли мы права админа (без них скрипт не работает)
bcdedit > nul
IF ERRORLEVEL 1 ( ECHO Permission denied! ) & goto FAIL
::Сбросить код возврата ( ERRORLEVEL = 0 )
cd .

::Если существует образ с именем WINVISTAx86.iso, то присваиваем переменной name имя модифицируемого образа
IF EXIST "%~dp0WINVISTAx86.iso" SET name=WINVISTAx86.iso

::Если существует образ с именем WINVISTAx64.iso, то присваиваем переменной name имя модифицируемого образа
IF EXIST "%~dp0WINVISTAx64.iso" SET name=WINVISTAx64.iso

::Если существует образ с именем WIN7x86.iso, то присваиваем переменной name имя модифицируемого образа
IF EXIST "%~dp0WIN7x86.iso" SET name=WIN7x86.iso

::Если существует образ с именем WIN7x64.iso, то присваиваем переменной name имя модифицируемого образа
IF EXIST "%~dp0WIN7x64.iso" SET name=WIN7x64.iso

::Если существует образ с именем WIN8x86.iso, то присваиваем переменной name имя модифицируемого образа
IF EXIST "%~dp0WIN8x86.iso" SET name=WIN8x86.iso

::Если существует образ с именем WIN8x64.iso, то присваиваем переменной name имя модифицируемого образа
IF EXIST "%~dp0WIN8x64.iso" SET name=WIN8x64.iso

::Проверяем была ли задана переменная, если нет - выдаем приглашение на ввод имени файла
IF NOT DEFINED name SET /P name="Enter filename ISO-image (example: WIN8 x64.iso): "

::Если было введено имя несуществующего файла, то goto FAIL
IF NOT EXIST "%~dp0%name%" ( echo File "%~dp0%name%" not exist! ) & goto FAIL

::Создать папку для boot.wim и точки монтирования
mkdir "%~dp0%tmp"

::Инициализация переменной для удобного доступа к папке tmp
SET TMP_PATH=%~dp0%tmp

::Достать файл /sources/boot.wim из образа %name% в папку %TMP_PATH%
"%TEMP%\UltraISO.exe" -sil -in "%~dp0%name%" -get /sources/boot.wim -ext "%TMP_PATH%"
:: -sil   Do not show any popup windows
:: -in    Input ISO image
:: -get   Set a file or folder(full path should be specified) to be extracted
:: -ext   Extract ISO image to specified directory

::Создать папку mount в каталоге %TMP_PATH%
mkdir "%TMP_PATH%"\mount

::Примонтировать файл %TMP_PATH%\boot.wim (2 индекс) в папку %TMP_PATH%\mount
dism /mount-wim /wimfile:"%TMP_PATH%\boot.wim" /index:2 /mountdir:"%TMP_PATH%\mount"

::Скопировать файл FiraDisk.cmd в \Windows\System32 внутри примонтированного каталога
copy /y "%TEMP%\FiraDisk.cmd" "%TMP_PATH%\mount\Windows\System32"

::Скопировать файл winpeshl.ini в \Windows\System32 внутри примонтированного каталога
copy /y "%TEMP%\winpeshl.ini" "%TMP_PATH%\mount\Windows\System32"

::Отмонтировать образ с сохранением изменений
dism /unmount-wim /mountdir:"%TMP_PATH%\mount" /commit

::Удалить все ресурсы, связанные с подключенным WIM-образом, который был отключен
dism /cleanup-wim

::Запихать модифицированный файл обратно в образ %name%
"%TEMP%\UltraISO.exe" -sil -in "%~dp0%name%" -chdir /sources -rm /sources/boot.wim -f "%TMP_PATH%\boot.wim"
:: -sil   Do not show any popup windows
:: -in    Input ISO image
:: -chdir Change current directory in ISO image
:: -rm    Remove a file or folder from ISO image (full path should be specified)
:: -f     Add one file or folder (include folder name and all files and folders under it)

:SUCCESS
Echo Success!
goto :DEL

:FAIL
Echo Fail!
goto :DEL

:DEL
if exist "%TEMP%\UltraISO.exe" ( del /q "%TEMP%\UltraISO.exe" )
if exist "%TEMP%\uikey.ini" ( del /q "%TEMP%\uikey.ini" )
if exist "%TEMP%\addFira.cmd" ( del /q "%TEMP%\addFira.cmd" )
if exist "%TEMP%\FiraDisk.cmd" ( del /q "%TEMP%\FiraDisk.cmd" )
if exist "%TEMP%\winpeshl.ini" ( del /q "%TEMP%\winpeshl.ini" )
if exist "%TMP_PATH%" ( rmdir /s /q "%TMP_PATH%" )
::/S      Удаление дерева каталогов, и всех содержащихся в нем файлов и подкаталогов
:: /Q     Отключение запроса подтверждения при удалении
pause
exit /b
   А теперь о том как создать такой сab-архив, который внутри себя бы содержал исполняемые файлы и скрипты. Очень просто - он создается с помощью утилиты makecab. А именно следующей командой:
makecab /f .\1.cdf
где файл 1.cdf - текстовый файл конфигурации для создания cab-архива.
    По сути он содержит список файлов, которые будут добавлены в cab-архив. Синтаксис очень прост. У меня он был следующего содержания:
.Set DiskDirectoryTemplate=output
.Set CabinetNameTemplate=result.cmd
.Set Compress=OFF
input\addFira.cmd
input\UltraISO.exe
input\winpeshl.ini
input\FiraDisk.cmd
input\uikey.ini
где:
DiskDirectoryTemplate=output          -   имя каталога содержащего создаваемый cab-архив
CabinetNameTemplate=result.cmd    -   имя создаваемого архива
Compress=OFF                                  -   без сжатия
input\addFira.cmd                              -  список файлов помещаемых в архив
......................                                     -  (первым в списке должен быть основной cmd-скрипт)

В итоге получается тот скрипт (addFira_in_ISO), который вы уже видели.

Используемый материал:
Makecab
Expand
Как вшить программу в дистрибутив Windows XP
команда makecab
Launch Batch Scripts as Administrator (with GUI UAC prompt)

При копировании статьи просьба указывать источник и автора.
С уважением, GRomR1.

1 комментарий:

  1. Привет. Получение админпривелегий ранее тоже так делал. Но оказалось, что если имя папки содержит "ин тересные" нелатинские буквы будет ошибка. VBS не возвращается. Я немного модифицировал - так всё ОК.

    @echo off
    cls
    pushd "%~dp0"
    "%systemroot%\system32\reg.exe" query "HKU\S-1-5-19" >nul 2>&1
    if %errorlevel% equ 0 ( goto GoAdmin )
    :UACPrompt
    echo Set UAC = CreateObject^("Shell.Application"^) > getadmin.vbs
    echo UAC.ShellExecute "%~nx0", "", "", "runas", 1 >> getadmin.vbs
    "%systemroot%\system32\cscript" //nologo getadmin.vbs
    exit /b
    :GoAdmin
    if exist getadmin.vbs ( del getadmin.vbs )

    Если требуется, то для передачи ключей в скрипт нужно добавить %1 и т.д.

    Dialmak.

    ОтветитьУдалить