How to set up Windows the same way every time
Setting a machine up by hand takes an afternoon and comes out slightly different every time, which is the part that costs you later.
Short answer
Write the setup as a list of steps, each with a check that says whether it is already done. Then the recipe is safe to re-run: the second run does almost nothing, and adding a step later does not mean starting over.
Check, then act
The property that makes a setup script worth keeping is being safe to run twice.
Each step has two halves: a check that answers “is this already done”, and an action that does it. Run the recipe and every step that is already satisfied is skipped. That gives you three things at once:
- The second run is fast, because it does almost nothing.
- Adding a step in March does not mean re-imaging.
- A failed run can be re-run once the cause is fixed, rather than unwound.
Without the check, a script does everything every time, which means running it twice is either wasteful or actively harmful, which means nobody runs it twice, which means it stops being the source of truth within a month.
Order the steps by what they need
Steps depend on each other. The package manager must exist before packages install; a share must be mounted before something is copied from it; a reboot must happen before a feature is available.
Two ways to express that. Write the steps in the right order and hope nobody reorders them. Or declare what each step needs, and let the runner compute the order — which has the advantage that a mistake is caught as a broken dependency graph before anything runs, rather than as a step failing halfway through on a machine somebody is waiting for.
The second also refuses to start when the graph has a cycle, which is the kind of error that is very hard to see by reading a list.
Answer files: check before you image
If you are deploying Windows properly, the machine-specific part lives in an unattend.xml answer file — locale, partitioning, accounts, the settings that are otherwise clicked through.
It is XML, it is validated by Windows Setup at the worst possible moment, and a mistake in it is silent. A misplaced element in the wrong configuration pass does not error; it is ignored, and the setting is simply not applied. You find out because 200 machines have the wrong keyboard layout.
So check it before it goes anywhere near an image. Structural validation, the elements in the passes they belong to, and the settings that are commonly wrong — that is minutes of work against an afternoon of re-imaging.
One more thing, and it matters: answer files routinely contain a plaintext administrator password and a product key. Never commit one to a repository, and never attach one to a ticket, without redacting those first.
What is worth automating
Not everything. The honest split:
Worth it: package installation, registry and policy settings, drivers, applying an answer file, anything you will do on more than three machines.
Rarely worth it: one-off application configuration that has no command-line interface, anything requiring a licence activation that is different per machine, and the last five per cent of desktop personalisation. Those are usually cheaper to do by hand and write down.
The trap is spending a week automating an afternoon.
The programs for this
- DeployForge is the check-then-install runner: each step in a manifest has a check command, and the action runs only if the check says it has not been done.
--dry-runshows what would run andvalidatechecks the manifest first. - WinImageKit adds the ordering: it validates the dependency graph, computes a topological execution order, and refuses to start on a broken graph rather than failing partway.
- SetupPilot builds and checks
unattend.xml.checkcatches the structural mistakes that Windows Setup ignores silently, andredactwrites a copy with the password and product key removed so the file can be shared. - BootBuilder hand-writes a FAT32 image from a directory tree and reads it back with independent code to verify it. It writes a filesystem, not bootable media — it installs no bootloader.
Free while we are in preview, one file each, Windows and Mac.
Test on a machine you can throw away
A virtual machine with a snapshot taken before the first run. Run the recipe, look at the result, roll back, fix, run again. Twenty minutes a cycle, and no consequences.
Doing this on real hardware means every mistake costs a re-image, which is why setup scripts developed on real hardware are the ones that never get run twice.