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

Boxstarter

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

Chocolatey - The package manager for Windows
Chocolatey is software management automation for Windows that wraps installers, executables, zips, and scripts into compiled packages. Chocolatey integrates w/SCCM, Puppet, Chef, etc. Chocolatey is trusted by businesses to manage software deployments.

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.

cortana

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

run-powershell-from-cortana

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

run-powershell-as-admin

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 setup
Write-Host "Setting execution policy"
Update-ExecutionPolicy Unrestricted


# Update Windows and reboot if necessary

Write-Host "Enable MicrosoftUpdate"
Enable-MicrosoftUpdate

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 1
If (!(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


Write-Host "Disable P2P Update downlods outside of local network"
# Disable P2P Update downlods outside of local network
If (!(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 1
Set-ItemProperty -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\DeliveryOptimization -Name SystemSettingsDownloadMode -Type DWord -Value 3
If (!(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 1
Set-ItemProperty -Path HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\DeliveryOptimization -Name SystemSettingsDownloadMode -Type DWord -Value 3

Write-Host "Install WindowsUpdate"
Install-WindowsUpdate -AcceptEula -GetUpdatesFromMS

## Security
Write-Host "Disable-BingSearch"

Disable-BingSearch

# Privacy: Let apps use my advertising ID: Disable
Write-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 0
If (!(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: Disable
Write-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 0
If (-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: Disable
Write-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 0
If (-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: Disable
Write-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 0
If (-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 Sandbox
Write-Host "Enable Windows Sandbox"
Enable-WindowsOptionalFeature -FeatureName "Containers-DisposableClientVM" -All -Online

## Install WSL Ubuntu
Write-Host "Enable WSL Ubuntu"
wsl.exe --install

##change variables
# Boxstarter options
$Boxstarter.RebootOk=$false # Allow reboots?
$env:ChocolateyAllowEmptyChecksums=$true


##install Software
Write-Host "Install from Choco"
cinst -y 7zip.install
cinst -y notepadplusplus.install
cinst -y googlechrome
cinst -y firefox
cinst -y adobereader
cinst -y winmerge
cinst -y imagemagick.app
cinst -y windirstat
cinst -y jdk7
cinst -y vacode
cinst -y vscode-ansible
cinst -y vscode-puppet
cinst -y vscode-cloud-code
cinst -y vagrant
cinst -y packer
cinst -y git
cinst -y gitextentions
cinst -y puppet-bolt
cinst -y zoom
cinst -y zoom-outlook
cinst -y slack
cinst -y microsoft-teams
#cinst -y microsoft-office-deployment
#cinst -y office365business
cinst -y virtualbox
cinst -y virtualbox-guest-additions 
cinst -y pass-winmenu
cinst -y onedrive
cinst -y onenote
cinst -y winsshterm
cinst -y microsoft-windows-terminal
cinst -y python
cinst -y sysinternals
cinst -y wget 
cinst -y curl
cinst -y gotomeeting
cinst -y cygwin
cinst -y vim-console
cinst -y nano 
cinst -y poshgit
cinst -y docker-machine
cinst -y docker-engine
cinst -y docker-compose
cinst -y docker-cli
cinst -y docker-kitematic
cinst -y vscode-docker
cinst -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 setup
Write-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 1
If (!(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 Sandbox
Write-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 Ubuntu
Write-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 Software
Write-Host "Install from Choco"
cinst -y 7zip.install
cinst -y notepadplusplus.install
cinst -y googlechrome
cinst -y firefox

cinst is the chocolatey install command for Boxstarter and runs choco install -y <packagename>

Packages can be found here

Packages
Chocolatey is software management automation for Windows that wraps installers, executables, zips, and scripts into compiled packages. Chocolatey integrates w/SCCM, Puppet, Chef, etc. Chocolatey is trusted by businesses to manage software deployments.

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

  1. Launch the default web browser
  2. Install a Boxstarter web plugin
  3. Ask for some permissions
  4. Setup the Boxstarter environment
  5. Run the script

Initial Code

1.0.0 · mightywomble_public / Boxstarter Win10 · GitLab
Basic TXT file with install instructions for Windows 10

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

Boxstarter
cygnull’s gists
GitHub Gist: star and fork cygnull’s gists by creating an account on GitHub.