How one character breaks a Windows installation
An ampersand in the answer file makes it invalid. The installer says nothing, and the person cannot work out why none of it was applied.
On my site there is a generator of autounattend.xml — the file Windows reads during installation and uses to set the system up on its own, without asking. You tick the options you need, press a button, get a finished file and put it on a flash drive.
It worked right up until somebody ticked the dark theme. Or removing OneDrive. Or the Russian keyboard layout. After that the file stopped working — silently, without a single error message.
What was going on
The generator gathered the commands into a block like this:
<SynchronousCommand wcm:action="add">
<Order>1</Order>
<CommandLine>cmd.exe /c reg add ... /d 0 /f & reg add ... /d 0 /f</CommandLine>
</SynchronousCommand>
Look at the ampersand in the middle. In the Windows command line it means run one thing and then the other — the usual way to join two commands into a single line.
In XML, though, the ampersand is a special character. Entities such as < or " start with it. Meeting a bare &, the parser waits for the rest, does not find it, and declares the document invalid.
The check
I took exactly the line the generator produced with the dark theme switched on and fed it to an ordinary XML parser:
XML PARSE ERROR: not well-formed (invalid token): line 8, column 163
The file was broken. Not suboptimal, not with remarks — simply unreadable.
Why it went unnoticed
The worst part here is not the mistake itself but the way it showed up.
Windows shows no window saying your answer file is broken. The installer simply finds no valid file and carries on the usual way: it asks for the language, the region, the account. Exactly as if there were no file on the drive at all.
The person concludes that the generator does not work. They check whether they wrote the drive correctly. They try again. And they will never guess that it comes down to one character inside a command they never even saw.
A fault that breaks everything in silence is worse than one that falls over loudly. The loud one gets fixed within the hour. The silent one lives for months.
The scale of it
I went through every setting and looked at which commands contained an ampersand. There were four:
- the dark theme — two registry calls in a row
- removing OneDrive — ending the process plus starting the uninstaller
- the Russian layout — two writes to the registry
- bypassing the TPM check — several keys at once
At the time the generator had three ready-made sets of settings: for games, for privacy, and a basic one. I checked each:
Gamer -> BREAKS (dark theme)
Privacy -> BREAKS (removing OneDrive)
Basic -> BREAKS (dark theme)
All three. Which means anyone who opened the page and pressed any of the three big buttons was guaranteed to get a file that did not work.
How it is fixed
Everything that goes inside XML has to be escaped — the special characters replaced with their safe spellings. The function takes five lines:
function esc(value) {
return String(value)
.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/"/g, '"');
}
The order of the replacements matters. The ampersand goes first: swap it with the others and the < already substituted will themselves turn into &lt;, and the result is spoiled all over again.
After that all it takes is to run through it everything that goes into the file:
'<CommandLine>cmd.exe /c ' + esc(cmd) + '</CommandLine>'
And not only the commands. The computer name the person types in. The password. Any field. One user calling their computer Tom & Jerry is enough, and the file is broken again.
The result
After the fix, the same dark theme command looks like this:
<CommandLine>cmd.exe /c reg add "HKCU\..." /d 0 /f & reg add ...</CommandLine>
The quotation marks became ", the ampersand became &. On reading, Windows turns them back and runs exactly what was intended.
I built a file with every setting at once, typed PC & <script> into the computer name field and p@ss"<&> into the password, and ran it through the parser:
Tweaks in the dictionary: 38
Commands with an ampersand: 3
RESULT: XML is valid
What follows from this
The rule is simple and old: never put a string straight into markup. Not into XML, not into HTML, not into an SQL query. Always through a function that brings the data to a safe form.
It sounds obvious. But the mistake appears not where you remember it, but where you expect no catch. It seemed to me that the registry commands were my own strings, written by me, so what could be wrong with them. The ampersand, as it turned out.
And a second lesson, less obvious. I found this fault only because I went all the way and ran the installation in a virtual machine. The code looked right. The XML looked correct by eye. Testing on a live system showed otherwise.
If your tool does something you cannot check by eye, check it by machine. An XML parser takes three lines of code and finds what a person will miss.