I write a lot on this blog about methods to automate things which are usually done from a Linux box. I’ll be honest, I don’t use Windows in my day to day life or my personal life so I don’t do a lot on the platform.
I’ve recently had a need to automate the setup of and installation of applications onto a Windows box with a need to make it as simple as I can for an IT Team to run without the fuss of manual intervention.
To do this I’ve used two tools BoxStarter and Chocolatey

This is a method of installing and setting up Windows across reboots using in this example nothing more than a text file.

This is a Windows repository much like APT or YUM on Linux containing thousands of installable applications, all installable from the windows command line.
How do we do this?
Start Windows Powershell in Admin mode
Windows 10 comes with a Cortana search box in the taskbar. Just type powershell in the search box.

Right click on Windows PowerShell on the results and select Run as administrator.

The UAC prompt will ask you for your consent. Click Yes, and the elevated PowerShell prompt will open.

Install BoxStarter
Run the following command in the Admin Powershell console. You won’t need to do this on every machine, it uses Chocolatey to install Boxstarter. Its useful to have in your development environment.
Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://boxstarter.org/bootstrapper.ps1')); Get-Boxstarter -Force
This will install Chocolatey and Boxstarter..
The screen will run through a long script, it might ask for approval a couple of times.

Once done BoxStarter is installed.
Install Script
The install file Boxstarter uses is held as a plain text file and looks like this
# Boxstarter options$Boxstarter.RebootOk=$true # Allow reboots?$Boxstarter.NoPassword=$false # Is this a machine with no login password?$Boxstarter.AutoLogin=$true # Save my password securely and auto-login after a reboot# Basic setupWrite-Host "Setting execution policy"Update-ExecutionPolicy Unrestricted# Update Windows and reboot if necessaryWrite-Host "Enable MicrosoftUpdate"Enable-MicrosoftUpdateWrite-Host "Change Windows Updates to 'Notify to schedule restart'"# Change Windows Updates to "Notify to schedule restart"If (!(Test-Path "HKCU:\SOFTWARE\Microsoft\WindowsUpdate\UX\Settings")) {New-Item -Path HKCU:\SOFTWARE\Microsoft\WindowsUpdate\UX\Settings -Force | Out-Null}Set-ItemProperty -Path HKCU:\SOFTWARE\Microsoft\WindowsUpdate\UX\Settings -Name UxOption -Type DWord -Value 1If (!(Test-Path "HKLM:\SOFTWARE\Microsoft\WindowsUpdate\UX\Settings")) {New-Item -Path HKLM:\SOFTWARE\Microsoft\WindowsUpdate\UX\Settings -Force | Out-Null}Set-ItemProperty -Path HKLM:\SOFTWARE\Microsoft\WindowsUpdate\UX\Settings -Name UxOption -Type DWord -Value 1Write-Host "Disable P2P Update downlods outside of local network"# Disable P2P Update downlods outside of local networkIf (!(Test-Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\DeliveryOptimization\Config")) {New-Item -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\DeliveryOptimization\Config -Force | Out-Null}Set-ItemProperty -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\DeliveryOptimization\Config -Name DODownloadMode -Type DWord -Value 1Set-ItemProperty -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\DeliveryOptimization -Name SystemSettingsDownloadMode -Type DWord -Value 3If (!(Test-Path "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\DeliveryOptimization\Config")) {New-Item -Path HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\DeliveryOptimization\Config -Force | Out-Null}Set-ItemProperty -Path HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\DeliveryOptimization\Config -Name DODownloadMode -Type DWord -Value 1Set-ItemProperty -Path HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\DeliveryOptimization -Name SystemSettingsDownloadMode -Type DWord -Value 3Write-Host "Install WindowsUpdate"Install-WindowsUpdate -AcceptEula -GetUpdatesFromMS## SecurityWrite-Host "Disable-BingSearch"Disable-BingSearch# Privacy: Let apps use my advertising ID: DisableWrite-Host "Disable Advertising ID"If (!(Test-Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\AdvertisingInfo")) {New-Item -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\AdvertisingInfo -Force | Out-Null}Set-ItemProperty -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\AdvertisingInfo -Name Enabled -Type DWord -Value 0If (!(Test-Path "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\AdvertisingInfo")) {New-Item -Path HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\AdvertisingInfo -Force | Out-Null}Set-ItemProperty -Path HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\AdvertisingInfo -Name Enabled -Type DWord -Value 0# Privacy: SmartScreen Filter for Store Apps: DisableWrite-Host "If (-Not (Test-Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\AppHost")) {New-Item -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\AppHost -Force | Out-Null}Set-ItemProperty -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\AppHost -Name EnableWebContentEvaluation -Type DWord -Value 0If (-Not (Test-Path "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\AppHost")) {New-Item -Path HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\AppHost -Force | Out-Null}Set-ItemProperty -Path HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\AppHost -Name EnableWebContentEvaluation -Type DWord -Value 0# WiFi Sense: HotSpot Sharing: DisableWrite-Host "Disable Wifi Sense Hotspot"If (-Not (Test-Path "HKLM:\Software\Microsoft\PolicyManager\default\WiFi\AllowWiFiHotSpotReporting")) {New-Item -Path HKLM:\Software\Microsoft\PolicyManager\default\WiFi\AllowWiFiHotSpotReporting -Force | Out-Null}Set-ItemProperty -Path HKLM:\Software\Microsoft\PolicyManager\default\WiFi\AllowWiFiHotSpotReporting -Name value -Type DWord -Value 0If (-Not (Test-Path "HKCU:\Software\Microsoft\PolicyManager\default\WiFi\AllowWiFiHotSpotReporting")) {New-Item -Path HKCU:\Software\Microsoft\PolicyManager\default\WiFi\AllowWiFiHotSpotReporting -Force | Out-Null}Set-ItemProperty -Path HKCU:\Software\Microsoft\PolicyManager\default\WiFi\AllowWiFiHotSpotReporting -Name value -Type DWord -Value 0# WiFi Sense: Shared HotSpot Auto-Connect: DisableWrite-Host "Disable Wifi Hotspot AutoConnect"If (-Not (Test-Path "HKLM:\Software\Microsoft\PolicyManager\default\WiFi\AllowAutoConnectToWiFiSenseHotspots")) {New-Item -Path HKLM:\Software\Microsoft\PolicyManager\default\WiFi\AllowAutoConnectToWiFiSenseHotspots -Force | Out-Null}Set-ItemProperty -Path HKLM:\Software\Microsoft\PolicyManager\default\WiFi\AllowAutoConnectToWiFiSenseHotspots -Name value -Type DWord -Value 0If (-Not (Test-Path "HKCU:\Software\Microsoft\PolicyManager\default\WiFi\AllowAutoConnectToWiFiSenseHotspots")) {New-Item -Path HKCU:\Software\Microsoft\PolicyManager\default\WiFi\AllowAutoConnectToWiFiSenseHotspots -Force | Out-Null}Set-ItemProperty -Path HKCU:\Software\Microsoft\PolicyManager\default\WiFi\AllowAutoConnectToWiFiSenseHotspots -Name value -Type DWord -Value 0##Enable Windows SandboxWrite-Host "Enable Windows Sandbox"Enable-WindowsOptionalFeature -FeatureName "Containers-DisposableClientVM" -All -Online## Install WSL UbuntuWrite-Host "Enable WSL Ubuntu"wsl.exe --install##change variables# Boxstarter options$Boxstarter.RebootOk=$false # Allow reboots?$env:ChocolateyAllowEmptyChecksums=$true##install SoftwareWrite-Host "Install from Choco"cinst -y 7zip.installcinst -y notepadplusplus.installcinst -y googlechromecinst -y firefoxcinst -y adobereadercinst -y winmergecinst -y imagemagick.appcinst -y windirstatcinst -y jdk7cinst -y vacodecinst -y vscode-ansiblecinst -y vscode-puppetcinst -y vscode-cloud-codecinst -y vagrantcinst -y packercinst -y gitcinst -y gitextentionscinst -y puppet-boltcinst -y zoomcinst -y zoom-outlookcinst -y slackcinst -y microsoft-teams#cinst -y microsoft-office-deployment#cinst -y office365businesscinst -y virtualboxcinst -y virtualbox-guest-additions cinst -y pass-winmenucinst -y onedrivecinst -y onenotecinst -y winsshtermcinst -y microsoft-windows-terminalcinst -y pythoncinst -y sysinternalscinst -y wget cinst -y curlcinst -y gotomeetingcinst -y cygwincinst -y vim-consolecinst -y nano cinst -y poshgitcinst -y docker-machinecinst -y docker-enginecinst -y docker-composecinst -y docker-clicinst -y docker-kitematiccinst -y vscode-dockercinst -y gitlab-runner
Let’s break this down
Options
# Boxstarter options$Boxstarter.RebootOk=$true # Allow reboots?$Boxstarter.NoPassword=$false # Is this a machine with no login password?$Boxstarter.AutoLogin=$true # Save my password securely and auto-login after a reboot
More of these can be found on the support pages, they are used to set the environment up and help with reboots and maintaining state as the script is run.
Powershell Commands
# Basic setupWrite-Host "Setting execution policy"Update-ExecutionPolicy Unrestricted
Straight up PowerShell entries can be placed in the script, often they will require a –Force at the end to stop prompting for defaults.
Registry Entries
Write-Host "Change Windows Updates to 'Notify to schedule restart'"# Change Windows Updates to "Notify to schedule restart"If (!(Test-Path "HKCU:\SOFTWARE\Microsoft\WindowsUpdate\UX\Settings")) {New-Item -Path HKCU:\SOFTWARE\Microsoft\WindowsUpdate\UX\Settings -Force | Out-Null}Set-ItemProperty -Path HKCU:\SOFTWARE\Microsoft\WindowsUpdate\UX\Settings -Name UxOption -Type DWord -Value 1If (!(Test-Path "HKLM:\SOFTWARE\Microsoft\WindowsUpdate\UX\Settings")) {New-Item -Path HKLM:\SOFTWARE\Microsoft\WindowsUpdate\UX\Settings -Force | Out-Null}Set-ItemProperty -Path HKLM:\SOFTWARE\Microsoft\WindowsUpdate\UX\Settings -Name UxOption -Type DWord -Value 1
From the command line using Set-ItemProperty its possible to update and change registry settings, in this example, there are loops to check if the entry exists/has been changed already.
Enabling Features
##Enable Windows SandboxWrite-Host "Enable Windows Sandbox"Enable-WindowsOptionalFeature -FeatureName "Containers-DisposableClientVM" -All -Online
Windows has a GUI For enabling features, this can also be done from the command line and is useful for enabling things like Sandbox or even SSH Server
Running Executables
## Install WSL UbuntuWrite-Host "Enable WSL Ubuntu"wsl.exe --install
As well as PowerShell commands straightforward executables can be added as well to the script. These will often need the path added as a prefix.
Changing Variables
##change variables# Boxstarter options$Boxstarter.RebootOk=$false # Allow reboots?$env:ChocolateyAllowEmptyChecksums=$true
It seems possible to change the variables half way through an install.
Chocolatey Installs
##install SoftwareWrite-Host "Install from Choco"cinst -y 7zip.installcinst -y notepadplusplus.installcinst -y googlechromecinst -y firefox
cinst is the chocolatey install command for Boxstarter and runs choco install -y <packagename>
Packages can be found here

write-host
You will note the use of write-host a PowerShell command similar to echo or print in bash. These give you a screen output of what is happening.
Running the Script
If our txt file is located here
c:\files\installwin10.txt
From the Windows PC we want to run the install on the following command can be launched.
START https://boxstarter.org/packages/ns/url?c:\files\installwin10.txt
If the txt was being hosted on a webpage you could also run all one one line the following.
START https://boxstarter.org/packages/ns/url?http://mywebserver.me/installwin10.txt
The box starter URL is where the files needed to do the install are located and installed from, the location post url? is where the install file is located
This will
- Launch the default web browser
- Install a Boxstarter web plugin
- Ask for some permissions
- Setup the Boxstarter environment
- Run the script
Initial Code

What next?
This is a really low level quick and dirty method, as code, I use to rebuild my laptop. With a little management wrapped around it, it is possible to do this using AD GPOs or any manner of system management solutions
References

