Autounattend.xml — странное поведение при длинной CommandLine

Autounattend.xml — странное поведение при длинной CommandLine

Версия: Windows 10 x64 1909 (испанский) | Сборка: 18363.959

Согласно Microsoft, ограничение элемента CommandLineсоставляет 1024 символа, но в моих тестах, когда он превышает двести с чем-то символов, он начинает вести себя странно. Учитывая, что один и тот же элемент вызывается Pathв Microsoft-Windows-Deploymentкомпоненте, я предполагаю, что документация неверна, и фактическое ограничение составляет 259 символов для обоих элементов.

Источники:

https://docs.microsoft.com/en-us/windows-hardware/customize/desktop/unattend/microsoft-windows-shell-setup-firstlogoncommands-synchronouscommand-commandline

https://docs.microsoft.com/en-us/windows-hardware/customize/desktop/unattend/microsoft-windows-deployment-runsynchronous-runsynchronouscommand-path

Как размножать:

В oobeSystemпропуске добавьте следующее FirstLogonCommands:

<SynchronousCommand wcm:action="add">
  <Order>1</Order>
  <Description>Test</Description>
  <CommandLine>reg add HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Run /v Test1 /t REG_SZ /d &quot;cmd /k echo aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa&quot; /f</CommandLine>
</SynchronousCommand>
<SynchronousCommand wcm:action="add">
  <Order>2</Order>
  <Description>Test</Description>
  <CommandLine>reg add HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Run /v Test2 /t REG_SZ /d &quot;cmd /k echo aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa&quot; /f</CommandLine>
</SynchronousCommand>

Команда 1 будет правильно добавлена ​​в реестр и выполнена:

HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run
    Test1    REG_SZ    cmd /k echo aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

Но команда 2 добавляется HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnceбуквально:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce
    Unattend0000000002{373CFC84-60AF-44A4-A316-9BECBAB1AD4B}    REG_EXPAND_SZ    reg add HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Run /v Test2 /t REG_SZ /d "cmd /k echo aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" /f

C:\Windows\Panther\UnattendedGC\setupact.logне показывает ничего аномального:

2020-08-17 19:09:39, Info                         [Shell Unattend] LogonCommands: Set command 'reg add HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Run /v Test1 /t REG_SZ /d "cmd /k echo aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" /f' 
2020-08-17 19:09:39, Info                         [Shell Unattend] LogonCommands: Set command 'reg add HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Run /v Test2 /t REG_SZ /d "cmd /k echo aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" /f' 

решение1

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

Следующий простой тест демонстрирует ограничение в 259 символов:

<SynchronousCommand wcm:action="add">
    <Order>1</Order>
    <RequiresUserInput>false</RequiresUserInput>
    <CommandLine>cmd /c ECHO This line will eventually be 259 characters long. This line will eventually be 259 characters long. This line will eventually be 259 characters long. This line will eventually be 259 characters long. This line will even > "C:\Windows\Temp\259.log"</CommandLine>
    <Description>259 characters, should produce file</Description>
</SynchronousCommand>
<SynchronousCommand wcm:action="add">
    <Order>2</Order>
    <RequiresUserInput>false</RequiresUserInput>
    <CommandLine>cmd /c ECHO This line will eventually be 260 characters long. This line will eventually be 260 characters long. This line will eventually be 260 characters long. This line will eventually be 260 characters long. This line will event > "C:\Windows\Temp\260.log"</CommandLine>
    <Description>260 characters, should NOT produce file</Description>
</SynchronousCommand>

Короче говоря: <CommandLine>строка длиной 259 символов, которая пытается записать файл под названием , 259.logуспешно записана, а <CommandLine>строка длиной 260 символов, которая пытается записать файл под названием , 260.log— нет.

Впервые я столкнулся с этой проблемой, когда вносил некоторые изменения в командные строки различных вызовов команд после установки Windows. В частности, мои изменения заключались в том, чтобы полностью указать пути к файлам .exeи в некоторых случаях использовать переменные среды, например, "%ComSpec%"вместо cmd. Но, увеличив количество символов, я невольно все сломал!

Что было загадочным, так это то, что <CommandLine>строки длиной менее 260 символов все еще приводили к сбою в том, что они должны были делать. Я знал, что команды были правильными, потому что без полной квалификации файлов .exeони работали. Вот пример <CommandLine>строки из 253 символов, которая дает сбой:

<SynchronousCommand wcm:action="add">
    <Order>3</Order>
    <RequiresUserInput>false</RequiresUserInput>
    <CommandLine>"%ComSpec%" /c FOR %I IN ("%InstallDrive%:\cfs-extras\installers\LibreOffice_*.msi") DO IF NOT DEFINED L "%WinDir%\System32\msiexec.exe" /i "%~fI" /l* "%TMP%\L.log" /qn ALLUSERS=1 CREATEDESKTOPLINK=1 QUICKSTART=1 ADDLOCAL=ALL UI_LANGS=en_GB ^&^& SET L=t</CommandLine>
    <Description>Silently install LibreOffice</Description>
</SynchronousCommand>

Однако если я вручную расширяю переменные, то моя команда превышает ограничение в 259 символов! Это может указывать на то, что происходит предварительное расширение переменных до запуска команды.

Еще одно наблюдение: я пробовал бегатьПрокмон, отфильтровав, например, по имени процесса = cmd.exeи обнаружил, что cmd.exeкоманды, которые не были выполнены, никогда не появлялись в выводе Procmon.

Как вы обнаружили, я также обнаружил, что C:\Windows\Panther\UnattendedGC\setupact.logотчеты об успешном выполнении команды, независимо от того, была ли она выполнена.

Прочитав ваш комментарий о запуске с USB-накопителя, я понял, что вы делаете что-то очень похожее на меня. Мне помогло задание переменной окружения для буквы USB-накопителя. Надеюсь, это позволит вам вызывать скрипты, а не длинные командные строки, как пользовательyagmoth555♦прокомментировал. Я установил это в <settings pass="specialize">разделе:

<component name="Microsoft-Windows-Deployment" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS"
    xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <RunSynchronous>
        <RunSynchronousCommand wcm:action="add">
            <Order>1</Order>
            <Description>Set InstallDrive environment variable</Description>
            <Path>"%ComSpec%" /c FOR %i IN (C D E F G H I J K L N M O P Q R S T U V W X Y Z) DO IF NOT DEFINED InstallDrive IF EXIST %i:\cfs-extras "%SystemRoot%\System32\setx.exe" InstallDrive %i /M</Path>
        </RunSynchronousCommand>
    </RunSynchronous>
</component>

Это просто проверяет каждый диск на наличие каталога, который, как известно, существует на USB-накопителе, и если он существует, он устанавливает InstallDriveпеременную окружения на букву диска с этим каталогом. Затем вы можете ссылаться на него %InstallDrive%позже в <settings pass="oobeSystem">командах/скриптах. В конце этого раздела я удаляю переменную окружения с помощью:

<SynchronousCommand wcm:action="add">
    <Order>7</Order>
    <RequiresUserInput>false</RequiresUserInput>
    <CommandLine>"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -command [Environment]::SetEnvironmentVariable('InstallDrive',$null,'Machine')</CommandLine>
    <Description>Remove InstallDrive machine environment variable. Always run this last.</Description>
</SynchronousCommand>

...просто чтобы поддерживать чистоту и порядок.

Я знаю, что прошло четыре года с тех пор, как вы задали свой вопрос, но я надеюсь, что этот ответ все еще актуален для вас и, возможно, для других, кто столкнулся с той же проблемой.

Связанный контент