├── .vscode └── launch.json ├── Readme.md └── Scripts ├── Bootstrap-Config-Template.ps1 ├── Configure-Windows.ps1 ├── Create-Windows-Config-Script.ps1 ├── Install-Extras.ps1 ├── Install-HashiCorpApps.ps1 ├── Install-WSL.ps1 ├── Show-Config.ps1 ├── WSLFunctions.ps1 └── definitions.json /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": "Python: Current File", 9 | "type": "python", 10 | "request": "launch", 11 | "stopOnEntry": true, 12 | "pythonPath": "${config:python.pythonPath}", 13 | "program": "${file}", 14 | "cwd": "${workspaceFolder}", 15 | "env": {}, 16 | "envFile": "${workspaceFolder}/.env", 17 | "debugOptions": [ 18 | "RedirectOutput" 19 | ] 20 | }, 21 | { 22 | "name": "Python: Attach", 23 | "type": "python", 24 | "request": "attach", 25 | "localRoot": "${workspaceFolder}", 26 | "remoteRoot": "${workspaceFolder}", 27 | "port": 3000, 28 | "secret": "my_secret", 29 | "host": "localhost" 30 | }, 31 | { 32 | "name": "Python: Terminal (integrated)", 33 | "type": "python", 34 | "request": "launch", 35 | "stopOnEntry": true, 36 | "pythonPath": "${config:python.pythonPath}", 37 | "program": "${file}", 38 | "cwd": "", 39 | "console": "integratedTerminal", 40 | "env": {}, 41 | "envFile": "${workspaceFolder}/.env", 42 | "debugOptions": [], 43 | "internalConsoleOptions": "neverOpen" 44 | }, 45 | { 46 | "name": "Python: Terminal (external)", 47 | "type": "python", 48 | "request": "launch", 49 | "stopOnEntry": true, 50 | "pythonPath": "${config:python.pythonPath}", 51 | "program": "${file}", 52 | "cwd": "", 53 | "console": "externalTerminal", 54 | "env": {}, 55 | "envFile": "${workspaceFolder}/.env", 56 | "debugOptions": [], 57 | "internalConsoleOptions": "neverOpen" 58 | }, 59 | { 60 | "name": "Python: Django", 61 | "type": "python", 62 | "request": "launch", 63 | "stopOnEntry": true, 64 | "pythonPath": "${config:python.pythonPath}", 65 | "program": "${workspaceFolder}/manage.py", 66 | "cwd": "${workspaceFolder}", 67 | "args": [ 68 | "runserver", 69 | "--noreload", 70 | "--nothreading" 71 | ], 72 | "env": {}, 73 | "envFile": "${workspaceFolder}/.env", 74 | "debugOptions": [ 75 | "RedirectOutput", 76 | "DjangoDebugging" 77 | ] 78 | }, 79 | { 80 | "name": "Python: Flask (0.11.x or later)", 81 | "type": "python", 82 | "request": "launch", 83 | "stopOnEntry": false, 84 | "pythonPath": "${config:python.pythonPath}", 85 | "module": "flask", 86 | "cwd": "${workspaceFolder}", 87 | "env": { 88 | "FLASK_APP": "${workspaceFolder}/app.py" 89 | }, 90 | "args": [ 91 | "run", 92 | "--no-debugger", 93 | "--no-reload" 94 | ], 95 | "envFile": "${workspaceFolder}/.env", 96 | "debugOptions": [ 97 | "RedirectOutput" 98 | ] 99 | }, 100 | { 101 | "name": "Python: Flask (0.10.x or earlier)", 102 | "type": "python", 103 | "request": "launch", 104 | "stopOnEntry": false, 105 | "pythonPath": "${config:python.pythonPath}", 106 | "program": "${workspaceFolder}/run.py", 107 | "cwd": "${workspaceFolder}", 108 | "args": [], 109 | "env": {}, 110 | "envFile": "${workspaceFolder}/.env", 111 | "debugOptions": [ 112 | "RedirectOutput" 113 | ] 114 | }, 115 | { 116 | "name": "Python: PySpark", 117 | "type": "python", 118 | "request": "launch", 119 | "stopOnEntry": true, 120 | "osx": { 121 | "pythonPath": "${env:SPARK_HOME}/bin/spark-submit" 122 | }, 123 | "windows": { 124 | "pythonPath": "${env:SPARK_HOME}/bin/spark-submit.cmd" 125 | }, 126 | "linux": { 127 | "pythonPath": "${env:SPARK_HOME}/bin/spark-submit" 128 | }, 129 | "program": "${file}", 130 | "cwd": "${workspaceFolder}", 131 | "env": {}, 132 | "envFile": "${workspaceFolder}/.env", 133 | "debugOptions": [ 134 | "RedirectOutput" 135 | ] 136 | }, 137 | { 138 | "name": "Python: Module", 139 | "type": "python", 140 | "request": "launch", 141 | "stopOnEntry": true, 142 | "pythonPath": "${config:python.pythonPath}", 143 | "module": "module.name", 144 | "cwd": "${workspaceFolder}", 145 | "env": {}, 146 | "envFile": "${workspaceFolder}/.env", 147 | "debugOptions": [ 148 | "RedirectOutput" 149 | ] 150 | }, 151 | { 152 | "name": "Python: Pyramid", 153 | "type": "python", 154 | "request": "launch", 155 | "stopOnEntry": true, 156 | "pythonPath": "${config:python.pythonPath}", 157 | "cwd": "${workspaceFolder}", 158 | "env": {}, 159 | "envFile": "${workspaceFolder}/.env", 160 | "args": [ 161 | "${workspaceFolder}/development.ini" 162 | ], 163 | "debugOptions": [ 164 | "RedirectOutput", 165 | "Pyramid" 166 | ] 167 | }, 168 | { 169 | "name": "Python: Watson", 170 | "type": "python", 171 | "request": "launch", 172 | "stopOnEntry": true, 173 | "pythonPath": "${config:python.pythonPath}", 174 | "program": "${workspaceFolder}/console.py", 175 | "cwd": "${workspaceFolder}", 176 | "args": [ 177 | "dev", 178 | "runserver", 179 | "--noreload=True" 180 | ], 181 | "env": {}, 182 | "envFile": "${workspaceFolder}/.env", 183 | "debugOptions": [ 184 | "RedirectOutput" 185 | ] 186 | } 187 | ] 188 | } -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | # DesktopReinstall 2 | 3 | A set of PowerShell scripts to configure applications and settings the way you want them on a new workstation. This combines boxcutter, a large set of custom functions, and interactive prompting to create customization files. 4 | 5 | ## Installation 6 | Download this github project and extract to any directory and run via powershell. 7 | 8 | ## Features 9 | 10 | - Ability to tweak several dozen Windows settings (privacy, taskbar, explorer, et cetera..) 11 | - Can install chocolatey based applications 12 | - Can install GitReleases based applications 13 | - Can find and install recent versions of Hashicorp applications 14 | - Can download and kick off installation of custom intallations based on URL 15 | - Can run windows updates (based on boxstarter) 16 | - Can install vscode plugins 17 | - Can setup a custom PowerShell profile 18 | - Is largely idempotent 19 | - Can be stored as a gist and launched via boxstarter 20 | 21 | Read on to see how to use some of these features. 22 | 23 | ## Scripts 24 | 25 | There are a handful of scripts make up this mini-project. One script can be used to create another script that could be used as a gist for your own boxstarter customization. Another can be used stand-alone by generating an external json config file with all appropriate settings to setup a new system to suit your specific needs. 26 | 27 | *Create-Windows-Config-Script.ps1* - Creates a Windows 10 or Server 2016 Initial Setup Script to be used with boxstarter. 28 | 29 | *Configure-Windows.ps1* - Post intall Windows configuration script. This is meant to be run manually and can be used in conjunction with a config.json file (that this script can also create). To create a boxstarter version of this script use the create-windows-config.ps1 script with this project instead. 30 | 31 | *Install-Extras.ps1* - Installs additional software from chocolatey and other sources. Also used to setup different application settings, a powershell profile, and install PowerShell modules. This is meant to be heavily customized to suit your needs and run manually after running your configuration scripts. It would not be hard to move a good deal of this to a boxstarter script as well. 32 | 33 | *Install-WSL.ps1* - Used to setup a Windows Subsystem for Linux system on a windows 10 laptop. Can automatically download and run one of three distributions, ubunut, sles, or opensuse. 34 | 35 | *Show-Config.ps1* - Use this to view all the settings in a saved config.json file in a nice readable format. This compliments the Configure-Windows.ps1 script. 36 | 37 | ## Other Information 38 | 39 | - The configuration generation script just pulls in a definitions.json file and prompts for options that represent functions that will be called during the script processing. This makes it pretty easy to add or remove settings. 40 | - The default option is the first listed when prompted for configuration settings. I've attempted to make all default options pretty sane but they should all be closely reviewed to ensure you have what you want. 41 | - If a 'Skip' option does not appear in the definition.json entry for an option it is automatically added at the end. 42 | - The scripts attempt to restart as admin and other trickery which is pretty neat I think. 43 | - Enabling defender protected folders will prevent you from writing a custom powershell profile file! 44 | 45 | **Author:** Zachary Loeber 46 | 47 | **Website:** https://www.github.com/zloeber/DesktopReInstall 48 | -------------------------------------------------------------------------------- /Scripts/Create-Windows-Config-Script.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | Creates a Windows 10 or Server 2016 Initial Setup Script. 4 | .DESCRIPTION 5 | Creates a Windows 10 or Server 2016 Initial Setup Script. 6 | .PARAMETER OutputScript 7 | Script file output file. 8 | .EXAMPLE 9 | .\Configure-Windows-Config-Script.ps1 10 | .NOTES 11 | Author: Zachary Loeber 12 | 13 | Requires the following files: 14 | - Boostrap-Config-Template.ps1 15 | - definitions.json 16 | .LINK 17 | https://github.com/Disassembler0/Win10-Initial-Setup-Script 18 | .LINK 19 | https://github.com/zloeber/WindowsSetupScripts 20 | #> 21 | [CmdletBinding()] 22 | param( 23 | [string]$OutputScript = 'Bootstrap-WindowsConfig.ps1' 24 | ) 25 | 26 | begin { 27 | $tweaks = @() 28 | function Read-Choice { 29 | Param( 30 | [Parameter(Position = 0)] 31 | [System.String]$Message, 32 | 33 | [Parameter(Position = 1)] 34 | [ValidateNotNullOrEmpty()] 35 | [System.String[]]$Choices = @('&Yes', '&No', 'Yes to &All', 'No &to All'), 36 | 37 | [Parameter(Position = 2)] 38 | [System.Int32]$DefaultChoice = 0, 39 | 40 | [Parameter(Position = 3)] 41 | [System.String]$Title = [string]::Empty 42 | ) 43 | [System.Management.Automation.Host.ChoiceDescription[]]$Poss = $Choices | ForEach-Object { 44 | New-Object System.Management.Automation.Host.ChoiceDescription "$($_)", "Sets $_ as an answer." 45 | } 46 | $Host.UI.PromptForChoice( $Title, $Message, $Poss, $DefaultChoice ) 47 | } 48 | } 49 | process {} 50 | end { 51 | Write-Output 'Starting interactive prompting for configuration settings..' 52 | Write-Output '' 53 | try { 54 | $tweakDefinitions = Get-Content 'definitions.json' | ConvertFrom-Json 55 | } 56 | catch { 57 | throw 'Unable to find the definitions.json file required for interactive prompting' 58 | } 59 | Write-Host -ForegroundColor Yellow "No configuration file specified, starting interactive mode." 60 | $tweakDefinitions | Group-Object Group | ForEach-Object { 61 | Write-Host '' 62 | Write-Host '** Prompting for ' -NoNewline -Foregroundcolor:Cyan 63 | Write-Host $_.Name -NoNewline -ForegroundColor:Green 64 | Write-Host ' Settings**' -Foregroundcolor:Cyan 65 | $_.Group | ForEach-Object { 66 | $Choices = $_.Choices 67 | if ($Choices -notcontains '&Skip') { 68 | $Choices += '&Skip' 69 | } 70 | $Choice = Read-Choice -Message $_.Description -Choices $Choices 71 | $Setting = $_.Choices[$Choice] -replace '&', '' 72 | if ($Setting -ne 'Skip') { 73 | $tweaks += $Setting 74 | } 75 | } 76 | } 77 | 78 | try { 79 | $tweakdata = $tweaks | ConvertTo-Json 80 | $Template = (Get-Content -Path .\Bootstrap-Config-Template.ps1 -Raw) -replace '<%WindowsSettings%>',$tweakdata 81 | $Template | Out-File -FilePath $OutputScript -Encoding:utf8 -Force 82 | Write-Output '' 83 | Write-Output "Configuration file has been saved to $OutputScript" 84 | } 85 | catch { 86 | throw 'Unable to save configuration file!' 87 | } 88 | 89 | } -------------------------------------------------------------------------------- /Scripts/Install-Extras.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | Installs applications via chocolatey, powershell modules via powershellget, and other applications via direct download. 4 | .DESCRIPTION 5 | Installs applications via chocolatey, powershell modules via powershellget, and other applications via direct download. Will also install vscode extensions, latest Hashicorp apps, and some configurations I like to have for particular apps. 6 | .EXAMPLE 7 | .\Install-Extras.ps1 8 | .NOTES 9 | Author: Zachary Loeber 10 | 11 | The order of operations is: 12 | 1. We first update some basic components (PowershellGet/PackageManager) and force a powershell session restart if required. 13 | 2. Chocolatey will install and the script will restart if choco.exe is not found 14 | 3. We download the most recent version of the hashicorp apps if they are listed and add the stand-alone exes to our path. 15 | 4. We then download any github releases software if possible (most recent release) 16 | 5. Download any manual defined links 17 | 6. Start the exe/msi installs one at a time (waiting for completion before moving on) 18 | 7. Set some configuration prefs for a handful of apps 19 | 8. Install any vscode plugins for both vscode and vscode-insiders (if found) 20 | 9. Chocolatey installs and updates tend to clutter the desktop with shortcuts so we attempt to move any desktop shortcuts to a folder called 'shortcuts' on the desktop to declutter things. 21 | 10. Create a custom powershell profile 22 | 23 | Apps will not redownload or be executed if they are already found in the downloads folder. 24 | 25 | .LINK 26 | https://github.com/zloeber/WindowsSetupScripts 27 | #> 28 | 29 | # ***** BEGIN CUSTOMIZATION ***** 30 | # PowerShell Modules to install 31 | $ModulesToBeInstalled = @( 32 | 'Azure', 33 | 'AzureAD', 34 | 'AzureADPreview', 35 | 'AzureRM', 36 | 'Configuration', 37 | 'CredentialManager', 38 | 'dbatools', 39 | 'EZOut', 40 | 'HistoryPx', 41 | 'InvokeBuild', 42 | 'msonline', 43 | 'PackageManagement', 44 | 'Pansies', 45 | 'platyPS', 46 | 'posh-git', 47 | 'PowerLine', 48 | 'PowerShellGet', 49 | 'powershell-yaml', 50 | 'psake', 51 | 'PSCodeHealth', 52 | 'PSDecode', 53 | 'PSDepend', 54 | 'PSGit', 55 | 'PSGraph', 56 | 'psmsgraph', 57 | 'PSScriptAnalyzer', 58 | 'SharePointPnPPowerShellOnline', 59 | 'SnippetPx', 60 | 'WinSCP', 61 | 'OhMyPsh' 62 | ) 63 | 64 | # Chocolatey packages to install 65 | $ChocoInstalls = @( 66 | 'toolsroot', 67 | 'vcredist140', 68 | '7zip', 69 | '7zip.commandline', 70 | 'amazon-music', 71 | 'cmder', 72 | 'curl', 73 | 'f.lux' 74 | 'dotnet4.7.1', 75 | 'dropbox', 76 | 'Firefox', 77 | 'foxitreader', 78 | 'git', 79 | 'git-credential-manager-for-windows', 80 | 'git-credential-winstore', 81 | 'gitextensions', 82 | 'GoogleChrome', 83 | 'sysinternals' 84 | 'hub', 85 | 'keypirinha', 86 | 'nano', 87 | 'nmap', 88 | 'notepadplusplus', 89 | 'nuget.commandline', 90 | 'paint.net', 91 | 'PDFCreator', 92 | 'procexp', 93 | 'putty', 94 | 'python', 95 | 'python3', 96 | 'sharex', 97 | 'superputty', 98 | 'terminals', 99 | 'virtualbox', 100 | 'VirtualBox.ExtensionPack', 101 | 'VirtualCloneDrive', 102 | 'vlc', 103 | 'windirstat', 104 | 'winscp', 105 | 'wireshark', 106 | 'etcher', 107 | 'visualstudiocode', 108 | 'imageglass', 109 | 'rapidee', 110 | 'hackfont', 111 | 'microsoft-teams' 112 | ) 113 | 114 | # Chocolatey places a bunch of crap on the desktop after installing or updating software. This flag allows 115 | # you to clean that up (Note: this will move *.lnk files from the Public user profile desktop and your own 116 | # desktop to a new directory called 'shortcuts' on your desktop. This may or may not be what you want..) 117 | $ClearDesktopShortcuts = $True 118 | 119 | # Add a folder to place your nefarious executables in so you can infect yourself (or run hacker tools like I do) 120 | $BypassDefenderPaths = @('C:\_ByPassDefender') 121 | 122 | # Downloads of non-chocolatey installed apps will go here (within system root) 123 | $UtilDownloadPath = join-path $env:systemdrive 'Utilities\Downloads' 124 | 125 | # Hahicorp manually installed apps go here and this gets added to your path 126 | $UtilBinPath = join-path $env:systemdrive 'Utilities\bin' 127 | 128 | # some manual installs: vscode-insiders, typora, and skypeonline powershell module (as examples) 129 | $ManualDownloadInstall = @{ 130 | 'vscodeinsiders.exe' = 'https://go.microsoft.com/fwlink/?Linkid=852155' 131 | # 'vscode.exe' = 'https://go.microsoft.com/fwlink/?linkid=852157' 132 | 'typora-setup-x64.exe' = 'https://typora.io/windows/typora-setup-x64.exe' 133 | 'skypeonlinepowershell.exe' = 'https://download.microsoft.com/download/2/0/5/2050B39B-4DA5-48E0-B768-583533B42C3B/SkypeOnlinePowershell.exe' 134 | 'keybase_setup_386.exe' = 'https://prerelease.keybase.io/keybase_setup_386.exe' 135 | } 136 | 137 | # Releases based github packages to download and install. I include Keeweb,Dokany (used for Keybase explorer integration), and pandoc 138 | $GithubReleasesPackages = @{ 139 | 'keeweb/keeweb' = "keeweb*win.x64.exe" 140 | 'dokan-dev/dokany' = "DokanSetup.exe" 141 | 'jgm/pandoc' = "pandoc-*-windows.msi" 142 | } 143 | 144 | # Hashicorp packages to install directly from their website 145 | $HashicorpPackages = @('vagrant', 'terraform', 'vault') 146 | 147 | # Change for whatever platform you want to download for 148 | $HashicorpOS = 'windows' 149 | 150 | # Architecture to download for (default is 64 bit) 151 | $HashicorpArch = "amd64|x86_64" 152 | 153 | # Visual Studio Code extensions to install (both code-insiders and code if available) 154 | $VSCodeExtensions = @( 155 | 'adamvoss.yaml', 156 | 'bierner.markdown-preview-github-styles', 157 | 'donjayamanne.githistory', 158 | 'DotJoshJohnson.xml', 159 | 'eriklynd.json-tools', 160 | 'formulahendry.azure-storage-explorer', 161 | 'ms-mssql.mssql', 162 | 'ms-python.python', 163 | 'ms-vscode.azure-account', 164 | 'ms-vscode.PowerShell', 165 | 'msazurermtools.azurerm-vscode-tools', 166 | 'robertohuertasm.vscode-icons', 167 | 'samcogan.arm-snippets', 168 | 'Shan.code-settings-sync' 169 | ) 170 | 171 | # Use the $MyPowerShellProfile to create a new powershell profile if one doesn't already exist 172 | $CreatePowershellProfile = $TRUE 173 | $MyPowerShellProfile = @' 174 | ## Detect if we are running powershell without a console. 175 | $_ISCONSOLE = $TRUE 176 | try { 177 | [System.Console]::Clear() 178 | } 179 | catch { 180 | $_ISCONSOLE = $FALSE 181 | } 182 | 183 | # Everything in this block is only relevant in a console. This keeps nonconsole based powershell sessions clean. 184 | if ($_ISCONSOLE) { 185 | ## Check SHIFT state ASAP at startup so we can use that to control verbosity :) 186 | try { 187 | Add-Type -Assembly PresentationCore, WindowsBase 188 | if ([System.Windows.Input.Keyboard]::IsKeyDown([System.Windows.Input.Key]::LeftShift) -or [System.Windows.Input.Keyboard]::IsKeyDown([System.Windows.Input.Key]::RightShift)) { 189 | $VerbosePreference = "Continue" 190 | } 191 | } 192 | catch { 193 | # Maybe this is a non-windows host? 194 | } 195 | 196 | ## Set the profile directory variable for possible use later 197 | Set-Variable ProfileDir (Split-Path $MyInvocation.MyCommand.Path -Parent) -Scope Global -Option AllScope, Constant -ErrorAction SilentlyContinue 198 | 199 | # Start OhMyPsh only if we are in a console 200 | if ($Host.Name -eq 'ConsoleHost') { 201 | if (Get-Module OhMyPsh -ListAvailable) { 202 | Import-Module OhMyPsh 203 | } 204 | } 205 | } 206 | 207 | # Relax the code signing restriction so we can actually get work done 208 | Import-module Microsoft.PowerShell.Security 209 | Set-ExecutionPolicy RemoteSigned Process 210 | '@ 211 | # ***** END CUSTOMIZATION ***** 212 | Function ReRunScriptElevated { 213 | if ( -not ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]'Administrator') ) { 214 | Start-Process powershell.exe "-NoProfile -ExecutionPolicy Bypass -File `"$PSCommandPath`" $PSCommandArgs" -WorkingDirectory $pwd -Verb RunAs 215 | Exit 216 | } 217 | } 218 | 219 | Function ReRunScript { 220 | Start-Process powershell.exe "-NoProfile -ExecutionPolicy Bypass -File `"$PSCommandPath`" $PSCommandArgs" -WorkingDirectory $pwd -Verb RunAs 221 | Exit 222 | } 223 | 224 | Function Get-SpecialPaths { 225 | $SpecialFolders = @{} 226 | 227 | $names = [Environment+SpecialFolder]::GetNames([Environment+SpecialFolder]) 228 | 229 | foreach ($name in $names) { 230 | $SpecialFolders[$name] = [Environment]::GetFolderPath($name) 231 | } 232 | 233 | $SpecialFolders 234 | } 235 | 236 | Function Get-EnvironmentVariableNames { 237 | param ( 238 | [string]$Scope 239 | ) 240 | 241 | ([Environment]::GetEnvironmentVariables($Scope).GetEnumerator()).Name 242 | } 243 | 244 | Function Get-EnvironmentVariable { 245 | param ( 246 | [string]$Name, 247 | [string]$Scope 248 | ) 249 | 250 | [Environment]::GetEnvironmentVariable($Name, $Scope) 251 | } 252 | Function Update-SessionEnvironment { 253 | <# 254 | Ripped directly from the chocolatey project, used here just for initial setup 255 | #> 256 | $refreshEnv = $false 257 | $invocation = $MyInvocation 258 | if ($invocation.InvocationName -eq 'refreshenv') { 259 | $refreshEnv = $true 260 | } 261 | 262 | if ($refreshEnv) { 263 | Write-Output "Refreshing environment variables from the registry for powershell.exe. Please wait..." 264 | } 265 | else { 266 | Write-Verbose "Refreshing environment variables from the registry." 267 | } 268 | 269 | $userName = $env:USERNAME 270 | $architecture = $env:PROCESSOR_ARCHITECTURE 271 | $psModulePath = $env:PSModulePath 272 | 273 | #ordering is important here, $user comes after so we can override $machine 274 | 'Process', 'Machine', 'User' | 275 | % { 276 | $scope = $_ 277 | Get-EnvironmentVariableNames -Scope $scope | 278 | % { 279 | Set-Item "Env:$($_)" -Value (Get-EnvironmentVariable -Scope $scope -Name $_) 280 | } 281 | } 282 | 283 | #Path gets special treatment b/c it munges the two together 284 | $paths = 'Machine', 'User' | 285 | % { 286 | (Get-EnvironmentVariable -Name 'PATH' -Scope $_) -split ';' 287 | } | Select-Object -Unique 288 | $Env:PATH = $paths -join ';' 289 | 290 | # PSModulePath is almost always updated by process, so we want to preserve it. 291 | $env:PSModulePath = $psModulePath 292 | 293 | # reset user and architecture 294 | if ($userName) { $env:USERNAME = $userName; } 295 | if ($architecture) { $env:PROCESSOR_ARCHITECTURE = $architecture; } 296 | 297 | if ($refreshEnv) { 298 | Write-Output "Finished" 299 | } 300 | } 301 | 302 | Function Add-EnvPath { 303 | # Adds a path to the $ENV:Path list for a user or system if it does not already exist (in both the system and user Path variables) 304 | param ( 305 | [string]$Location, 306 | [string]$NewPath 307 | ) 308 | 309 | $AllPaths = $Env:Path -split ';' 310 | if ($AllPaths -notcontains $NewPath) { 311 | Write-Output "Adding Utilties bin directory path to the environmental path list: $UtilBinPath" 312 | 313 | $NewPaths = (@(([Environment]::GetEnvironmentVariables($Location).GetEnumerator() | Where {$_.Name -eq 'Path'}).Value -split ';') + $UtilBinPath | Select-Object -Unique) -join ';' 314 | 315 | [Environment]::SetEnvironmentVariable("PATH", $NewPaths, $Location) 316 | } 317 | } 318 | 319 | function Start-Proc { 320 | param([string]$Exe = $(Throw "An executable must be specified"), 321 | [string]$Arguments, 322 | [switch]$Hidden, 323 | [switch]$waitforexit) 324 | 325 | $startinfo = New-Object System.Diagnostics.ProcessStartInfo 326 | $startinfo.FileName = $Exe 327 | $startinfo.Arguments = $Arguments 328 | if ($Hidden) { 329 | $startinfo.WindowStyle = 'Hidden' 330 | $startinfo.CreateNoWindow = $True 331 | } 332 | $process = [System.Diagnostics.Process]::Start($startinfo) 333 | if ($waitforexit) { $process.WaitForExit() } 334 | } 335 | 336 | function Get-HashiCorpLatestVersion { 337 | <# 338 | function to find the most recent version in the json manifest 339 | Note: We ignore anything not in strict x.x.x version format (betas and such) 340 | #> 341 | param( 342 | $manifest, 343 | $software 344 | ) 345 | 346 | (($manifest.$software.versions | get-member -MemberType 'NoteProperty').Name | Where {$_ -match "^\d+\.\d+\.\d+$"} | ForEach-Object {[version]$_} | Sort-Object -Descending | Select-Object -First 1).ToString() 347 | } 348 | 349 | function Get-AllHashiCorpPackageLatestVersion { 350 | <# 351 | .SYNOPSIS 352 | Retreives the most recent version of Hashicorp software packages from a json manifest 353 | .DESCRIPTION 354 | Retreives the most recent version of Hashicorp software packages from a json manifest 355 | .PARAMETER manifest 356 | JSON manifest data to search. 357 | .EXAMPLE 358 | Get-AllHashiCorpPackageLatestVersion 359 | .NOTES 360 | Author: Zachary Loeber 361 | #> 362 | param( 363 | $manifest 364 | ) 365 | 366 | $OutHash = @{} 367 | 368 | $manifest | Get-Member -MemberType 'NoteProperty' | Foreach { 369 | $OutHash.($_.Name) = Get-HashiCorpLatestVersion $manifest $_.Name 370 | } 371 | 372 | $OutHash 373 | } 374 | 375 | function Get-ChocoPackages { 376 | if (get-command clist -ErrorAction:SilentlyContinue) { 377 | clist -lo -r -all | Foreach { 378 | $Name, $Version = $_ -split '\|' 379 | New-Object -TypeName psobject -Property @{ 380 | 'Name' = $Name 381 | 'Version' = $Version 382 | } 383 | } 384 | } 385 | } 386 | 387 | # Add a path for windows defender to bypass 388 | function Add-DefenderBypassPath { 389 | [CmdletBinding()] 390 | param( 391 | [Parameter(Mandatory = $true, ValueFromPipeline = $true)] 392 | [string[]]$Path 393 | ) 394 | begin { 395 | $Paths = @() 396 | } 397 | process { 398 | $Paths += $Path 399 | } 400 | end { 401 | $Paths | Foreach-Object { 402 | if (-not [string]::isnullorempty($_)) { 403 | Add-MpPreference -ExclusionPath $_ -Force 404 | } 405 | } 406 | } 407 | } 408 | 409 | # Rerun elevated if required 410 | ReRunScriptElevated 411 | 412 | # Need this to download via Invoke-WebRequest 413 | [Net.ServicePointManager]::SecurityProtocol = [System.Security.Authentication.SslProtocols] "tls, tls11, tls12" 414 | 415 | # Trust the psgallery for installs 416 | Write-Host -ForegroundColor 'Yellow' 'Setting PSGallery as a trusted installation source...' 417 | Set-PSRepository -Name PSGallery -InstallationPolicy Trusted 418 | 419 | # Install/Update PowershellGet and PackageManager if needed 420 | try { 421 | Import-Module PowerShellGet 422 | } 423 | catch { 424 | throw 'Unable to load PowerShellGet!' 425 | } 426 | 427 | # Need to set Nuget as a provider before installing modules via PowerShellGet 428 | $null = Install-PackageProvider NuGet -Force 429 | 430 | # Store a few things for later use 431 | $SpecialPaths = Get-SpecialPaths 432 | $packages = Get-Package 433 | 434 | if (@($packages | Where-Object {$_.Name -eq 'PackageManagement'}).Count -eq 0) { 435 | Write-Host -ForegroundColor cyan "PackageManager is installed but not being maintained via the PowerShell gallery (so it will never get updated). Forcing the install of this module through the gallery to rectify this now." 436 | Install-Module PackageManagement -Force 437 | Install-Module PowerShellGet -Force 438 | 439 | Write-Host -ForegroundColor:Red "PowerShellGet and PackageManagement have been installed from the gallery. You need to close and rerun this script for them to work properly!" 440 | 441 | # Rerun this script if we got this far as upgrading packagemanagament seems to require it after an update 442 | ReRunScript 443 | } 444 | else { 445 | $InstalledModules = (Get-InstalledModule).name 446 | $ModulesToBeInstalled = $ModulesToBeInstalled | Where-Object {$InstalledModules -notcontains $_} 447 | if ($ModulesToBeInstalled.Count -gt 0) { 448 | Write-Host -ForegroundColor:cyan "Installing modules that are not already installed via powershellget. Modules to be installed = $($ModulesToBeInstalled.Count)" 449 | Install-Module -Name $ModulesToBeInstalled -AllowClobber -AcceptLicense -ErrorAction:SilentlyContinue 450 | } 451 | else { 452 | Write-Output "No modules were found that needed to be installed." 453 | } 454 | } 455 | 456 | if ($null -eq (get-command choco.exe -ErrorAction SilentlyContinue)) { 457 | Invoke-Expression ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1')) 458 | ReRunScript 459 | } 460 | # Install any chocolatey packages now 461 | Write-Output "Installing software via chocolatey" 462 | 463 | # We run upgrade which will install the software if it doesn't exist or upgrade it if it does. 464 | if ($ChocoInstalls.Count -gt 0) { 465 | # Install a ton of other crap I use or like, update $ChocoInsalls to suit your needs of course 466 | $ChocoInstalls | Foreach-Object { 467 | try { 468 | choco upgrade -y $_ --cacheLocation "$($env:userprofile)\AppData\Local\Temp\chocolatey" 469 | } 470 | catch { 471 | Write-Warning "Unable to install software package with Chocolatey: $($_)" 472 | } 473 | } 474 | } 475 | else { 476 | Write-Output 'There were no packages to install!' 477 | } 478 | 479 | <# 480 | Manually installed packages (not in chocolatey or packagemanager) 481 | #> 482 | If (-not (Test-Path $UtilDownloadPath)) { 483 | mkdir $UtilDownloadPath -Force 484 | } 485 | If (-not (Test-Path $UtilBinPath)) { 486 | mkdir $UtilBinPath -Force 487 | } 488 | 489 | Push-Location $UtilDownloadPath 490 | # Store all the file we download for later processing 491 | $FilesDownloaded = @() 492 | 493 | <# 494 | Hashicorp recent app downloads 495 | - Find and download the most recent versions of Hashicorp applications as defined in 496 | $HashicorpPackages. Ignores all plugins and providers. 497 | #> 498 | $HashicorpReleaseManifestURL = 'https://releases.hashicorp.com/index.json' 499 | $HashiCorpJSONreq = (Invoke-WebRequest -Uri $HashicorpReleaseManifestURL -UseBasicParsing).Content | ConvertFrom-JSON 500 | $HashiCorpJSONreq | Get-Member -MemberType 'NoteProperty' | Where-Object { $_.Name -notmatch "provider|plugin" } | ForEach-Object { 501 | $software = $_.Name 502 | $recentversion = Get-HashiCorpLatestVersion $HashiCorpJSONreq $software 503 | if ($HashicorpPackages -contains $software) { 504 | Write-Output "Found $software - $recentversion" 505 | $HashiCorpJSONreq.$software.Versions.$recentversion.builds | Where {($_.os -eq $HashicorpOS) -and ($_.arch -match $HashicorpArch)} | Foreach { 506 | if ( -not (Test-Path $_.filename)) { 507 | try { 508 | Invoke-WebRequest -Uri $_.url -OutFile $_.filename 509 | $FilesDownloaded += $_.filename 510 | } 511 | catch {} 512 | } 513 | else { 514 | Write-Warning "Hashicorp file is already downloaded, skipping: $($_.filename)" 515 | } 516 | } 517 | } 518 | } 519 | 520 | # Github releases based software. 521 | Foreach ($software in $GithubReleasesPackages.keys) { 522 | $releases = "https://api.github.com/repos/$software/releases" 523 | Write-Output "Determining latest release for repo $Software" 524 | $tag = (Invoke-WebRequest $releases -UseBasicParsing | ConvertFrom-Json)[0] 525 | $tag.assets | ForEach-Object { 526 | if ($_.name -like $GithubReleasesPackages[$software]) { 527 | if ( -not (Test-Path $_.name)) { 528 | try { 529 | Write-Output "Downloading $($_.name)..." 530 | Invoke-WebRequest $_.'browser_download_url' -OutFile $_.Name 531 | $FilesDownloaded += $_.Name 532 | } 533 | catch {} 534 | } 535 | else { 536 | Write-Warning "File is already downloaded, skipping: $($_.Name)" 537 | } 538 | } 539 | } 540 | } 541 | 542 | # Manually downloaded software 543 | Foreach ($software in $ManualDownloadInstall.keys) { 544 | Write-Output "Downloading $software" 545 | if ( -not (Test-Path $software) ) { 546 | try { 547 | Invoke-WebRequest $ManualDownloadInstall[$software] -OutFile $software -UseBasicParsing 548 | $FilesDownloaded += $software 549 | } 550 | catch {} 551 | } 552 | else { 553 | Write-Warning "File is already downloaded, skipping: $software" 554 | } 555 | } 556 | 557 | # Extracting self-contained binaries (zip files) to our bin folder 558 | Write-Output 'Extracting self-contained binaries (zip files) to our bin folder' 559 | Get-ChildItem -Path $UtilDownloadPath -File -Filter '*.zip' | Where {$FilesDownloaded -contains $_.Name} | ForEach-Object { 560 | Expand-Archive -Path $_.FullName -DestinationPath $UtilBinPath -Force 561 | } 562 | 563 | Add-EnvPath -Location 'User' -NewPath $UtilBinPath 564 | Update-SessionEnvironment 565 | 566 | # Kick off exe installs 567 | Get-ChildItem -Path $UtilDownloadPath -File -Filter '*.exe' | Where {$FilesDownloaded -contains $_.Name} | ForEach-Object { 568 | Start-Proc -Exe $_.FullName -waitforexit 569 | } 570 | 571 | # Kick off msi installs 572 | Get-ChildItem -Path $UtilDownloadPath -File -Filter '*.msi' | Where {$FilesDownloaded -contains $_.Name} | ForEach-Object { 573 | Start-Proc -Exe $_.FullName -waitforexit 574 | } 575 | 576 | <# 577 | Configuration 578 | #> 579 | 580 | # keyprinha ini setup. If you don't use this launchy alternative then don't run this. 581 | $keypirinhaconfigdata = @' 582 | [app] 583 | launch_at_startup = yes 584 | hotkey_run = Alt+Space 585 | escape_always_closes = yes 586 | '@ 587 | 588 | if ($null -ne (Get-Command 'keypirinha.exe' -ErrorAction:SilentlyContinue)) { 589 | Write-Output 'Found keypirinha, attempting to configure...' 590 | if ($null -eq (Get-Process -Name 'keypirinha-x64' -ErrorAction:SilentlyContinue)) { 591 | Write-Output ' Need to start KeyPirinha at least once to get the app directories created' 592 | . 'keypirinha.exe' 593 | } 594 | 595 | $keypirinhaconfig = join-path $SpecialPaths['ApplicationData'] 'Keypirinha\User\Keypirinha.ini' 596 | if (-not (Test-Path $keypirinhaconfig)) { 597 | Write-Output ' No custom user keypirinha config found, creating one that binds Alt+Space to launch the app..' 598 | $keypirinhaconfigdata | Out-File -FilePath $keypirinhaconfig -Encoding:utf8 -Force 599 | Stop-Process -Name 'keypirinha-x64' -ErrorAction:SilentlyContinue 600 | . 'keypirinha.exe' 601 | } 602 | else { 603 | Write-Warning "KeyPirinha user config file already found and NOT overwritten: $keypirinhaconfig" 604 | } 605 | } 606 | 607 | # Visual Studio Code extension setup 608 | if ($null -ne (get-command 'code-insiders' -ErrorAction:SilentlyContinue)) { 609 | Write-Host "Installing $($VSCodeExtensions.count) extensions to VS Code Insiders" 610 | $VSCodeExtensions | ForEach-Object { 611 | code-insiders --install-extension $_ 612 | } 613 | } 614 | 615 | # Visual Studio Code extension setup 616 | if ($null -ne (get-command 'code' -ErrorAction:SilentlyContinue)) { 617 | Write-Host "Installing $($VSCodeExtensions.count) extensions to VS Code" 618 | $VSCodeExtensions | ForEach-Object { 619 | code --install-extension $_ 620 | } 621 | } 622 | 623 | # Setup Defender bypass directory 624 | if ($BypassDefenderPaths.Count -gt 0) { 625 | Write-Output 'Adding defender paths to bypass...' 626 | $ByPassDefenderPaths | Add-DefenderBypassPath 627 | } 628 | 629 | if ($ClearDesktopShortcuts) { 630 | $Desktop = $SpecialPaths['DesktopDirectory'] 631 | $DesktopShortcuts = Join-Path $Desktop 'Shortcuts' 632 | if (-not (Test-Path $DesktopShortcuts)) { 633 | Write-Host -ForegroundColor:Cyan "Creating a new shortcuts folder on your desktop and moving all .lnk files to it: $DesktopShortcuts" 634 | $null = mkdir $DesktopShortcuts 635 | } 636 | 637 | Write-Output "Moving .lnk files from $($SpecialPaths['CommonDesktopDirectory']) to the Shortcuts folder" 638 | Get-ChildItem -Path $SpecialPaths['CommonDesktopDirectory'] -Filter '*.lnk' | ForEach-Object { 639 | Move-Item -Path $_.FullName -Destination $DesktopShortcuts -ErrorAction:SilentlyContinue 640 | } 641 | 642 | Write-Output "Moving .lnk files from $Desktop to the Shortcuts folder" 643 | Get-ChildItem -Path $Desktop -Filter '*.lnk' | ForEach-Object { 644 | Move-Item -Path $_.FullName -Destination $DesktopShortcuts -ErrorAction:SilentlyContinue 645 | } 646 | } 647 | 648 | if ($CreatePowershellProfile) { 649 | if (-not (Test-Path $PROFILE)) { 650 | $ControlledFolderAccess = (Get-MpPreference).EnableControlledFolderAccess 651 | Set-MpPreference -EnableControlledFolderAccess 0 652 | Write-Output 'Creating user powershell profile...' 653 | $MyPowerShellProfile | Out-File -FilePath $PROFILE -Encoding:utf8 -Force 654 | Set-MpPreference -EnableControlledFolderAccess $ControlledFolderAccess 655 | } 656 | else { 657 | Write-Warning "Powershell profile already exists!" 658 | } 659 | } 660 | 661 | Pop-Location 662 | -------------------------------------------------------------------------------- /Scripts/Install-HashiCorpApps.ps1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zloeber/WindowsSetupScripts/830e5b5adc6aea06dd92219ff3fe374d61dc2013/Scripts/Install-HashiCorpApps.ps1 -------------------------------------------------------------------------------- /Scripts/Install-WSL.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | Installs Windows subsystem for linux (WSL) option if not already configured. Also downloads and starts the distro setup. 4 | .DESCRIPTION 5 | Installs Windows subsystem for linux (WSL) option if not already configured. Also downloads and starts the distro setup. Supports ubuntu, sles, and opensuse. 6 | .PARAMETER InstallPath 7 | Path to install chosen WSL distribution 8 | .PARAMETER Distro 9 | Distro to attempt to download and install 10 | .EXAMPLE 11 | .\Install-WSL.ps1 12 | 13 | Configures the WSL feature if required then attempts to install the ubuntu wsl distribution to C:\WSLDistros\Ubuntu 14 | .NOTES 15 | Author: Zachary Loeber 16 | - The downloads are skipped if already found in the $env:temp directory. 17 | - The installer process may fail without a reboot between the feature install and the distro installer running. 18 | - Unregister or manage the default distro install via wslconfig.exe 19 | .LINK 20 | https://docs.microsoft.com/en-us/windows/wsl/install-on-server 21 | #> 22 | [CmdletBinding()] 23 | param( 24 | [Parameter(HelpMessage = 'Path to save and install WSL distro to.')] 25 | [string]$InstallPath = 'C:\WSLDistros\Ubuntu', 26 | [Parameter(HelpMessage = 'Distro to attempt to download and install')] 27 | [ValidateSet('ubuntu', 'opensuse', 'sles')] 28 | [string]$Distro = 'ubuntu' 29 | ) 30 | 31 | Begin { 32 | $WSLDownloadPath = Join-Path $ENV:TEMP "$Distro.zip" 33 | $DistroURI = @{ 34 | 'ubuntu' = 'https://aka.ms/wsl-ubuntu-1604' 35 | 'sles' = 'https://aka.ms/wsl-sles-12' 36 | 'opensuse' = 'https://aka.ms/wsl-opensuse-42' 37 | } 38 | $DistroEXE = @{ 39 | 'ubuntu' = 'ubuntu.exe' 40 | 'sles' = 'SLES-12.exe' 41 | 'opensuse' = 'openSUSE-42.exe' 42 | } 43 | 44 | function Start-Proc { 45 | param([string]$Exe = $(Throw "An executable must be specified"), 46 | [string]$Arguments, 47 | [switch]$Hidden, 48 | [switch]$waitforexit) 49 | 50 | $startinfo = New-Object System.Diagnostics.ProcessStartInfo 51 | $startinfo.FileName = $Exe 52 | $startinfo.Arguments = $Arguments 53 | if ($Hidden) { 54 | $startinfo.WindowStyle = 'Hidden' 55 | $startinfo.CreateNoWindow = $True 56 | } 57 | $process = [System.Diagnostics.Process]::Start($startinfo) 58 | if ($waitforexit) { $process.WaitForExit() } 59 | } 60 | 61 | Function ReRunScriptElevated { 62 | if ( -not ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]'Administrator') ) { 63 | Start-Process powershell.exe "-NoProfile -ExecutionPolicy Bypass -File `"$PSCommandPath`" $PSCommandArgs" -WorkingDirectory $pwd -Verb RunAs 64 | Exit 65 | } 66 | } 67 | 68 | ReRunScriptElevated 69 | } 70 | end { 71 | if ((Get-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux).State -ne 'Enabled') { 72 | try { 73 | Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux -NoRestart 74 | } 75 | catch { 76 | Write-Warning 'Unable to install the WSL feature!' 77 | } 78 | } 79 | else { 80 | Write-Output 'Windows subsystem for Linux optional feature already installed!' 81 | } 82 | 83 | $InstalledWSLDistros = @((Get-ChildItem 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Lxss' -ErrorAction:SilentlyContinue | ForEach-Object { Get-ItemProperty $_.pspath }).DistributionName) 84 | 85 | $WSLExe = Join-Path $InstallPath $DistroEXE[$Distro] 86 | 87 | if ($InstalledWSLDistros -notcontains $Distro) { 88 | Write-Output "WSL distro $Distro is not found to be installed on this system, attempting to download and install it now..." 89 | 90 | if (-not (Test-Path $WSLDownloadPath)) { 91 | Invoke-WebRequest -Uri $DistroURI[$Distro] -OutFile $WSLDownloadPath -UseBasicParsing 92 | } 93 | else { 94 | Write-Warning "The $Distro zip file appears to already be downloaded." 95 | } 96 | 97 | Expand-Archive $WSLDownloadPath $InstallPath -Force 98 | 99 | if (Test-Path $WSLExe) { 100 | Write-Output "Starting $WSLExe" 101 | Start-Proc -Exe $WSLExe -waitforexit 102 | } 103 | else { 104 | Write-Warning " $WSLExe was not found for whatever reason" 105 | } 106 | } 107 | else { 108 | Write-Warning "Found $Distro is already installed on this system. Enter it simply by typing bash.exe" 109 | } 110 | } -------------------------------------------------------------------------------- /Scripts/Show-Config.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .DESCRIPTION 3 | Displays the settings for a Windows customization configuration file. 4 | #> 5 | [CmdletBinding()] 6 | param( 7 | [Parameter(HelpMessage='Configuration file to load')] 8 | [string]$Configuration = (Join-Path $PSScriptRoot 'config.json') 9 | ) 10 | 11 | begin { 12 | try { 13 | $Definitions = Get-Content 'definitions.json' | ConvertFrom-Json 14 | $Definitions = $Definitions | Sort-Object -Property 'Group' 15 | } 16 | catch { 17 | throw 'Unable to load the definitions.json file!' 18 | } 19 | 20 | # Create a hash of lookup values (minus any 'skip' options) 21 | $DefinitionLookup = @{} 22 | Foreach ($Def in $Definitions) { 23 | $Def.Choices | ForEach-Object { 24 | if ($_ -ne '&Skip') { 25 | $key = ($_ -replace '&','') 26 | Write-Verbose "Adding Definition: $Key" 27 | Write-Verbose " Group: $($Def.Group)" 28 | Write-Verbose " Description: $($Def.Description)" 29 | $DefinitionLookup[$key] = @($Def.Group, $Def.Description) 30 | } 31 | } 32 | } 33 | 34 | try { 35 | $Config = Get-Content $Configuration | ConvertFrom-Json 36 | } 37 | catch { 38 | throw "Unable to load the configuration file: $Configuration" 39 | } 40 | 41 | $Config | ForEach-Object { 42 | Write-Verbose "Action = $_" 43 | New-Object -TypeName psobject -Property @{ 44 | 'Action' = $_ 45 | 'Category' = $DefinitionLookup[$_][0] 46 | 'Description' = $DefinitionLookup[$_][1] 47 | } 48 | } 49 | } -------------------------------------------------------------------------------- /Scripts/WSLFunctions.ps1: -------------------------------------------------------------------------------- 1 | Function Install-WSL { 2 | <# 3 | .SYNOPSIS 4 | Installs Windows subsystem for linux (WSL) as well as downloads, starts the distro setup. Supports ubuntu, sles, and opensuse 5 | .DESCRIPTION 6 | Installs Windows subsystem for linux (WSL) as well as downloads, starts the distro setup. Supports ubuntu, sles, and opensuse. 7 | .PARAMETER InstallPath 8 | Path to save and install WSL distro to 9 | .PARAMETER Distro 10 | Distro to attempt to download and install 11 | .EXAMPLE 12 | .\Install-WSL.ps1 13 | 14 | Configures the WSL feature if required then attempts to install the ubuntu wsl distrobution to C:\WSLDistros\Ubuntu 15 | .NOTES 16 | Author: Zachary Loeber 17 | 18 | - I've only really tested the ubuntu installer. This is the only distro that is currently setup to autoupdate after the initial installation. 19 | - The downloads are skipped if already found in the $env:temp directory. 20 | - The installer process may fail without a reboot inbetween the feature install and the distro installer running. 21 | - Unregister or manage the default distro install via wslconfig.exe 22 | .LINK 23 | https://docs.microsoft.com/en-us/windows/wsl/install-on-server 24 | #> 25 | [CmdletBinding()] 26 | param( 27 | [Parameter(HelpMessage = 'Path to save and install WSL distro to.')] 28 | [string]$InstallPath = 'C:\WSLDistros\Ubuntu', 29 | [Parameter(HelpMessage = 'Distro to attempt to download and install')] 30 | [ValidateSet('ubuntu', 'opensuse', 'sles')] 31 | [string]$Distro = 'ubuntu' 32 | ) 33 | 34 | Begin { 35 | $WSLDownloadPath = Join-Path $ENV:TEMP "$Distro.zip" 36 | $DistroURI = @{ 37 | 'ubuntu' = 'https://aka.ms/wsl-ubuntu-1604' 38 | 'sles' = 'https://aka.ms/wsl-sles-12' 39 | 'opensuse' = 'https://aka.ms/wsl-opensuse-42' 40 | } 41 | $DistroEXE = @{ 42 | 'ubuntu' = 'ubuntu.exe' 43 | 'sles' = 'SLES-12.exe' 44 | 'opensuse' = 'openSUSE-42.exe' 45 | } 46 | 47 | function Start-Proc { 48 | param([string]$Exe = $(Throw "An executable must be specified"), 49 | [string]$Arguments, 50 | [switch]$Hidden, 51 | [switch]$waitforexit) 52 | 53 | $startinfo = New-Object System.Diagnostics.ProcessStartInfo 54 | $startinfo.FileName = $Exe 55 | $startinfo.Arguments = $Arguments 56 | if ($Hidden) { 57 | $startinfo.WindowStyle = 'Hidden' 58 | $startinfo.CreateNoWindow = $True 59 | } 60 | $process = [System.Diagnostics.Process]::Start($startinfo) 61 | if ($waitforexit) { $process.WaitForExit() } 62 | } 63 | 64 | Function ReRunScriptElevated { 65 | if ( -not ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]'Administrator') ) { 66 | Start-Process powershell.exe "-NoProfile -ExecutionPolicy Bypass -File `"$PSCommandPath`" $PSCommandArgs" -WorkingDirectory $pwd -Verb RunAs 67 | Exit 68 | } 69 | } 70 | 71 | ReRunScriptElevated 72 | } 73 | end { 74 | if ((Get-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux).State -ne 'Enabled') { 75 | try { 76 | Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux -NoRestart 77 | } 78 | catch { 79 | Write-Warning 'Unable to install the WSL feature!' 80 | } 81 | } 82 | else { 83 | Write-Output 'Windows subsystem for Linux optional feature already installed!' 84 | } 85 | 86 | $InstalledWSLDistros = @((Get-ChildItem 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Lxss' -ErrorAction:SilentlyContinue | ForEach-Object { Get-ItemProperty $_.pspath }).DistributionName) 87 | 88 | $WSLExe = Join-Path $InstallPath $DistroEXE[$Distro] 89 | 90 | if ($InstalledWSLDistros -notcontains $Distro) { 91 | Write-Output "WSL distro $Distro is not found to be installed on this system, attempting to download and install it now..." 92 | 93 | if (-not (Test-Path $WSLDownloadPath)) { 94 | Invoke-WebRequest -Uri $DistroURI[$Distro] -OutFile $WSLDownloadPath -UseBasicParsing 95 | } 96 | else { 97 | Write-Warning "The $Distro zip file appears to already be downloaded." 98 | } 99 | 100 | Expand-Archive $WSLDownloadPath $InstallPath -Force 101 | 102 | if (Test-Path $WSLExe) { 103 | Start-Proc -Exe $WSLExe -waitforexit 104 | } 105 | else { 106 | Write-Warning " $WSLExe was not found for whatever reason" 107 | } 108 | } 109 | else { 110 | Write-Warning "Found $Distro is already installed on this system. Enter it simply by typing bash.exe" 111 | } 112 | } 113 | } 114 | 115 | Function Test-WSLFeatureInstalled { 116 | <# 117 | .SYNOPSIS 118 | Validates if the WSL feature is installed or not. Only works when run elevated. 119 | .DESCRIPTION 120 | Validates if the WSL feature is installed or not. Only works when run elevated. 121 | .EXAMPLE 122 | Test-WSLFeatureInstalled 123 | .NOTES 124 | Author: Zachary Loeber 125 | If not elevated this function returns $null 126 | 127 | .LINK 128 | TBD 129 | .LINK 130 | https://docs.microsoft.com/en-us/windows/wsl/install-on-server 131 | #> 132 | 133 | try { 134 | if ((Get-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux).State -ne 'Enabled') { 135 | return $FALSE 136 | } 137 | else { 138 | return $TRUE 139 | } 140 | } 141 | catch {} 142 | } 143 | 144 | Function Get-CanonicalPath { 145 | # Used to ensure that we fix any case-sensitivity issues 146 | [CmdletBinding()] 147 | param ( 148 | [string]$Path 149 | ) 150 | begin { 151 | Function Get-RecurseCN ([string]$Path) { 152 | if ( -not [string]::IsNullOrEmpty($Path) ) { 153 | try { 154 | $CurrPath = Get-Item -Path $Path 155 | } 156 | catch { 157 | throw 158 | } 159 | if ($CurrPath -is [System.IO.DirectoryInfo]) { 160 | # this is a directory 161 | Write-Verbose "Processing Directory: $($CurrPath.ToString())" 162 | if ($null -ne $CurrPath.Parent) { 163 | # we are not at a root directory 164 | $ThisPath = $Currpath.Parent 165 | $ThisLeafPath = Split-Path $CurrPath.ToString() -leaf 166 | Write-Verbose "...Leaf Path: $ThisLeafPath" 167 | Get-CanonicalPath $ThisPath.FullName.ToString() 168 | return $ThisPath.GetDirectories($ThisLeafPath).Name 169 | } 170 | else { 171 | # We are at a drive or base location, return it lowercase to align with WSL mounting 172 | return $CurrPath.ToString().ToLower() 173 | } 174 | } 175 | elseif ($CurrPath -is [System.IO.FileInfo]) { 176 | # this is a file 177 | Write-Verbose "Processing File: $($CurrPath.ToString())" 178 | $Base = Get-Item (Get-CanonicalPath (Split-Path $CurrPath.ToString())) 179 | $LeafPath = Split-Path $CurrPath.ToString() -Leaf 180 | return $Base.GetFiles($LeafPath).FullName 181 | } 182 | else { 183 | # this is something else 184 | throw 185 | } 186 | } 187 | } 188 | 189 | ((Get-RecurseCN $Path) -join '\') -replace "\\\\",'\' 190 | } 191 | } 192 | 193 | Function ConvertTo-WSLPath { 194 | <# 195 | .SYNOPSIS 196 | Converts a Windows path to a WSL linux path. 197 | .DESCRIPTION 198 | Converts a Windows path to a WSL linux path. 199 | .PARAMETER Path 200 | The Windows path to convert. 201 | .EXAMPLE 202 | ConvertTo-WSLPath -Path 'C:\' 203 | 204 | Returns /mnt/c 205 | .NOTES 206 | Author: Zachary Loeber 207 | 208 | For this to work 209 | .LINK 210 | TBD 211 | #> 212 | [CmdletBinding()] 213 | param( 214 | [Parameter()] 215 | [string]$Path 216 | ) 217 | begin { 218 | try { 219 | $SourcePath = Get-Item -Path $Path 220 | } 221 | catch { 222 | throw 'Unable to find the source script path!' 223 | } 224 | $LinuxPath = (Get-CanonicalPath $SourcePath.toString()) -replace [regex]::Escape($SourcePath.psdrive.root), '' -replace '\\', '/' 225 | 226 | "/mnt/$(($SourcePath.PSDrive.Name).ToLower())/$LinuxPath" 227 | } 228 | } 229 | 230 | Function Invoke-CopyStartWSLScript { 231 | <# 232 | .SYNOPSIS 233 | Copies over, makes executable, and runs a shell script on WSL Linux servers. 234 | .DESCRIPTION 235 | Copies over, makes executable, and runs a shell script on WSL Linux servers. 236 | .PARAMETER Path 237 | Local path to the shell file (ie. c:\temp\setup.sh) 238 | .PARAMETER Destination 239 | Linux destination path. Default is /tmp 240 | .PARAMETER Sudo 241 | Run file as sudo user (prompts for password) 242 | .PARAMETER Distro 243 | Distribution to target. 244 | .EXAMPLE 245 | TBD 246 | .NOTES 247 | Author: Zachary Loeber 248 | .LINK 249 | https://github.com/zloeber/WindowsSetupScripts 250 | .LINK 251 | https://docs.microsoft.com/en-us/windows/wsl/install-on-server 252 | #> 253 | [CmdletBinding()] 254 | param( 255 | [Parameter()] 256 | [string]$Path, 257 | [Parameter()] 258 | [string]$Destination = '/tmp', 259 | [Parameter()] 260 | [switch]$Sudo, 261 | [Parameter()] 262 | [ValidateSet('Ubuntu', 'Opensuse', 'SLES')] 263 | [string]$Distro = 'Ubuntu' 264 | ) 265 | 266 | Begin { 267 | try { 268 | $scriptpath = Get-ChildItem -Path $Path 269 | } 270 | catch { 271 | throw 'Unable to find the source script path!' 272 | } 273 | $LinuxPath = ConvertTo-WSLPath $Path 274 | 275 | $LinuxDestScript = (Join-Path -Path $Destination -ChildPath (Split-Path -Path $scriptpath -Leaf)) -replace '\\', '/' 276 | } 277 | end { 278 | Invoke-WSLCommand "cp $LinuxPath $LinuxDestScript" -Distro:$Distro 279 | Invoke-WSLCommand "chmod +x $LinuxDestScript" -Distro:$Distro 280 | 281 | if ($Sudo) { 282 | Write-Output "Running sudo $LinuxDestScript" 283 | Invoke-WSLCommand "sudo $LinuxDestScript" -Distro:$Distro 284 | } 285 | else { 286 | Write-Output "Running $LinuxDestScript" 287 | Invoke-WSLCommand "$LinuxDestScript" -Distro:$Distro 288 | } 289 | } 290 | } 291 | 292 | Function Copy-WSLFile { 293 | <# 294 | .SYNOPSIS 295 | Copies a file to a WSL Linux instance. 296 | .DESCRIPTION 297 | Copies a file to a WSL Linux instance. 298 | .PARAMETER Path 299 | Local path to the shell file (ie. c:\temp\setup.sh) 300 | .PARAMETER Destination 301 | Linux destination path. 302 | .PARAMETER Distro 303 | Distribution to target. 304 | .EXAMPLE 305 | TBD 306 | .NOTES 307 | Author: Zachary Loeber 308 | .LINK 309 | https://github.com/zloeber/WindowsSetupScripts 310 | .LINK 311 | https://docs.microsoft.com/en-us/windows/wsl/install-on-server 312 | #> 313 | [CmdletBinding()] 314 | param( 315 | [Parameter()] 316 | [string]$Path, 317 | [Parameter()] 318 | [string]$Destination = '/tmp', 319 | [Parameter()] 320 | [ValidateSet('Ubuntu', 'Opensuse', 'SLES')] 321 | [string]$Distro = 'Ubuntu' 322 | ) 323 | 324 | Begin { 325 | try { 326 | $scriptpath = Get-ChildItem -Path $Path 327 | } 328 | catch { 329 | throw 'Unable to find the source script path!' 330 | } 331 | $LinuxPath = ConvertTo-WSLPath $Path 332 | $LinuxDestScript = (Join-Path -Path $Destination -ChildPath (Split-Path -Path $scriptpath -Leaf)) -replace '\\', '/' 333 | } 334 | end { 335 | Invoke-WSLCommand "cp $LinuxPath $LinuxDestScript" -Distro:$Distro 336 | } 337 | } 338 | 339 | Function Invoke-WSLCommand { 340 | <# 341 | .SYNOPSIS 342 | Runs a Linux command within the WSL instance. 343 | .DESCRIPTION 344 | Runs a Linux command within the WSL instance. 345 | .PARAMETER Command 346 | Command to run 347 | .PARAMETER Distro 348 | Distribution to run command against. Only tested against ubuntu. 349 | .EXAMPLE 350 | TBD 351 | .NOTES 352 | Author: Zachary Loeber 353 | .LINK 354 | TBD 355 | .LINK 356 | https://docs.microsoft.com/en-us/windows/wsl/install-on-server 357 | #> 358 | [CmdletBinding()] 359 | param( 360 | [Parameter()] 361 | [string]$Command, 362 | [Parameter()] 363 | [ValidateSet('Ubuntu', 'Opensuse', 'SLES')] 364 | [string]$Distro = 'Ubuntu' 365 | ) 366 | 367 | Begin { 368 | $DistroEXE = @{ 369 | 'Ubuntu' = 'ubuntu.exe' 370 | 'SLES' = 'SLES-12.exe' 371 | 'Opensuse' = 'openSUSE-42.exe' 372 | } 373 | if (Test-WSLFeatureInstalled -eq $FALSE) { 374 | throw 'WSL optional feature is not installed!' 375 | } 376 | } 377 | end { 378 | $InstalledWSLDistros = @{} 379 | (Get-ChildItem 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Lxss' -ErrorAction:SilentlyContinue | ForEach-Object { Get-ItemProperty $_.pspath }) | ForEach-Object { 380 | $InstalledWSLDistros.($_.DistributionName) = $_.BasePath 381 | } 382 | 383 | if ($InstalledWSLDistros.Keys -contains $Distro) { 384 | $WSLExe = Join-Path $InstalledWSLDistros[$Distro] $DistroEXE[$Distro] 385 | Write-Verbose "WSL distro $Distro found, setting exe path to $WSLExe" 386 | 387 | # Run distro specific updates and such 388 | switch ($Distro) { 389 | default { 390 | Write-Output "Executing command: $Command" 391 | try { 392 | & $WSLExe run $Command 393 | } 394 | catch { 395 | throw 396 | } 397 | } 398 | } 399 | } 400 | else { 401 | Write-Warning "$Distro not installed on this system!" 402 | } 403 | } 404 | } -------------------------------------------------------------------------------- /Scripts/definitions.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "Group": "Privacy", 4 | "Description": "Disable or enable Windows telementry services (disabling MAY break Windows updates!)", 5 | "Name": "Telemetry", 6 | "Choices": [ 7 | "\u0026Skip", 8 | "\u0026DisableTelemetry", 9 | "\u0026EnableTelemetry" 10 | ] 11 | }, 12 | { 13 | "Group": "Privacy", 14 | "Description": "Disable or enable Windows WiFi sense (Wifi sharing)", 15 | "Name": "WiFi Sense", 16 | "Choices": [ 17 | "\u0026DisableWiFiSense", 18 | "\u0026EnableWiFiSense" 19 | ] 20 | }, 21 | { 22 | "Group": "Privacy", 23 | "Description": "Disable or enable SmartScreen security in IE", 24 | "Name": "SmartScreen", 25 | "Choices": [ 26 | "\u0026Skip", 27 | "\u0026DisableSmartScreen", 28 | "\u0026EnableSmartScreen" 29 | ] 30 | }, 31 | { 32 | "Group": "Privacy", 33 | "Description": "Disable or enable bing web search in start menu results", 34 | "Name": "WebSearch", 35 | "Choices": [ 36 | "\u0026DisableWebSearch", 37 | "\u0026EnableWebSearch" 38 | ] 39 | }, 40 | { 41 | "Group": "Privacy", 42 | "Description": "Disable or enable application suggestions in start menu", 43 | "Name": "AppSuggestions", 44 | "Choices": [ 45 | "\u0026DisableAppSuggestions", 46 | "\u0026EnableAppSuggestions" 47 | ] 48 | }, 49 | { 50 | "Group": "Privacy", 51 | "Description": "Disable or enable background app installation", 52 | "Name": "BackgroundApps", 53 | "Choices": [ 54 | "\u0026DisableBackgroundApps", 55 | "\u0026EnableBackgroundApps" 56 | ] 57 | }, 58 | { 59 | "Group": "Privacy", 60 | "Description": "Disable or enable lock screen spotlight", 61 | "Name": "LockScreenSpotlight", 62 | "Choices": [ 63 | "\u0026DisableLockScreenSpotlight", 64 | "\u0026EnableLockScreenSpotlight" 65 | ] 66 | }, 67 | { 68 | "Group": "Privacy", 69 | "Description": "Disable or enable GPS location tracking", 70 | "Name": "LocationTracking", 71 | "Choices": [ 72 | "\u0026DisableLocationTracking", 73 | "\u0026EnableLocationTracking" 74 | ] 75 | }, 76 | { 77 | "Group": "Privacy", 78 | "Description": "Disable or enable map updates", 79 | "Name": "MapUpdates", 80 | "Choices": [ 81 | "\u0026DisableMapUpdates", 82 | "\u0026EnableMapUpdates" 83 | ] 84 | }, 85 | { 86 | "Group": "Privacy", 87 | "Description": "Disable or enable feedback", 88 | "Name": "Feedback", 89 | "Choices": [ 90 | "\u0026DisableFeedback", 91 | "\u0026EnableFeedback" 92 | ] 93 | }, 94 | { 95 | "Group": "Privacy", 96 | "Description": "Disable or enable advertising ID tracking", 97 | "Name": "AdvertisingID", 98 | "Choices": [ 99 | "\u0026DisableAdvertisingID", 100 | "\u0026EnableAdvertisingID" 101 | ] 102 | }, 103 | { 104 | "Group": "Privacy", 105 | "Description": "Disable or enable Cortana voice recognition", 106 | "Name": "Cortana", 107 | "Choices": [ 108 | "\u0026DisableCortana", 109 | "\u0026EnableCortana" 110 | ] 111 | }, 112 | { 113 | "Group": "Privacy", 114 | "Description": "Disable or enable error reporting uploads", 115 | "Name": "ErrorReporting", 116 | "Choices": [ 117 | "\u0026DisableErrorReporting", 118 | "\u0026EnableErrorReporting" 119 | ] 120 | }, 121 | { 122 | "Group": "Privacy", 123 | "Description": "Disable or enable peer to peer update sharing", 124 | "Name": "P2PUpdate", 125 | "Choices": [ 126 | "SetP2PUpdate\u0026Local", 127 | "SetP2PUpdate\u0026Internet" 128 | ] 129 | }, 130 | { 131 | "Group": "Privacy", 132 | "Description": "Disable or enable automatic logger", 133 | "Name": "AutoLogger", 134 | "Choices": [ 135 | "\u0026DisableAutoLogger", 136 | "\u0026EnableAutoLogger" 137 | ] 138 | }, 139 | { 140 | "Group": "Privacy", 141 | "Description": "Disable or enable diagnostics tracking", 142 | "Name": "DiagTrack", 143 | "Choices": [ 144 | "\u0026DisableDiagTrack", 145 | "\u0026EnableDiagTrack" 146 | ] 147 | }, 148 | { 149 | "Group": "Privacy", 150 | "Description": "Disable or enable WAP push service", 151 | "Name": "WAPPush", 152 | "Choices": [ 153 | "\u0026DisableWAPPush", 154 | "\u0026EnableWAPPush" 155 | ] 156 | }, 157 | { 158 | "Group": "Security", 159 | "Description": "Set the UAC level", 160 | "Name": "UACLevel", 161 | "Choices": [ 162 | "\u0026Skip", 163 | "SetUAC\u0026Low", 164 | "SetUAC\u0026High" 165 | ] 166 | }, 167 | { 168 | "Group": "Security", 169 | "Description": "Disable or enable sharing of mapped drives", 170 | "Name": "SharingMappedDrives", 171 | "Choices": [ 172 | "\u0026Skip", 173 | "\u0026DisableSharingMappedDrives", 174 | "\u0026EnableSharingMappedDrives" 175 | ] 176 | }, 177 | { 178 | "Group": "Security", 179 | "Description": "Disable or enable admin shares", 180 | "Name": "AdminShares", 181 | "Choices": [ 182 | "\u0026DisableAdminShares", 183 | "\u0026EnableAdminShares" 184 | ] 185 | }, 186 | { 187 | "Group": "Security", 188 | "Description": "Disable or enable SMB1 protocol", 189 | "Name": "SMB1", 190 | "Choices": [ 191 | "\u0026DisableSMB1", 192 | "\u0026EnableSMB1" 193 | ] 194 | }, 195 | { 196 | "Group": "Security", 197 | "Description": "Set the current network zone as public or private", 198 | "Name": "CurrentNetworkZone", 199 | "Choices": [ 200 | "\u0026Skip", 201 | "SetCurrentNetworkP\u0026rivate", 202 | "SetCurrentNetworkP\u0026ublic" 203 | ] 204 | }, 205 | { 206 | "Group": "Security", 207 | "Description": "Set unknown network zone as public or private", 208 | "Name": "UnknownNetworkZone", 209 | "Choices": [ 210 | "\u0026Skip", 211 | "SetUnknownNetworkP\u0026rivate", 212 | "SetUnknownNetworkP\u0026ublic" 213 | ] 214 | }, 215 | { 216 | "Group": "Security", 217 | "Description": "Disable or enable unknown network device auto-installation", 218 | "Name": "NetDevicesAutoInst", 219 | "Choices": [ 220 | "\u0026DisableNetDevicesAutoInst", 221 | "\u0026EnableNetDevicesAutoInst" 222 | ] 223 | }, 224 | { 225 | "Group": "Security", 226 | "Description": "Disable or enable controlled folder access (WARNING: Enabling can cause issues with Powershell profile path access!)", 227 | "Name": "ControlledFolderAccess", 228 | "Choices": [ 229 | "\u0026Skip", 230 | "\u0026EnableCtrldFolderAccess", 231 | "\u0026DisableCtrldFolderAccess" 232 | ] 233 | }, 234 | { 235 | "Group": "Security", 236 | "Description": "Disable or enable firewall service", 237 | "Name": "Firewall", 238 | "Choices": [ 239 | "\u0026Skip", 240 | "\u0026DisableFirewall", 241 | "\u0026EnableFirewall" 242 | ] 243 | }, 244 | { 245 | "Group": "Security", 246 | "Description": "Disable or enable defender service", 247 | "Name": "Defender", 248 | "Choices": [ 249 | "\u0026Skip", 250 | "\u0026DisableDefender", 251 | "\u0026EnableDefender" 252 | ] 253 | }, 254 | { 255 | "Group": "Security", 256 | "Description": "Disable or enable defender cloud service", 257 | "Name": "DefenderCloud", 258 | "Choices": [ 259 | "\u0026Skip", 260 | "\u0026DisableDefenderCloud", 261 | "\u0026EnableDefenderCloud" 262 | ] 263 | }, 264 | { 265 | "Group": "Security", 266 | "Description": "Disable or enable Malicious Software Removal Tool offering", 267 | "Name": "UpdateMSRT", 268 | "Choices": [ 269 | "\u0026Skip", 270 | "\u0026DisableUpdateMSRT", 271 | "\u0026EnableUpdateMSRT" 272 | ] 273 | }, 274 | { 275 | "Group": "Security", 276 | "Description": "Disable or enable updating of drivers", 277 | "Name": "UpdateDriver", 278 | "Choices": [ 279 | "\u0026Skip", 280 | "\u0026DisableUpdateDriver", 281 | "\u0026EnableUpdateDriver" 282 | ] 283 | }, 284 | { 285 | "Group": "Security", 286 | "Description": "Disable or enable automatic update and restart", 287 | "Name": "UpdateRestart", 288 | "Choices": [ 289 | "\u0026DisableUpdateRestart", 290 | "\u0026EnableUpdateRestart" 291 | ] 292 | }, 293 | { 294 | "Group": "Security", 295 | "Description": "Disable or enable prompt to schedule update and restart", 296 | "Name": "UpdateScheduleRestart", 297 | "Choices": [ 298 | "\u0026EnableUpdateScheduleRestart", 299 | "\u0026DisableUpdateScheduleRestart" 300 | ] 301 | }, 302 | { 303 | "Group": "Service - Other", 304 | "Description": "Disable or enable HomeGroup service", 305 | "Name": "HomeGroups", 306 | "Choices": [ 307 | "\u0026DisableHomeGroups", 308 | "\u0026EnableHomeGroups" 309 | ] 310 | }, 311 | { 312 | "Group": "Service - Other", 313 | "Description": "Disable or enable shared experiences", 314 | "Name": "SharedExperiences", 315 | "Choices": [ 316 | "\u0026DisableSharedExperiences", 317 | "\u0026EnableSharedExperiences" 318 | ] 319 | }, 320 | { 321 | "Group": "Security", 322 | "Description": "Disable or enable remote assistance service", 323 | "Name": "RemoteAssistance", 324 | "Choices": [ 325 | "\u0026DisableRemoteAssistance", 326 | "\u0026EnableRemoteAssistance" 327 | ] 328 | }, 329 | { 330 | "Group": "Security", 331 | "Description": "Disable or enable remote desktop service", 332 | "Name": "RemoteDesktop", 333 | "Choices": [ 334 | "\u0026DisableRemoteDesktop", 335 | "\u0026EnableRemoteDesktop" 336 | ] 337 | }, 338 | { 339 | "Group": "Security", 340 | "Description": "Disable or enable autoplay", 341 | "Name": "Autoplay", 342 | "Choices": [ 343 | "\u0026DisableAutoplay", 344 | "\u0026EnableAutoplay" 345 | ] 346 | }, 347 | { 348 | "Group": "Security", 349 | "Description": "Disable or enable autorun for all drives", 350 | "Name": "Autorun", 351 | "Choices": [ 352 | "\u0026DisableAutorun", 353 | "\u0026EnableAutorun" 354 | ] 355 | }, 356 | { 357 | "Group": "Service - Other", 358 | "Description": "Disable or enable storage sense service", 359 | "Name": "StorageSense", 360 | "Choices": [ 361 | "\u0026Skip", 362 | "\u0026DisableStorageSense", 363 | "\u0026EnableStorageSense" 364 | ] 365 | }, 366 | { 367 | "Group": "Service - Other", 368 | "Description": "Disable or enable defragmentation service", 369 | "Name": "Defragmentation", 370 | "Choices": [ 371 | "\u0026Skip", 372 | "\u0026DisableDefragmentation", 373 | "\u0026EnableDefragmentation" 374 | ] 375 | }, 376 | { 377 | "Group": "Service - Other", 378 | "Description": "Disable or enable superfetch service", 379 | "Name": "Superfetch", 380 | "Choices": [ 381 | "\u0026Skip", 382 | "\u0026DisableSuperfetch", 383 | "\u0026EnableSuperfetch" 384 | ] 385 | }, 386 | { 387 | "Group": "Service - Other", 388 | "Description": "Disable or enable indexing service", 389 | "Name": "Indexing", 390 | "Choices": [ 391 | "\u0026Skip", 392 | "\u0026DisableIndexing", 393 | "\u0026EnableIndexing" 394 | ] 395 | }, 396 | { 397 | "Group": "Service - Other", 398 | "Description": "Set BIOS time setting", 399 | "Name": "BIOSTime", 400 | "Choices": [ 401 | "\u0026Skip", 402 | "SetBIOSTime\u0026UTC", 403 | "SetBIOSTime\u0026Local" 404 | ] 405 | }, 406 | { 407 | "Group": "Service - Power", 408 | "Description": "Disable or enable hibernation", 409 | "Name": "Hibernation", 410 | "Choices": [ 411 | "\u0026Skip", 412 | "\u0026DisableHibernation", 413 | "\u0026EnableHibernation" 414 | ] 415 | }, 416 | { 417 | "Group": "Service - Power", 418 | "Description": "Disable or enable sleep button", 419 | "Name": "SleepButton", 420 | "Choices": [ 421 | "\u0026Skip", 422 | "\u0026DisableSleepButton", 423 | "\u0026EnableSleepButton" 424 | ] 425 | }, 426 | { 427 | "Group": "Service - Power", 428 | "Description": "Disable or enable sleep timeout", 429 | "Name": "SleepTimeout", 430 | "Choices": [ 431 | "\u0026Skip", 432 | "\u0026DisableSleepTimeout", 433 | "\u0026EnableSleepTimeout" 434 | ] 435 | }, 436 | { 437 | "Group": "Service - Power", 438 | "Description": "Disable or enable fast startup", 439 | "Name": "FastStartup", 440 | "Choices": [ 441 | "\u0026Skip", 442 | "\u0026DisableFastStartup", 443 | "\u0026EnableFastStartup" 444 | ] 445 | }, 446 | { 447 | "Group": "User Interface - Other", 448 | "Description": "Disable or enable action center", 449 | "Name": "ActionCenter", 450 | "Choices": [ 451 | "\u0026DisableActionCenter", 452 | "\u0026EnableActionCenter" 453 | ] 454 | }, 455 | { 456 | "Group": "User Interface - Lock Screen", 457 | "Description": "Disable or enable lock screen", 458 | "Name": "LockScreen", 459 | "Choices": [ 460 | "\u0026Skip", 461 | "\u0026DisableLockScreen", 462 | "\u0026EnableLockScreen" 463 | ] 464 | }, 465 | { 466 | "Group": "User Interface - Lock Screen", 467 | "Description": "Hide or show network from lock screen", 468 | "Name": "HideNetworkFromLockScreen", 469 | "Choices": [ 470 | "\u0026HideNetworkFromLockScreen", 471 | "Show\u0026NetworkOnLockScreen" 472 | ] 473 | }, 474 | { 475 | "Group": "User Interface - Lock Screen", 476 | "Description": "Hide or show shutdown from lock screen", 477 | "Name": "HideShutdownFromLockScreen", 478 | "Choices": [ 479 | "\u0026HideShutdownFromLockScreen", 480 | "S\u0026howShutdownOnLockScreen" 481 | ] 482 | }, 483 | { 484 | "Group": "User Interface - Other", 485 | "Description": "Disable or enable sticky keys", 486 | "Name": "StickyKeys", 487 | "Choices": [ 488 | "\u0026DisableStickyKeys", 489 | "\u0026EnableStickyKeys" 490 | ] 491 | }, 492 | { 493 | "Group": "User Interface - Other", 494 | "Description": "Hide or show task manager details", 495 | "Name": "TaskManagerDetails", 496 | "Choices": [ 497 | "Show\u0026TaskManagerDetails", 498 | "\u0026HideTaskManagerDetails" 499 | ] 500 | }, 501 | { 502 | "Group": "User Interface - Other", 503 | "Description": "Hide or show file operations details", 504 | "Name": "ShowFileOperationsDetails", 505 | "Choices": [ 506 | "Show\u0026FileOperationsDetails", 507 | "\u0026HideFileOperationsDetails" 508 | ] 509 | }, 510 | { 511 | "Group": "User Interface - Other", 512 | "Description": "Disable or enable confirm file deletion", 513 | "Name": "FileDeleteConfirm", 514 | "Choices": [ 515 | "\u0026Skip", 516 | "\u0026DisableFileDeleteConfirm", 517 | "\u0026EnableFileDeleteConfirm" 518 | ] 519 | }, 520 | { 521 | "Group": "User Interface - Taskbar", 522 | "Description": "Taskbar Search Box Visibility", 523 | "Name": "TaskbarSearchBox", 524 | "Choices": [ 525 | "\u0026HideTaskbarSearchBox", 526 | "Show\u0026TaskbarSearchBox" 527 | ] 528 | }, 529 | { 530 | "Group": "User Interface - Taskbar", 531 | "Description": "Show or hide task view", 532 | "Name": "TaskView", 533 | "Choices": [ 534 | "\u0026HideTaskView", 535 | "Show\u0026TaskView" 536 | ] 537 | }, 538 | { 539 | "Group": "User Interface - Taskbar", 540 | "Description": "Set Taskbar icon size", 541 | "Name": "TaskbarIcon", 542 | "Choices": [ 543 | "\u0026Skip", 544 | "ShowS\u0026mallTaskbarIcons", 545 | "Show\u0026LargeTaskbarIcons" 546 | ] 547 | }, 548 | { 549 | "Group": "User Interface - Taskbar", 550 | "Description": "Taskbar docking location", 551 | "Name": "TaskbarDocking", 552 | "Choices": [ 553 | "\u0026Skip", 554 | "DockTaskBar\u0026Left", 555 | "DockTaskBar\u0026Right", 556 | "DockTaskBar\u0026Top", 557 | "DockTaskBar\u0026Bottom" 558 | ] 559 | }, 560 | { 561 | "Group": "User Interface - Taskbar", 562 | "Description": "Hide or show taskbar titles", 563 | "Name": "TaskbarTitles", 564 | "Choices": [ 565 | "Show\u0026TaskbarTitles", 566 | "\u0026HideTaskbarTitles" 567 | ] 568 | }, 569 | { 570 | "Group": "User Interface - Taskbar", 571 | "Description": "Hide or show people icon in taskbar", 572 | "Name": "TaskbarPeopleIcon", 573 | "Choices": [ 574 | "\u0026HideTaskbarPeopleIcon", 575 | "Show\u0026TaskbarPeopleIcon" 576 | ] 577 | }, 578 | { 579 | "Group": "User Interface - Taskbar", 580 | "Description": "Hide or show Tray icon in taskbar", 581 | "Name": "TrayIcons", 582 | "Choices": [ 583 | "Show\u0026TrayIcons", 584 | "\u0026HideTrayIcons" 585 | ] 586 | }, 587 | { 588 | "Group": "User Interface - Taskbar", 589 | "Description": "Enable or disable taskbar autohiding", 590 | "Name": "TaskbarAutoHide", 591 | "Choices": [ 592 | "\u0026Skip", 593 | "\u0026EnableAutoHideTaskbar", 594 | "\u0026DisableAutoHideTaskbar" 595 | ] 596 | }, 597 | { 598 | "Group": "User Interface - Explorer", 599 | "Description": "Hide or show known extensions in Explorer", 600 | "Name": "KnownExtensions", 601 | "Choices": [ 602 | "Show\u0026KnownExtensions", 603 | "\u0026HideKnownExtensions" 604 | ] 605 | }, 606 | { 607 | "Group": "User Interface - Explorer", 608 | "Description": "Hide or show hidden files in Explorer", 609 | "Name": "HiddenFiles", 610 | "Choices": [ 611 | "Sh\u0026owHiddenFiles", 612 | "\u0026HideHiddenFiles" 613 | ] 614 | }, 615 | { 616 | "Group": "User Interface - System Tray", 617 | "Description": "Hide or show Sync notifications in system tray", 618 | "Name": "SyncNotifications", 619 | "Choices": [ 620 | "\u0026HideSyncNotifications", 621 | "ShowS\u0026yncNotifications" 622 | ] 623 | }, 624 | { 625 | "Group": "User Interface - Start Menu", 626 | "Description": "Hide or show Recent Shortcuts in start menu", 627 | "Name": "RecentShortcuts", 628 | "Choices": [ 629 | "\u0026HideRecentShortcuts", 630 | "Show\u0026RecentShortcuts" 631 | ] 632 | }, 633 | { 634 | "Group": "User Interface - Explorer", 635 | "Description": "Set default Explorer view to This PC or Quick Access", 636 | "Name": "ExplorerDefaultView", 637 | "Choices": [ 638 | "SetExplorer\u0026ThisPC", 639 | "SetExplorer\u0026QuickAccess" 640 | ] 641 | }, 642 | { 643 | "Group": "User Interface - Desktop", 644 | "Description": "Hide or show This PC on desktop", 645 | "Name": "ThisPCOnDesktop", 646 | "Choices": [ 647 | "Show\u0026ThisPCOnDesktop", 648 | "\u0026HideThisPCOnDesktop" 649 | ] 650 | }, 651 | { 652 | "Group": "User Interface - Desktop", 653 | "Description": "Hide or show User folder on desktop", 654 | "Name": "UserFolderOnDesktop", 655 | "Choices": [ 656 | "\u0026Skip", 657 | "Show\u0026UserFolderOnDesktop", 658 | "\u0026HideUserFolderOnDesktop" 659 | ] 660 | }, 661 | { 662 | "Group": "User Interface - This PC", 663 | "Description": "Hide or show Desktop icon on This PC", 664 | "Name": "HideDesktopFromThisPC", 665 | "Choices": [ 666 | "\u0026Skip", 667 | "\u0026HideDesktopFromThisPC", 668 | "Show\u0026DesktopInThisPC" 669 | ] 670 | }, 671 | { 672 | "Group": "User Interface - This PC", 673 | "Description": "Hide or show documents folder on This PC", 674 | "Name": "DocumentsFromThisPC", 675 | "Choices": [ 676 | "\u0026Skip", 677 | "H\u0026ideDocumentsFromThisPC", 678 | "S\u0026howDocumentsFromThisPC" 679 | ] 680 | }, 681 | { 682 | "Group": "User Interface - Explorer", 683 | "Description": "Hide or show Documents folder from Explorer", 684 | "Name": "DocumentsFromExplorer", 685 | "Choices": [ 686 | "H\u0026ideDocumentsFromExplorer", 687 | "Sh\u0026owDocumentsFromExplorer" 688 | ] 689 | }, 690 | { 691 | "Group": "User Interface - This PC", 692 | "Description": "Hid or show Downloads folder from This PC", 693 | "Name": "DownloadsFromThisPC", 694 | "Choices": [ 695 | "\u0026Skip", 696 | "\u0026HideDownloadsFromThisPC", 697 | "Sh\u0026owDownloadsFromThisPC" 698 | ] 699 | }, 700 | { 701 | "Group": "User Interface - Explorer", 702 | "Description": "Hide or show Downloads folder in Explorer", 703 | "Name": "DownloadsFolderInExplorer", 704 | "Choices": [ 705 | "\u0026Skip", 706 | "\u0026HideDownloadsFromExplorer", 707 | "Sh\u0026owDownloadsInExplorer" 708 | ] 709 | }, 710 | { 711 | "Group": "User Interface", 712 | "Description": "Hide or show Music folder in This PC", 713 | "Name": "MusicFolderInThisPC", 714 | "Choices": [ 715 | "\u0026Skip", 716 | "\u0026HideMusicFromThisPC", 717 | "Sh\u0026owMusicInThisPC" 718 | ] 719 | }, 720 | { 721 | "Group": "User Interface - Explorer", 722 | "Description": "Hide or show Music folder in Explorer", 723 | "Name": "MusicFolderInExplorer", 724 | "Choices": [ 725 | "\u0026Skip", 726 | "\u0026HideMusicFromExplorer", 727 | "Sh\u0026owMusicInExplorer" 728 | ] 729 | }, 730 | { 731 | "Group": "User Interface - This PC", 732 | "Description": "Hide or show Pictures folder in This PC", 733 | "Name": "PicturesFolderInThisPC", 734 | "Choices": [ 735 | "\u0026Skip", 736 | "\u0026HidePicturesFromThisPC", 737 | "Sh\u0026owPicturesInThisPC" 738 | ] 739 | }, 740 | { 741 | "Group": "User Interface - Explorer", 742 | "Description": "Hide or show Pictures folder in Explorer", 743 | "Name": "PicturesFolderInExplorer", 744 | "Choices": [ 745 | "\u0026Skip", 746 | "\u0026HidePicturesFromExplorer", 747 | "Sh\u0026owPicturesInExplorer" 748 | ] 749 | }, 750 | { 751 | "Group": "User Interface - This PC", 752 | "Description": "Hide or show Videos folder in This PC", 753 | "Name": "VideoFoldersThisPC", 754 | "Choices": [ 755 | "\u0026Skip", 756 | "\u0026HideVideosFromThisPC", 757 | "Sh\u0026owVideosInThisPC" 758 | ] 759 | }, 760 | { 761 | "Group": "User Interface - Explorer", 762 | "Description": "Hide or show Videos folder in Explorer", 763 | "Name": "VideosFolderInExplorer", 764 | "Choices": [ 765 | "\u0026Skip", 766 | "\u0026HideVideosFromExplorer", 767 | "Sh\u0026owVideosInExplorer" 768 | ] 769 | }, 770 | { 771 | "Group": "User Interface - This PC", 772 | "Description": "Hide or show 3D Objects folder in This PC", 773 | "Name": "3DObjectsThisPC", 774 | "Choices": [ 775 | "\u0026Hide3DObjectsFromThisPC", 776 | "Sh\u0026ow3DObjectsInThisPC" 777 | ] 778 | }, 779 | { 780 | "Group": "User Interface - Explorer", 781 | "Description": "Hide or show 3D Objects folder in Explorer", 782 | "Name": "3DObjectsExplorer", 783 | "Choices": [ 784 | "\u0026Hide3DObjectsFromExplorer", 785 | "Sh\u0026ow3DObjectsInExplorer" 786 | ] 787 | }, 788 | { 789 | "Group": "User Interface - Other", 790 | "Description": "Set control panel display as Icon or Category mode", 791 | "Name": "ControlPanelView", 792 | "Choices": [ 793 | "SetControlPanelView\u0026Icons", 794 | "SetControlPanelView\u0026Categories" 795 | ] 796 | }, 797 | { 798 | "Group": "User Interface - Other", 799 | "Description": "Set visual effects for fastest performance or best appearance", 800 | "Name": "FXType", 801 | "Choices": [ 802 | "SetVisualFX\u0026Performance", 803 | "SetVisualFX\u0026Appearance" 804 | ] 805 | }, 806 | { 807 | "Group": "User Interface - Other", 808 | "Description": "Disable or enable Thumbnail generation", 809 | "Name": "Thumbnails", 810 | "Choices": [ 811 | "\u0026Skip", 812 | "\u0026DisableThumbnails", 813 | "\u0026EnableThumbnails" 814 | ] 815 | }, 816 | { 817 | "Group": "User Interface - Other", 818 | "Description": "Disable or enable thumbnail database file creation", 819 | "Name": "ThumbnailDB", 820 | "Choices": [ 821 | "\u0026Skip", 822 | "\u0026DisableThumbsDB", 823 | "\u0026EnableThumbsDB" 824 | ] 825 | }, 826 | { 827 | "Group": "User Interface - System Tray", 828 | "Description": "Add or remove EN Keyboard icon in system tray", 829 | "Name": "ENKeyboard", 830 | "Choices": [ 831 | "\u0026Skip", 832 | "\u0026AddENKeyboard", 833 | "\u0026RemoveENKeyboard" 834 | ] 835 | }, 836 | { 837 | "Group": "User Interface - Other", 838 | "Description": "Disable or enable Numlock", 839 | "Name": "Numlock", 840 | "Choices": [ 841 | "\u0026Skip", 842 | "\u0026DisableNumlock", 843 | "\u0026EnableNumlock" 844 | ] 845 | }, 846 | { 847 | "Group": "Application", 848 | "Description": "Disable or enable OneDrive", 849 | "Name": "OneDriveService", 850 | "Choices": [ 851 | "\u0026Skip", 852 | "\u0026DisableOneDrive", 853 | "\u0026EnableOneDrive" 854 | ] 855 | }, 856 | { 857 | "Group": "Application", 858 | "Description": "Uninstall or install OneDrive", 859 | "Name": "OneDriveInstall", 860 | "Choices": [ 861 | "\u0026Skip", 862 | "\u0026UninstallOneDrive", 863 | "\u0026InstallOneDrive" 864 | ] 865 | }, 866 | { 867 | "Group": "Application", 868 | "Description": "Install or uninstall Microsoft default AppX packages", 869 | "Name": "MsftBloat", 870 | "Choices": [ 871 | "\u0026UninstallMsftBloat", 872 | "\u0026InstallMsftBloat" 873 | ] 874 | }, 875 | { 876 | "Group": "Application", 877 | "Description": "Uninstall or install third party default AppX packages.", 878 | "Name": "ThirdPartyBloat", 879 | "Choices": [ 880 | "\u0026UninstallThirdPartyBloat", 881 | "\u0026InstallThirdPartyBloat" 882 | ] 883 | }, 884 | { 885 | "Group": "Application", 886 | "Description": "Uninstall or install the windows store application", 887 | "Name": "WindowsStore", 888 | "Choices": [ 889 | "\u0026Skip", 890 | "\u0026UninstallWindowsStore", 891 | "\u0026InstallWindowsStore" 892 | ] 893 | }, 894 | { 895 | "Group": "Application", 896 | "Description": "Uninstall or install Xbox features", 897 | "Name": "XboxFeatures", 898 | "Choices": [ 899 | "\u0026DisableXboxFeatures", 900 | "\u0026EnableXboxFeatures" 901 | ] 902 | }, 903 | { 904 | "Group": "Application", 905 | "Description": "Disable or enable built-in Adobe Flash in IE and Edge", 906 | "Name": "AdobeFlash", 907 | "Choices": [ 908 | "\u0026DisableAdobeFlash", 909 | "\u0026EnableAdobeFlash" 910 | ] 911 | }, 912 | { 913 | "Group": "Application", 914 | "Description": "Uninstall or install media player", 915 | "Name": "MediaPlayer", 916 | "Choices": [ 917 | "\u0026Skip", 918 | "\u0026UninstallMediaPlayer", 919 | "\u0026InstallMediaPlayer" 920 | ] 921 | }, 922 | { 923 | "Group": "Application", 924 | "Description": "Uninstall or install work folder client", 925 | "Name": "WorkFolders", 926 | "Choices": [ 927 | "\u0026Skip", 928 | "\u0026UninstallWorkFolders", 929 | "\u0026InstallWorkFolders" 930 | ] 931 | }, 932 | { 933 | "Group": "Application", 934 | "Description": "Uninstall or install HyperV", 935 | "Name": "HyperV", 936 | "Choices": [ 937 | "\u0026Skip", 938 | "\u0026InstallHyperV", 939 | "\u0026UninstallHyperV" 940 | ] 941 | }, 942 | { 943 | "Group": "Application", 944 | "Description": "Set or unset Photo Viewer association", 945 | "Name": "PhotoViewerAssociation", 946 | "Choices": [ 947 | "Set\u0026PhotoViewerAssociation", 948 | "\u0026UnSetPhotoViewerAssociation" 949 | ] 950 | }, 951 | { 952 | "Group": "Application", 953 | "Description": "Add or remove Photo Viewer to 'Open with'", 954 | "Name": "PhotoViewerOpenWith", 955 | "Choices": [ 956 | "\u0026AddPhotoViewerOpenWith", 957 | "\u0026RemovePhotoViewerOpenWith" 958 | ] 959 | }, 960 | { 961 | "Group": "Application", 962 | "Description": "Disable or enable searching for app in store for unknown extensions", 963 | "Name": "SearchAppInStore", 964 | "Choices": [ 965 | "\u0026DisableSearchAppInStore", 966 | "\u0026EnableSearchAppInStore" 967 | ] 968 | }, 969 | { 970 | "Group": "Application", 971 | "Description": "Disable or enable 'How do you want to open this file?' prompt", 972 | "Name": "NewAppPrompt", 973 | "Choices": [ 974 | "\u0026Skip", 975 | "\u0026DisableNewAppPrompt", 976 | "\u0026EnableNewAppPrompt" 977 | ] 978 | }, 979 | { 980 | "Group": "Application", 981 | "Description": "Disable or enable F8 boot menu", 982 | "Name": "F8BootMenu", 983 | "Choices": [ 984 | "\u0026Skip", 985 | "\u0026DisableF8BootMenu", 986 | "\u0026EnableF8BootMenu" 987 | ] 988 | }, 989 | { 990 | "Group": "Application", 991 | "Description": "Set Data Execution Prevention (DEP) policy to Opt out or in", 992 | "Name": "DEP", 993 | "Choices": [ 994 | "\u0026Skip", 995 | "SetDEPOpt\u0026Out", 996 | "SetDEPOpt\u0026In" 997 | ] 998 | }, 999 | { 1000 | "Group": "Application", 1001 | "Description": "Disable or enable Meltdown (CVE-2017-5754) compatibility flag - Required for January 2018 and all subsequent Windows updates. This flag is normally automatically enabled by compatible antivirus software (such as Windows Defender). Use the tweak only if you have confirmed that your AV is compatible but unable to set the flag automatically or if you don\u0027t use any AV at all. See https://support.microsoft.com/en-us/help/4072699/january-3-2018-windows-security-updates-and-antivirus-software for details.", 1002 | "Name": "MeltdownCompatFlag", 1003 | "Choices": [ 1004 | "\u0026Skip", 1005 | "\u0026DisableMeltdownCompatFlag", 1006 | "\u0026EnableMeltdownCompatFlag" 1007 | ] 1008 | }, 1009 | { 1010 | "Group": "Server", 1011 | "Description": "Disable or enable Hide Server Manager On Login", 1012 | "Name": "HideServerManagerOnLogin", 1013 | "Choices": [ 1014 | "\u0026Skip", 1015 | "\u0026HideServerManagerOnLogin", 1016 | "Sh\u0026owServerManagerOnLogin" 1017 | ] 1018 | }, 1019 | { 1020 | "Group": "Server", 1021 | "Description": "Disable or enable Shutdown Tracker dialog box", 1022 | "Name": "ShutdownTracker", 1023 | "Choices": [ 1024 | "\u0026Skip", 1025 | "\u0026DisableShutdownTracker", 1026 | "\u0026EnableShutdownTracker" 1027 | ] 1028 | }, 1029 | { 1030 | "Group": "Server", 1031 | "Description": "Disable or enable Password Policy", 1032 | "Name": "PasswordPolicy", 1033 | "Choices": [ 1034 | "\u0026Skip", 1035 | "\u0026DisablePasswordPolicy", 1036 | "\u0026EnablePasswordPolicy" 1037 | ] 1038 | }, 1039 | { 1040 | "Group": "Server", 1041 | "Description": "Disable or enable Ctrl-Alt-Del Login", 1042 | "Name": "CtrlAltDelLogin", 1043 | "Choices": [ 1044 | "\u0026Skip", 1045 | "\u0026DisableCtrlAltDelLogin", 1046 | "\u0026EnableCtrlAltDelLogin" 1047 | ] 1048 | }, 1049 | { 1050 | "Group": "Server", 1051 | "Description": "Disable or enable IE Enhanced Security", 1052 | "Name": "IEEnhancedSecurity", 1053 | "Choices": [ 1054 | "\u0026Skip", 1055 | "\u0026DisableIEEnhancedSecurity", 1056 | "\u0026EnableIEEnhancedSecurity" 1057 | ] 1058 | }, 1059 | { 1060 | "Group": "Unpinning", 1061 | "Description": "Unpin start menu tiles (WARNING: One way operation!)", 1062 | "Name": "UnpinStartMenuTiles", 1063 | "Choices": [ 1064 | "\u0026Skip", 1065 | "\u0026UnpinStartMenuTiles" 1066 | ] 1067 | }, 1068 | { 1069 | "Group": "Unpinning", 1070 | "Description": "Unpin taskbar icons (WARNING: One way operation!)", 1071 | "Name": "UnpinTaskbarIcons", 1072 | "Choices": [ 1073 | "\u0026Skip", 1074 | "\u0026UnpinTaskbarIcons" 1075 | ] 1076 | }, 1077 | { 1078 | "Group": "Printers", 1079 | "Description": "Remove default printers (WARNING: One way operation!)", 1080 | "Name": "RemoveDefaultPrinters", 1081 | "Choices": [ 1082 | "\u0026Skip", 1083 | "\u0026RemoveDefaultPrinters" 1084 | ] 1085 | } 1086 | ] --------------------------------------------------------------------------------