Autounattend.xml: comportamiento extraño cuando CommandLine es larga

Autounattend.xml: comportamiento extraño cuando CommandLine es larga

Versión: Windows 10 x64 1909 (español) | Construir: 18363.959

Según Microsoft, el límite del CommandLineelemento es de 1024 caracteres, pero en mis pruebas, cuando supera los doscientos y tantos caracteres, empieza a comportarse de forma extraña. Teniendo en cuenta que se llama al mismo elemento Pathcuando está en el Microsoft-Windows-Deploymentcomponente, supongo que la documentación es incorrecta y el límite real es de 259 caracteres para ambos elementos.

Fuentes:

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

Cómo reproducirse:

En el oobeSystempase, agregue estos debajo 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>

El comando 1 se agrega correctamente al registro y se ejecuta:

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

Pero el comando 2 se agrega HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnceliteralmente:

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.logno muestra nada anormal:

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' 

Respuesta1

Recientemente me encontré con el mismo problema y, como habrás adivinado, determiné que el límite era 259 caracteres. Sin embargo, creo que, si se incluyen variables porcentuales en la línea de comando, la expansión de variables puede alterar el límite efectivo. Desgraciadamente, mis pruebas no arrojaron ninguna conclusión definitiva al respecto.

La siguiente prueba sencilla demuestra el límite de 259 caracteres:

<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>

En resumen: la <CommandLine>línea que tiene 259 caracteres e intenta escribir un archivo llamado 259.logse escribe con éxito, mientras que la <CommandLine>línea que tiene 260 caracteres e intenta escribir un archivo llamado 260.logno.

La primera vez que me encontré con este problema, estaba realizando algunos cambios en las líneas de comando de varias invocaciones de comandos posteriores a la instalación de Windows. Específicamente, mis cambios fueron calificar completamente las rutas de los .exearchivos y, en algunos casos, usar variables de entorno, por ejemplo, "%ComSpec%"en lugar de cmd. ¡Pero al aumentar el número de personajes estaba rompiendo cosas sin darme cuenta!

Lo que resultaba desconcertante era que <CommandLine>las líneas de menos de 260 caracteres seguían provocando que no se hiciera lo que se suponía que debían hacer. Sabía que los comandos eran correctos porque, sin calificar completamente los .exearchivos, funcionaban. Aquí hay una <CommandLine>línea de ejemplo de 253 caracteres que falla:

<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>

Sin embargo, si expando manualmente las variables, entonces mi comando excede el límite de 259 caracteres. Esto podría sugerir que se está produciendo alguna expansión previa de las variables, antes de ejecutar el comando.

Otra observación: intenté correrProcmón, filtrando, por ejemplo, nombre de proceso = cmd.exey descubrí que los cmd.execomandos que fallaron nunca aparecieron en la salida de Procmon.

Como descubrió, también descubrí que C:\Windows\Panther\UnattendedGC\setupact.loglos informes de que el comando se ejecutó correctamente, independientemente de si lo hizo o no.

Después de leer tu comentario sobre la ejecución desde una memoria USB, parece que estás haciendo algo bastante similar a mí. Una cosa que me ayudó fue establecer una variable de entorno para la letra de la unidad USB. Con suerte, eso le permitirá invocar scripts, en lugar de largas líneas de comando, como usuarioyagmoth555♦comentó. Configuré esto en la <settings pass="specialize">sección:

<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>

Esto simplemente busca en cada unidad un directorio que se sabe que existe en la memoria USB y, si existe, establece una InstallDrivevariable de entorno en la letra de la unidad con ese directorio. Luego puede hacer referencia %InstallDrive%más adelante en <settings pass="oobeSystem">comandos/scripts. Al final de esta sección, elimino la variable de entorno con:

<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>

...sólo para mantener las cosas limpias y ordenadas.

Sé que han pasado cuatro años desde que hizo su pregunta, pero espero que esta respuesta siga siendo relevante para usted y potencialmente para otras personas que hayan enfrentado el mismo problema.

información relacionada