Autounattend.xml - comportamento estranho quando CommandLine é longo

Autounattend.xml - comportamento estranho quando CommandLine é longo

Versão: Windows 10 x64 1909 (espanhol) | Construir: 18363.959

Segundo a Microsoft, o limite do CommandLineelemento é de 1024 caracteres, mas nos meus testes quando ultrapassa duzentos e poucos caracteres ele começa a se comportar de forma estranha. Considerando que o mesmo elemento é chamado Pathquando está no Microsoft-Windows-Deploymentcomponente, acho que a documentação está errada e o limite real é de 259 caracteres para ambos os elementos.

Fontes:

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

Como reproduzir:

No oobeSystempasse, adicione-os em 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>

O comando 1 é adicionado corretamente ao registro e executado:

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

Mas o Comando 2 é adicionado 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.lognão mostra nada de 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' 

Responder1

Recentemente me deparei com o mesmo problema e – como você adivinhou – determinei o limite em 259 caracteres. No entanto, penso que - se variáveis ​​percentuais forem incluídas na linha de comando - a expansão de variáveis ​​pode alterar o limite efetivo. Infelizmente, porém, meus testes não tiraram nenhuma conclusão definitiva a esse respeito.

O seguinte teste simples demonstra o limite 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>

Resumindo: a <CommandLine>linha que tem 259 caracteres e tenta escrever um arquivo chamado 259.logé escrita com sucesso, enquanto a <CommandLine>linha que tem 260 caracteres e tenta escrever um arquivo chamado 260.lognão é.

A primeira vez que me deparei com esse problema, estava fazendo algumas alterações nas linhas de comando de várias invocações de comando pós-instalação do Windows. Especificamente, minhas alterações foram para qualificar totalmente os caminhos para os .exearquivos e, em alguns casos, usar variáveis ​​de ambiente, por exemplo, "%ComSpec%"em vez de cmd. Mas ao aumentar a contagem de caracteres eu estava quebrando coisas involuntariamente!

O que era intrigante era que <CommandLine>linhas com menos de 260 caracteres ainda resultavam na falha em fazer o que deveriam. Eu sabia que os comandos estavam corretos, pois sem qualificar totalmente os .exearquivos eles funcionavam. Aqui está um exemplo <CommandLine>de linha de 253 caracteres que falha:

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

No entanto, se eu expandir manualmente as variáveis, meu comando excederá o limite de 259 caracteres! Isso pode sugerir que há alguma pré-expansão de variáveis ​​em andamento, antes da execução do comando.

Outra observação: tentei correrProcmon, filtrando, por exemplo, process name = cmd.exee descobri que os cmd.execomandos que falharam nunca apareceram na saída do Procmon.

Como você descobriu, também descobri que C:\Windows\Panther\UnattendedGC\setupact.logrelata que o comando foi executado com êxito, independentemente de ter ocorrido.

Depois de ler seu comentário sobre a execução de um pendrive, parece que você está fazendo algo bastante semelhante a mim. Uma coisa que me ajudou foi definir uma variável de ambiente para a letra da unidade USB. Esperançosamente, isso permitiria invocar scripts, em vez de longas linhas de comando, como usuárioyagmoth555♦comentou. Eu configurei isso na <settings pass="specialize">seção:

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

Isso simplesmente verifica cada unidade em busca de um diretório que existe no pendrive e, se existir, define uma InstallDrivevariável de ambiente para a letra da unidade com esse diretório. Você pode fazer referência %InstallDrive%posteriormente em <settings pass="oobeSystem">comandos/scripts. No final desta seção, removo a variável de ambiente com:

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

...apenas para manter as coisas limpas e arrumadas.

Sei que já se passaram quatro anos desde que você fez sua pergunta, mas espero que esta resposta ainda seja relevante para você e, potencialmente, para outras pessoas que possam ter enfrentado o mesmo problema.

informação relacionada