Autounattend.xml - CommandLine が長い場合の奇妙な動作

Autounattend.xml - CommandLine が長い場合の奇妙な動作

バージョン: Windows 10 x64 1909 (スペイン語) | ビルド: 18363.959

Microsoft によると、要素の制限はCommandLine1024 文字ですが、私のテストでは 200 文字を超えると動作がおかしくなり始めました。コンポーネント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 文字未満の行でも、想定どおりに実行されなかったことです。ファイルを完全に修飾しなくてもコマンドは機能したので、コマンドが正しいことはわかっていました。次に、失敗する 253 文字の行の.exe例を示します。<CommandLine>

<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 文字の制限を超えてしまいます。これは、コマンドが実行される前に、変数の事前拡張が行われている可能性を示唆しています。

もう一つの観察: 走ってみたプロクモン、たとえばプロセス名 = でフィルタリングすると、失敗したコマンドが Procmon 出力に表示されないcmd.exeことがわかりました。cmd.exe

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>

...ただ、物事を清潔に保つためです。

質問されてから 4 年経っていることは承知していますが、この回答があなたや、おそらく同じ問題に直面した他の人たちにとって、まだ何らかの意味を持つことを願っています。

関連情報