-
-
Save QNimbus/83a86ee072d2b4dbfd13f2fe901796df to your computer and use it in GitHub Desktop.
This PowerShell script is designed to automate the setup and configuration of my Windows 11 environment. It streamlines the deployment process, ensuring a consistent and efficient setup.
Script: win11.ps1
- WinGet Installation: Installs Microsoft's package manager, WinGet, along with its dependencies, if not already installed.
- Bloatware Removal: Systematically removes a predefined list of bloatware applications to streamline the Windows 11 experience.
- Application Installation: Automates the installation of essential applications like Git, Visual Studio Code, Windows Terminal, and others via WinGet.
- Windows Features and Services Configuration: Enables crucial Windows features and configures various services for optimal performance and usability.
- Windows Subsystem for Linux (WSL2) Setup: Facilitates the setup of WSL2, including the installation of a preferred Linux distribution (Ubuntu-22.04).
- Windows Registry Tweaks: Applies a series of registry tweaks for system optimization and customization, such as disabling telemetry, web search in Start Menu, Edge HubSidebar, Windows 11 widgets, and automatic Maps updates. Additionally, sets the display format for date and time, and modifies taskbar search settings.
- Taskbar and Desktop Customization: Generates a taskbar layout and restores desktop icons, tailoring the user interface to enhance accessibility and ease of use.
- System Cleanup: Performs a system-wide cleanup to remove residual files in specific directories.
- Administrative Check: Ensures the script is executed with administrative privileges for proper functioning.
- PowerShell 5.1 or higher
- Internet connection for downloading necessary components
-
Execute bootstrap script:
PowerShell.exe -ExecutionPolicy Bypass { Invoke-RestMethod -Uri https://gist.githubusercontent.com/QNimbus/83a86ee072d2b4dbfd13f2fe901796df/raw/scripts---bootstrap.ps1 | Invoke-Expression }
[!INFO] You can create a desktop shortcut with the following target
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -NoProfile -Command "Invoke-RestMethod -Uri https://gist.githubusercontent.com/QNimbus/83a86ee072d2b4dbfd13f2fe901796df/raw/scripts---bootstrap_sandbox.ps1 | Invoke-Expression"
Important
Run this command in an elevated PowerShell terminal.
- Script Execution: The sandbox will automatically download and execute the deployment script upon launch, setting up the environment as per the script’s configuration.
Contributions to this script are welcome. Please submit pull requests with your proposed changes.
This script is released under the MIT License.
B. van Wetten
Last Updated: 2024-01-06
This PowerShell script is designed to automate the setup and configuration of a Windows 11 Sandbox environment. It streamlines the deployment process, ensuring a consistent and efficient setup.
Script: sandbox.ps1
- Scoop Installation: Automatically installs Scoop, a command-line installer for Windows, and configures its settings.
- Windows Registry Configuration: Executes various Windows registry hacks to customize the Windows environment.
- Desktop and Taskbar Customization: Sets up the desktop and taskbar layout, including creating shortcuts and modifying the taskbar layout.
- Downloading and Setting Wallpaper: Downloads and sets a random wallpaper from Unsplash if no wallpaper is found in the designated folder.
- Script Execution: Allows for the execution of additional install scripts (currently disabled by default).
- Windows 11 Sandbox enabled (
Enable-WindowsOptionalFeature -FeatureName "Containers-DisposableClientVM" -All -Online
) - PowerShell 5.1 or higher
- Internet connection for downloading necessary components
-
Create a Windows Sandbox Config File: Create a
.wsb
file (e.g.,%USERPROFILE%/Windows Sandbox config.wsb
) with the necessary configuration to set up the sandbox environment. This includes enabling vGPU, setting networking options, and specifying other features like audio and video input, printer redirection, clipboard redirection, and protected client mode.Example configuration - See: Windows Sandbox.wsb
<Configuration> <vGPU>Enable</vGPU> <Networking>Default</Networking> <AudioInput>Disable</AudioInput> <VideoInput>Disable</VideoInput> <PrinterRedirection>Disable</PrinterRedirection> <ClipboardRedirection>Default</ClipboardRedirection> <ProtectedClient>Enable</ProtectedClient> <MappedFolders> <MappedFolder> <HostFolder>C:\Users\bas\Downloads\.sandbox</HostFolder> <SandboxFolder>C:\Users\WDAGUtilityAccount\Downloads</SandboxFolder> <ReadOnly>False</ReadOnly> </MappedFolder> </MappedFolders> <LogonCommand> <Command>powershell -executionpolicy Unrestricted -Command "start powershell { -Command \"Set-ExecutionPolicy Unrestricted -Scope LocalMachine -Force; Invoke-WebRequest -UseBasicParsing -Uri 'https://gist.githubusercontent.com/QNimbus/83a86ee072d2b4dbfd13f2fe901796df/raw/scripts---bootstrap_sandbox.ps1' | Select-Object -ExpandProperty Content | Invoke-Expression \"}"</Command> </LogonCommand> </Configuration>
-
Run the Config File: Double-click on the
.wsb
file to start Windows Sandbox with the specified configuration. -
Script Execution: The sandbox will automatically download and execute the deployment script upon launch, setting up the environment as per the script’s configuration.
Important
Make sure the folder in <HostFolder />
exists and also ensure that the URLs and file paths in the .wsb
file are accurate and relevant to your setup.
Contributions to this script are welcome. Please submit pull requests with your proposed changes.
This script is released under the MIT License.
B. van Wetten
Last Updated: 2024-01-06
# Title: Bootstrap script of Windows 11 deployment script | |
# Author: B. van Wetten | |
# Last Update: 2024-01-06 | |
# | |
# Prerequisites: See: https://gist.github.com/QNimbus/83a86ee072d2b4dbfd13f2fe901796df#file-provisioning-md | |
# | |
# Download only: Invoke-WebRequest -Uri https://gist.githubusercontent.com/QNimbus/83a86ee072d2b4dbfd13f2fe901796df/raw/scripts---bootstrap.ps1 -OutFile $env:userprofile\Downloads\bootstrap.ps1 | |
# Usage: PowerShell.exe -ExecutionPolicy Bypass { Invoke-RestMethod -Uri https://gist.githubusercontent.com/QNimbus/83a86ee072d2b4dbfd13f2fe901796df/raw/scripts---bootstrap.ps1 | Invoke-Expression } | |
# Start of script | |
Set-StrictMode -Version 1.0 | |
Set-Variable -Name ProgressPreference -Value "SilentlyContinue" # Default is "Continue" | |
Set-Variable -Name ErrorActionPreference -Value "Stop" # Default is "Continue" | |
Write-Host "[Info] Starting bootstrap script" -ForegroundColor Yellow | |
# Download Powershell scripts from GitHub | |
[hashtable[]] $PowerShellScripts = @( | |
@{ destination = "$env:USERPROFILE\Downloads\scripts\win11.ps1"; url ='https://gist.githubusercontent.com/QNimbus/83a86ee072d2b4dbfd13f2fe901796df/raw/scripts---win11.ps1'; } | |
@{ destination = "$env:USERPROFILE\Downloads\scripts\lib\utils.psm1"; url ='https://gist.githubusercontent.com/QNimbus/83a86ee072d2b4dbfd13f2fe901796df/raw/scripts---utils.psm1'; } | |
) | |
try { | |
# Clear the screen | |
Clear-Host | |
# Loop through the array of PowerShell scripts | |
ForEach ($PowerShellScript in $PowerShellScripts) { | |
# Get the directory of the PowerShell script | |
$PowerShellScriptDirectory = Split-Path -Path $PowerShellScript.destination -Parent | |
# Create the directory if it does not exist | |
If (-Not (Test-Path -Path $PowerShellScriptDirectory)) { | |
Write-Host "[Info] Creating directory $PowerShellScriptDirectory" -ForegroundColor Blue | |
New-Item -Path $PowerShellScriptDirectory -ItemType Directory -Force | |
} | |
# If the PowerShell script already exists, remove it | |
If (Test-Path -Path $PowerShellScript.destination) { | |
Write-Host "[Info] Removing existing file $($PowerShellScript.destination)" -ForegroundColor Blue | |
Remove-Item -Path $PowerShellScript.destination -Force | |
} | |
# Download the PowerShell script | |
Write-Host "[Info] Downloading $($PowerShellScript.url) to $($PowerShellScript.destination)" -ForegroundColor Blue | |
Invoke-WebRequest -Uri $PowerShellScript.url -OutFile $PowerShellScript.destination | |
} | |
# Execute the first PowerShell script in the foreground | |
Write-Host "[Info] Executing $($PowerShellScripts[0].destination)" -ForegroundColor Blue | |
Start-Process -FilePath "powershell.exe" -NoNewWindow -Wait -ArgumentList "-NoProfile -File `"$($PowerShellScripts[0].destination)`"" | |
} catch { | |
Write-Host "[Error] $($_.Exception.Message)" -ForegroundColor Red | |
Read-Host -Prompt "Press any key to continue..." | |
} |
# Title: Bootstrap script of Windows 11 Sandbox deployment script | |
# Author: B. van Wetten | |
# Last Update: 2024-01-10 | |
# | |
# Prerequisites: See: https://gist.github.com/QNimbus/83a86ee072d2b4dbfd13f2fe901796df#file-provisioning-sandbox-md | |
# | |
# Download only: Invoke-WebRequest -Uri https://gist.githubusercontent.com/QNimbus/83a86ee072d2b4dbfd13f2fe901796df/raw/scripts---bootstrap_sandbox.ps1 | |
# Usage: PowerShell.exe -ExecutionPolicy Bypass { Invoke-RestMethod -Uri https://gist.githubusercontent.com/QNimbus/83a86ee072d2b4dbfd13f2fe901796df/raw/scripts---bootstrap_sandbox.ps1 | Invoke-Expression } | |
# Start of script | |
Set-StrictMode -Version 1.0 | |
Set-Variable -Name ProgressPreference -Value 'SilentlyContinue' # Default is "Continue" | |
Set-Variable -Name ErrorActionPreference -Value 'SilentlyContinue' # Default is "Continue" | |
$global:SandboxVersion = '1.0.0' | |
$global:TempFolder = "$env:Temp" | |
$global:TempFolderRemote = 'C:\Users\WDAGUtilityAccount\AppData\Local\Temp' | |
$global:SandboxUserProfile = "$env:UserProfile" | |
$global:SandboxUserProfileRemote = 'C:\Users\WDAGUtilityAccount' | |
$global:SandboxPath = "$env:UserProfile\.sandbox" | |
$global:SandboxPathRemote = 'C:\Users\WDAGUtilityAccount\Desktop\Sandbox' | |
$global:SandboxScript = "$global:SandboxPath\.setup\sandbox.ps1" | |
$global:SandboxScriptRemote = "$global:SandboxPathRemote\.setup\sandbox.ps1" | |
$global:SandboxScriptsFolder = "$global:SandboxPath\.setup\scripts" | |
$global:SandboxScriptsFolderRemote = "$global:SandboxPathRemote\.setup\scripts" | |
$global:SandboxLibFolder = "$global:SandboxPath\.setup\scripts\lib" | |
$global:SandboxLibFolderRemote = "$global:SandboxPathRemote\.setup\scripts\lib" | |
$global:errorOccurred = $true | |
Write-Host '[Info] Starting bootstrap script' -ForegroundColor Yellow | |
try { | |
# Clear the screen | |
Clear-Host | |
# Check if Windows Sandbox is installed | |
try { | |
# Requires elevation: Get-WindowsOptionalFeature -Online -FeatureName Containers-DisposableClientVM -ErrorAction Stop | Out-Null | |
Get-Command -Name WindowsSandbox -ErrorAction Stop | Out-Null | |
Write-Host ('[OK] Windows Sandbox Feature is installed, continuing...') -ForegroundColor Green | |
} | |
catch { | |
Throw 'Windows Sandbox Feature is not installed, exiting...' | |
} | |
# Check if Sandbox is already running, exit if it is | |
if ((Get-Process -Name WindowsSandbox -ErrorAction SilentlyContinue).Length -gt 0) { | |
Write-Host ('[Info] Sandbox is already running, exiting...') -ForegroundColor DarkGray | |
# Ask if use wants to terminate running Sandbox | |
$choice = Read-Host -Prompt 'Terminate running Sandbox? [Y/N]' | |
if ($choice -eq 'Y') { | |
# Get sandbox process and kill it | |
$sandboxProcess = Get-Process -Name WindowsSandboxClient -ErrorAction SilentlyContinue | |
if ($sandboxProcess) { | |
Write-Host ('[Info] Killing Windows Sandbox process...') -ForegroundColor DarkGray | |
$sandboxProcess | Stop-Process -Force:$true -Confirm:$false | |
} | |
} | |
else { | |
Write-Host ('[Info] Exiting...') -ForegroundColor DarkGray | |
} | |
exit 0 | |
} | |
# Check if $global:SandboxPath exists | |
if (-not (Test-Path -Path $global:SandboxPath)) { | |
New-Item -ItemType Directory -Path $global:SandboxPath -Force | Out-Null | |
Write-Host ("[Info] Created $global:SandboxPath folder") -ForegroundColor DarkGray | |
} | |
# Create a $global:SandboxPath/.setup folder if it does not exist | |
if (-not (Test-Path -Path $global:SandboxPath\.setup)) { | |
New-Item -ItemType Directory -Path $global:SandboxPath\.setup -Force | Out-Null | |
Write-Host ("[Info] Created $global:SandboxPath\.setup folder") -ForegroundColor DarkGray | |
} | |
# Ensure other required folders exist | |
New-Item -ItemType Directory -Path "$global:SandboxPath\.scoop\" -Force | Out-Null | |
New-Item -ItemType Directory -Path "$global:SandboxPath\Downloads" -Force | Out-Null | |
New-Item -ItemType Directory -Path "$global:SandboxPath\installers\data" -Force | Out-Null | |
New-Item -ItemType Directory -Path "$global:SandboxPath\.setup\scripts\lib" -Force | Out-Null | |
# Remove previous sandbox_ip | |
if (Test-Path -Path "$global:SandboxPath\.setup\sandbox_ip") { | |
Write-Host ("[Info] Removing previous $global:SandboxPath\.setup\sandbox_ip file...") -ForegroundColor DarkGray | |
Remove-Item -Path "$global:SandboxPath\.setup\sandbox_ip" -Force | |
} | |
# Remove previous sandbox_hostname | |
if (Test-Path -Path "$global:SandboxPath\.setup\sandbox_hostname") { | |
Write-Host ("[Info] Removing previous $global:SandboxPath\.setup\sandbox_hostname file...") -ForegroundColor DarkGray | |
Remove-Item -Path "$global:SandboxPath\.setup\sandbox_hostname" -Force | |
} | |
# Create a temporary Sandbox.wsb file | |
$wsb = @" | |
<Configuration> | |
<vGPU>Enable</vGPU> | |
<Networking>Default</Networking> | |
<AudioInput>Disable</AudioInput> | |
<VideoInput>Disable</VideoInput> | |
<PrinterRedirection>Disable</PrinterRedirection> | |
<ClipboardRedirection>Default</ClipboardRedirection> | |
<ProtectedClient>Disable</ProtectedClient> | |
<MappedFolders> | |
<MappedFolder> | |
<HostFolder>$global:SandboxUserProfile\.ssh</HostFolder> | |
<SandboxFolder>$global:SandboxPathRemote\.setup\.ssh</SandboxFolder> | |
<ReadOnly>true</ReadOnly> | |
</MappedFolder> | |
<MappedFolder> | |
<HostFolder>$global:SandboxPath</HostFolder> | |
<SandboxFolder>$global:SandboxPathRemote</SandboxFolder> | |
<ReadOnly>False</ReadOnly> | |
</MappedFolder> | |
</MappedFolders> | |
<LogonCommand> | |
<Command>powershell.exe -NoProfile -ExecutionPolicy Unrestricted -File "$global:SandboxScriptRemote"</Command> | |
</LogonCommand> | |
</Configuration> | |
"@ | |
$wsb | Out-File "$global:TempFolder\Sandbox.wsb" -Force -Confirm:$false | |
# Create the sandbox.ps1 script | |
# Logging can be found in C:\Users\WDAGUtilityAccount\Desktop\Sandbox\.setup\sandbox_transcript | |
$sandbox = @" | |
# Start of script | |
param( | |
[switch]`$LogTranscript | |
) | |
Set-Variable -Name ProgressPreference -Value 'SilentlyContinue' # Default is "Continue" | |
Set-Variable -Name ErrorActionPreference -Value 'SilentlyContinue' # Default is "Continue" | |
`$scriptName = `$($MyInvocation.MyCommand.Name).Replace('.ps1', '') | |
`$transcriptFile = "$PSScriptRoot\`${scriptName}_transcript" | |
if (`$LogTranscript) { | |
Start-Transcript -Path `$transcriptFile | |
} | |
try { | |
# Modify local user account WDAGUtilityAccount with password "sandbox" | |
Write-Host ('[Info] Modifying local user account WDAGUtilityAccount with password "sandbox"...') -ForegroundColor DarkGray | |
Set-LocalUser -Name WDAGUtilityAccount -PasswordNeverExpires 1 -Password ("sandbox" | ConvertTo-SecureString -AsPlainText -Force) | |
# Check if 'install.ps1' already exists in $global:SandboxPathRemote\.scoop | |
if (-not (Test-Path -Path "$global:SandboxPathRemote\.scoop\install.ps1")) { | |
Write-Host ('[Info] Downloading Scoop install.ps1 script...') -ForegroundColor DarkGray | |
Invoke-RestMethod -Uri "https://get.scoop.sh" | Out-File -FilePath "$global:SandboxPathRemote\.scoop\install.ps1" -Force | |
} | |
Write-Host ('[Info] Installing Scoop...') -ForegroundColor DarkGray | |
"$global:SandboxPathRemote\.scoop\install.ps1" | Invoke-Expression | |
Write-Host ('[Info] Configuring Scoop...') -ForegroundColor DarkGray | |
scoop config cache_path "$global:SandboxPathRemote\.scoop" | |
scoop config aria2-warning-enabled false | |
Write-Host ('[Info] Installing Scoop packages...') -ForegroundColor DarkGray | |
# scoop config use_lessmsi `$true | |
# scoop install lessmsi | |
scoop install 7zip aria2 git pwsh | |
Write-Host ('[Info] Applying Scoop registry settings...') -ForegroundColor DarkGray | |
reg import "$global:SandboxUserProfileRemote\scoop\apps\git\current\install-context.reg" *> `$null | |
reg import "$global:SandboxUserProfileRemote\scoop\apps\7zip\current\install-context.reg" *> `$null | |
reg import "$global:SandboxUserProfileRemote\scoop\apps\git\current\install-file-associations.reg" *> `$null | |
# Set ExecutionPolicy to Unrestricted | |
Write-Host ('[Info] Setting ExecutionPolicy to Unrestricted...') -ForegroundColor DarkGray | |
powershell -Command "Set-ExecutionPolicy -ExecutionPolicy Unrestricted -Scope LocalMachine -Force" | |
pwsh -Command "Set-ExecutionPolicy -ExecutionPolicy Unrestricted -Scope LocalMachine -Force" | |
# Set network category to Private | |
Write-Host ("[Info] Setting interface '`$(Get-NetConnectionProfile).InterfaceAlias' - NetworkCategory to Public...") -ForegroundColor DarkGray | |
Set-NetConnectionProfile -InterfaceAlias `$(Get-NetConnectionProfile).InterfaceAlias -NetworkCategory "Public" | Out-Null | |
# Enable PowerShell remoting | |
Write-Host ('[Info] Enabling PowerShell remoting...') -ForegroundColor DarkGray | |
Enable-PSRemoting -SkipNetworkProfileCheck -Force | Out-Null | |
# Download Powershell scripts from GitHub | |
[hashtable[]] `$PowerShellScripts = @( | |
@{ destination = "$global:SandboxPathRemote\.setup\scripts\sandbox_configure.ps1"; url ='https://gist.githubusercontent.com/QNimbus/83a86ee072d2b4dbfd13f2fe901796df/raw/scripts---sandbox_configure.ps1'; } | |
@{ destination = "$global:SandboxPathRemote\.setup\scripts\ps-aliases.ps1"; url ='https://gist.githubusercontent.com/QNimbus/83a86ee072d2b4dbfd13f2fe901796df/raw/scripts---ps-aliases.ps1'; } | |
@{ destination = "$global:SandboxPathRemote\.setup\scripts\lib\utils.psm1"; url ='https://gist.githubusercontent.com/QNimbus/83a86ee072d2b4dbfd13f2fe901796df/raw/scripts---utils.psm1'; } | |
@{ destination = "$global:SandboxPathRemote\installers\data\vscode_user_data"; url ='https://gist.githubusercontent.com/QNimbus/83a86ee072d2b4dbfd13f2fe901796df/raw/scripts---vscode_user_data'; } | |
@{ destination = "$global:SandboxPathRemote\installers\Install development tools.ps1"; url ='https://gist.githubusercontent.com/QNimbus/83a86ee072d2b4dbfd13f2fe901796df/raw/scripts---sandbox-install-development-tools.ps1'; } | |
@{ destination = "$global:SandboxPathRemote\installers\Install Brave.ps1"; url ='https://gist.githubusercontent.com/QNimbus/83a86ee072d2b4dbfd13f2fe901796df/raw/scripts---sandbox-install-brave.ps1'; } | |
@{ destination = "$global:SandboxPathRemote\installers\Install Telegram.ps1"; url ='https://gist.githubusercontent.com/QNimbus/83a86ee072d2b4dbfd13f2fe901796df/raw/scripts---sandbox-install-telegram.ps1'; } | |
@{ destination = "$global:SandboxPathRemote\installers\Install Wireguard.ps1"; url ='https://gist.githubusercontent.com/QNimbus/83a86ee072d2b4dbfd13f2fe901796df/raw/scripts---sandbox-install-wireguard.ps1'; } | |
@{ destination = "$global:SandboxPathRemote\installers\Install BlueStacks.ps1"; url ='https://gist.githubusercontent.com/QNimbus/83a86ee072d2b4dbfd13f2fe901796df/raw/scripts---sandbox-install-bluestacks.ps1'; } | |
@{ destination = "$global:SandboxPathRemote\installers\Install Audacity.ps1"; url ='https://gist.githubusercontent.com/QNimbus/83a86ee072d2b4dbfd13f2fe901796df/raw/scripts---sandbox-install-audacity.ps1'; } | |
@{ destination = "$global:SandboxPathRemote\installers\Install Inkscape.ps1"; url ='https://gist.githubusercontent.com/QNimbus/83a86ee072d2b4dbfd13f2fe901796df/raw/scripts---sandbox-install-inkscape.ps1'; } | |
@{ destination = "$global:SandboxPathRemote\installers\Install Scratch 3.ps1"; url ='https://gist.githubusercontent.com/QNimbus/83a86ee072d2b4dbfd13f2fe901796df/raw/scripts---sandbox-install-scratch.ps1'; } | |
@{ destination = "$global:SandboxPathRemote\installers\Install Windows Terminal.ps1"; url ='https://gist.githubusercontent.com/QNimbus/83a86ee072d2b4dbfd13f2fe901796df/raw/scripts---sandbox-install-windows-terminal.ps1'; } | |
@{ destination = "$global:SandboxPathRemote\installers\Install Apps - Codux.ps1"; url ='https://gist.githubusercontent.com/QNimbus/83a86ee072d2b4dbfd13f2fe901796df/raw/scripts---sandbox-install-app-codux.ps1'; } | |
@{ destination = "$global:SandboxPathRemote\installers\Install Apps - LibreCAD.ps1"; url ='https://gist.githubusercontent.com/QNimbus/83a86ee072d2b4dbfd13f2fe901796df/raw/scripts---sandbox-install-app-librecad.ps1'; } | |
) | |
# Create symbolic link to Downloads folder | |
Write-Host ('[Info] Creating symbolic link to Downloads folder...') -ForegroundColor DarkGray | |
Remove-Item -Path "$global:SandboxUserProfileRemote\Downloads" -Force -Recurse -ErrorAction SilentlyContinue | |
New-Item -ItemType SymbolicLink -Path "$global:SandboxUserProfileRemote\Downloads" -Target "$global:SandboxPathRemote\Downloads" -Force | Out-Null | |
# Store current ip address of Sandbox in $global:SandboxPathRemote\.setup\sandbox_ip | |
Write-Host ('[Info] Storing current Sandbox IP address in $global:SandboxPathRemote\.setup\sandbox_ip...') -ForegroundColor DarkGray | |
`$ip = (Get-NetIPAddress -InterfaceAlias Ethernet -AddressFamily IPv4).IPAddress | |
`$ip | Out-File "$global:SandboxPathRemote\.setup\sandbox_ip" -Force | |
# Store current computer name of Sandbox in $global:SandboxPathRemote\.setup\sandbox_hostname | |
Write-Host ('[Info] Storing current Sandbox computer name in $global:SandboxPathRemote\.setup\sandbox_hostname...') -ForegroundColor DarkGray | |
[Net.Dns]::GetHostEntry("`$ip").HostName | Out-File "$global:SandboxPathRemote\.setup\sandbox_hostname" -Force | |
# `$env:ComputerName | Out-File "$global:SandboxPathRemote\.setup\sandbox_hostname" -Force | |
# Copy .ssh folder to C:\Users\WDAGUtilityAccount and create symbolic link | |
Write-Host ('[Info] Attempting to copy .ssh folder to $global:SandboxUserProfileRemote and creating symbolic link...') -ForegroundColor DarkGray | |
Copy-Item -Path "$global:SandboxPathRemote\.setup\.ssh" -Destination "$global:SandboxUserProfileRemote" -Recurse -Force -ErrorAction SilentlyContinue | |
# Create symbolic link to .gitconfig file | |
Write-Host ('[Info] Attemptint to create symbolic link in $global:SandboxUserProfileRemote to $global:SandboxPathRemote\.setup\.gitconfig file...') -ForegroundColor DarkGray | |
Copy-Item -Path "$global:SandboxPathRemote\.setup\.gitconfig" -Destination "$global:SandboxUserProfileRemote" -Force -ErrorAction SilentlyContinue | |
# Download PowerShell scripts from GitHub | |
Write-Host ('[Info] Downloading PowerShell scripts from GitHub...') -ForegroundColor DarkGray | |
`$PowerShellScripts | ForEach-Object { | |
# Download PowerShell scripts from GitHub | |
Invoke-WebRequest -Uri `$_.url -OutFile `$_.destination | |
# | |
# Only required when starting script with PowerShell 5.0 | |
# | |
# Fix a problem with Powershell 5.0 and UTF-8 without BOM | |
# See: https://stackoverflow.com/a/5596984/1654717 | |
# `$raw = Get-Content -Raw `$_.destination | |
# `$encoded = New-Object System.Text.UTF8Encoding `$False | |
# [IO.File]::WriteAllLines(`$_.destination, `$raw, `$encoded) | |
} | |
# <?xml version="1.0" encoding="utf-8"?> | |
# <LayoutModificationTemplate | |
# xmlns="http://schemas.microsoft.com/Start/2014/LayoutModification" | |
# xmlns:defaultlayout="http://schemas.microsoft.com/Start/2014/FullDefaultLayout" | |
# xmlns:start="http://schemas.microsoft.com/Start/2014/StartLayout" | |
# xmlns:taskbar="http://schemas.microsoft.com/Start/2014/TaskbarLayout" | |
# Version="1"> | |
# <CustomTaskbarLayoutCollection PinListPlacement="Replace"> | |
# <defaultlayout:TaskbarLayout> | |
# <taskbar:TaskbarPinList> | |
# <taskbar:DesktopApp DesktopApplicationID="Microsoft.Windows.Explorer" /> | |
# <taskbar:DesktopApp DesktopApplicationLinkPath="%PROGRAMDATA%\Microsoft\Windows\Start Menu\Programs\Microsoft Edge.lnk" /> | |
# </taskbar:TaskbarPinList> | |
# </defaultlayout:TaskbarLayout> | |
# </CustomTaskbarLayoutCollection> | |
# </LayoutModificationTemplate> | |
Write-Host '[Info] Creating taskbar layout' -ForegroundColor Blue | |
`$dataFolder = "`${env:UserProfile}\Desktop\Sandbox\installers\data" | |
`$taskbarLayoutModificationFileData = 'PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4NCjxMYXlvdXRNb2RpZmljYXRpb25UZW1wbGF0ZQ0KICAgIHhtbG5zPSJodHRwOi8vc2NoZW1hcy5taWNyb3NvZnQuY29tL1N0YXJ0LzIwMTQvTGF5b3V0TW9kaWZpY2F0aW9uIg0KICAgIHhtbG5zOmRlZmF1bHRsYXlvdXQ9Imh0dHA6Ly9zY2hlbWFzLm1pY3Jvc29mdC5jb20vU3RhcnQvMjAxNC9GdWxsRGVmYXVsdExheW91dCINCiAgICB4bWxuczpzdGFydD0iaHR0cDovL3NjaGVtYXMubWljcm9zb2Z0LmNvbS9TdGFydC8yMDE0L1N0YXJ0TGF5b3V0Ig0KICAgIHhtbG5zOnRhc2tiYXI9Imh0dHA6Ly9zY2hlbWFzLm1pY3Jvc29mdC5jb20vU3RhcnQvMjAxNC9UYXNrYmFyTGF5b3V0Ig0KICAgIFZlcnNpb249IjEiPg0KICA8Q3VzdG9tVGFza2JhckxheW91dENvbGxlY3Rpb24gUGluTGlzdFBsYWNlbWVudD0iUmVwbGFjZSI+DQogICAgPGRlZmF1bHRsYXlvdXQ6VGFza2JhckxheW91dD4NCiAgICAgIDx0YXNrYmFyOlRhc2tiYXJQaW5MaXN0Pg0KICAgICAgICA8dGFza2JhcjpEZXNrdG9wQXBwIERlc2t0b3BBcHBsaWNhdGlvbklEPSJNaWNyb3NvZnQuV2luZG93cy5FeHBsb3JlciIgLz4NCiAgICAgICAgPHRhc2tiYXI6RGVza3RvcEFwcCBEZXNrdG9wQXBwbGljYXRpb25MaW5rUGF0aD0iJVBST0dSQU1EQVRBJVxNaWNyb3NvZnRcV2luZG93c1xTdGFydCBNZW51XFByb2dyYW1zXE1pY3Jvc29mdCBFZGdlLmxuayIgLz4NCiAgICAgIDwvdGFza2JhcjpUYXNrYmFyUGluTGlzdD4NCiAgICA8L2RlZmF1bHRsYXlvdXQ6VGFza2JhckxheW91dD4NCiA8L0N1c3RvbVRhc2tiYXJMYXlvdXRDb2xsZWN0aW9uPg0KPC9MYXlvdXRNb2RpZmljYXRpb25UZW1wbGF0ZT4NCg==' | |
try { | |
`$taskbarLayoutModificationFile = "`$dataFolder\TaskbarLayoutModification.xml" | |
if (!(Test-Path `$dataFolder)) { | |
# Create directory | |
New-Item `$dataFolder -ItemType Directory -Force | Out-Null | |
} | |
Write-Host "[Info] Creating 'TaskbarLayoutModification.xml' file" -ForegroundColor Blue | |
try { | |
# Decode the base64 string | |
`$decodedBytes = [System.Convert]::FromBase64String(`$taskbarLayoutModificationFileData) | |
# Ensure the directory exists | |
`$directoryPath = [System.IO.Path]::GetDirectoryName(`$taskbarLayoutModificationFile) | |
if (-not (Test-Path `$directoryPath)) { | |
New-Item -Path `$directoryPath -ItemType Directory -Force | Out-Null | |
} | |
[System.IO.File]::WriteAllBytes(`$taskbarLayoutModificationFile, `$decodedBytes); | |
} | |
catch { | |
Write-Host "[Error] Failed to write file from base64 string. Error: `$_" -ForegroundColor Red | |
} | |
New-Item -Path "HKCU:\Software\Policies\Microsoft\Windows\Explorer" -Force > `$null | |
New-Item -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Group Policy Objects\{E0CC53D9-2FFF-4D2E-BECB-333B41615D7E}User\Software\Policies\Microsoft\Windows\Explorer" -Force > `$null | |
Set-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Group Policy Objects\{E0CC53D9-2FFF-4D2E-BECB-333B41615D7E}User\Software\Policies\Microsoft\Windows\Explorer" -Name "LockedStartLayout" -Value 1 -Type "DWord" | |
Set-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Group Policy Objects\{E0CC53D9-2FFF-4D2E-BECB-333B41615D7E}User\Software\Policies\Microsoft\Windows\Explorer" -Name "ReapplyStartLayoutEveryLogon" -Value 1 -Type "DWord" | |
Set-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Group Policy Objects\{E0CC53D9-2FFF-4D2E-BECB-333B41615D7E}User\Software\Policies\Microsoft\Windows\Explorer" -Name "StartLayoutFile" -Value "`$taskbarLayoutModificationFile" -Type "String" | |
Set-ItemProperty -Path "HKCU:\Software\Policies\Microsoft\Windows\Explorer" -Name "LockedStartLayout" -Value 1 -Type "DWord" | |
Set-ItemProperty -Path "HKCU:\Software\Policies\Microsoft\Windows\Explorer" -Name "ReapplyStartLayoutEveryLogon" -Value 1 -Type "DWord" | |
Set-ItemProperty -Path "HKCU:\Software\Policies\Microsoft\Windows\Explorer" -Name "StartLayoutFile" -Value "`$taskbarLayoutModificationFile" -Type "String" | |
} | |
catch { | |
Write-Host "[Error] Failed to set taskbar layout. Error: `$_" -ForegroundColor Red | |
} | |
Get-Process -Name Explorer | Stop-Process -Force | |
Start-Sleep -Seconds 3 | |
try { | |
`$p = Get-Process -Name Explorer -ErrorAction Stop | |
} | |
catch { | |
Try { | |
Start-Process explorer.exe | |
} | |
Catch { | |
# This should never be called | |
Throw `$_ | |
} | |
} | |
} catch { | |
Write-Host "[Error] `$(`$_.Exception.Message)" -ForegroundColor Red | |
exit 1 | |
} | |
# Execute PowerShell script | |
Write-Host ("[Info] Executing PowerShell script...") -ForegroundColor DarkGray | |
$global:SandboxUserProfileRemote\scoop\apps\pwsh\current\pwsh.exe -File "$global:SandboxPathRemote\.setup\scripts\sandbox_configure.ps1" -LogTranscript -Wait | |
Write-Host ('[Info] Done...') -ForegroundColor DarkGray | |
Stop-Transcript | |
"@ | |
$sandbox | Out-File -FilePath $global:SandboxScript -Force | |
$constants = @" | |
`$downloadFolder = (New-Object -ComObject Shell.Application).NameSpace('shell:Downloads').Self.Path | |
`$sandboxFolder = "`${env:UserProfile}\Desktop\Sandbox" | |
`$scoopFolder = "`$sandboxFolder\.scoop" | |
`$gistsFolder = "`$sandboxFolder\gists" | |
`$installersFolder = "`$sandboxFolder\installers" | |
`$dataFolder = "`$installersFolder\data" | |
Export-ModuleMember -Variable downloadFolder, sandboxFolder, scoopFolder, gistsFolder, installersFolder, dataFolder | |
"@ | |
$constants | Out-File -FilePath $global:SandboxLibFolder\constants.psm1 -Force | |
# Start Windows Sandbox using the Sandbox.wsb file | |
Write-Host ('[Info] Starting Windows Sandbox...') -ForegroundColor DarkGray | |
Start-Process -FilePath $(Get-Command -Name WindowsSandbox).Source -ArgumentList "$global:TempFolder\Sandbox.wsb" | Out-Null | |
# Wait for installation of OpenSSH server and creation of sandbox_ip file | |
$interval = 0 | |
while (-not (Test-Path -Path $global:SandboxPath\.setup\sandbox_ip)) { | |
Start-Sleep -Seconds 1 | |
# Perform modulo on $interval to check if it is a multiple of 5 | |
if (($interval++ % 15) -eq 0) { | |
Write-Host ("[Info] Waiting for creation of $global:SandboxPath\.setup\sandbox_ip file... ($interval seconds)") -ForegroundColor DarkGray | |
} | |
if ($interval -gt 90) { | |
Throw "Error creating $global:SandboxPath\.setup\sandbox_ip file, exiting..." | |
} | |
} | |
# Retrieve current ip address of Sandbox from $global:SandboxPath\.setup\sandbox_ip | |
$sandbox_ip = Get-Content $global:SandboxPath\.setup\sandbox_ip | |
# If ip address is not in the 10.0.0.0/8 range or the 172.16.0.0/12 range or the 192.168.0.0/16 range, exit | |
if (($sandbox_ip -notmatch '^10\.\d{1,3}\.\d{1,3}\.\d{1,3}$') -and ($sandbox_ip -notmatch '^172\.[1-3]\d\.\d{1,3}\.\d{1,3}$') -and ($sandbox_ip -notmatch '^192\.168\.\d{1,3}\.\d{1,3}$')) { | |
Throw 'Error retrieving Sandbox IP address, exiting...' | |
} | |
Write-Host ('[OK] Installation done...') -ForegroundColor Green | |
$global:errorOccurred = $false | |
} | |
catch { | |
Write-Host "[Error] $($_.Exception.Message)" -ForegroundColor Red | |
# Get sandbox process and kill it | |
$sandboxProcess = Get-Process -Name WindowsSandboxClient -ErrorAction SilentlyContinue | |
if ($sandboxProcess) { | |
Write-Host ('[Info] Killing Windows Sandbox process...') -ForegroundColor DarkGray | |
$sandboxProcess | Stop-Process -Force:$true -Confirm:$false | |
} | |
} | |
finally { | |
if ($global:errorOccurred) { | |
# Wait for keypress | |
Write-Host ('[Done] Press any key to exit...') -ForegroundColor Yellow | |
$null = $host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown') | |
exit 1 | |
} | |
else { | |
$timeout = 3 | |
# Wait for keypress or continue after 10 seconds | |
Write-Host ('[Done] Press any key to exit or wait 3 seconds...') -ForegroundColor Green | |
$timer = New-Object System.Diagnostics.Stopwatch | |
$timer.Start() | |
while (-not [Console]::KeyAvailable -and ($timeout -eq 0 -or $timer.Elapsed.Seconds -lt $timeout)) { | |
Start-Sleep -Milliseconds 50 | |
} | |
if ([Console]::KeyAvailable) { | |
[void][Console]::ReadKey($true) | |
} | |
exit 0 | |
} | |
} |
https://gist.githubusercontent.com/QNimbus/ff3ea6edad2d62a8f56d7029d62a118a/raw/.gitconfig%20(windows) | |
out=.gitconfig | |
https://gist.githubusercontent.com/QNimbus/e6e974f95217b109789f4b8f9730800b/raw/config%20(windows) | |
out=.ssh/config | |
https://gist.githubusercontent.com/QNimbus/41b14daabd04c6bd2f24c12c1a087904/raw/settings.sandbox.json | |
out=windows-terminal-settings.json |
<# | |
.SYNOPSIS | |
This script sets up a PowerShell profile for running scripts inside the Windows Sandbox VM. | |
.DESCRIPTION | |
The script sets up a PowerShell profile with aliases and functions for interacting with a 1Password account inside the Windows Sandbox VM. It checks if the script is running inside the Windows Sandbox VM, if the 1Password CLI is installed, and if the sandbox folder exists. It retrieves the IP address of the sandbox and adds it to the trusted hosts list if necessary. It then retrieves the 1Password account credentials and creates a PowerShell profile with aliases and a function for adding the 1Password account to the sandbox terminal session. | |
.PARAMETER VaultName | |
The name of the 1Password vault. Default is 'Private'. | |
.PARAMETER AccountName | |
The name of the 1Password account. Default is '1Password'. | |
.PARAMETER SandboxFolder | |
The path to the sandbox folder. Default is '$env:UserProfile\.sandbox'. | |
.PARAMETER Transcript | |
A switch parameter to enable transcript logging. Default is $false. | |
.EXAMPLE | |
.\ps-aliases.ps1 -VaultName 'Private' -AccountName '1Password' -SandboxFolder 'C:\Sandbox' -Transcript | |
This example sets up the PowerShell profile with the specified vault name, account name, sandbox folder, and enables transcript logging. | |
.NOTES | |
This script requires the 1Password CLI to be installed and the Windows Sandbox VM to be running. | |
#> | |
Param ( | |
[Parameter(Mandatory = $false)] | |
[Alias('vn')] | |
[string]$VaultName = 'Private', | |
[Parameter(Mandatory = $false)] | |
[Alias('an')] | |
[string]$AccountName = '1Password', | |
[Parameter(Mandatory = $false)] | |
[Alias('sf')] | |
[string]$SandboxFolder = "$env:UserProfile\.sandbox", | |
[Parameter(Mandatory = $false)] | |
[Alias('t')] | |
[Switch]$Transcript = $false | |
) | |
$scriptName = $($MyInvocation.MyCommand.Name).Replace('.ps1', '') | |
$transcriptFile = "$PSScriptRoot\${scriptName}_transcript" | |
if ($Transcript) { Start-Transcript -Path $transcriptFile } | |
Set-StrictMode -Version 1.0 | |
Set-Variable -Name ProgressPreference -Value 'SilentlyContinue' # Default is "Continue" | |
Set-Variable -Name ErrorActionPreference -Value 'SilentlyContinue' # Default is "Continue" | |
try { | |
# Check if we run inside the Windows Sandbox VM | |
if (-not (Get-Process -Name 'WindowsSandbox')) { throw 'Script is *not* intended to run inside the Windows Sandbox VM' } | |
if (-not (Get-Command -Name 'op' -ErrorAction SilentlyContinue)) { throw '1Password-CLI not installed' } | |
if (-not (Test-Path $SandboxFolder)) { throw "Sandbox folder '$SandboxFolder' not found" } | |
$ip = (Get-Content -Path ..\sandbox_ip -ErrorAction SilentlyContinue) | |
if (-not $ip) { throw 'Unable to retrieve sandbox IP address' } | |
# Check if the ip address is already in the trusted hosts list | |
$trustedHosts = Get-Item -Path WSMan:\localhost\Client\TrustedHosts -ErrorAction SilentlyContinue | |
if ($trustedHosts -and -not( $trustedHosts.Value -match $ip)) { | |
Write-Host("[Info] Adding sandbox IP address ($ip) to trusted hosts...") | |
Start-Process -FilePath powershell.exe -WindowStyle Hidden -Verb RunAs -Wait -ArgumentList "-Command Set-Item -Path WSMan:\localhost\Client\TrustedHosts -Value $ip -Force" | |
} | |
$sandboxUser = 'WDAGUtilityAccount' | |
$sandboxPassword = "sandbox" | ConvertTo-SecureString -AsPlainText -Force | |
[PSCredential] $credential = New-Object System.Management.Automation.PSCredential($sandboxUser, $sandboxPassword) | |
$session = New-PSSession -ComputerName $ip -Credential $credential | |
Write-Host('[Info] Retrieving 1Password account credentials...') | |
# Redirect stderr to null to suppress error messages | |
Write-Host("[Info] Retrieving 1Password sign-in address: op://$VaultName/$AccountName/website") | |
$opWebsite = ([Uri](op read "op://$VaultName/$AccountName/website" 2>$null)).Authority | |
Write-Host("[Info] Retrieving 1Password username: op://$VaultName/$AccountName/username") | |
$opSecretKey = op read "op://$VaultName/$AccountName/secret key" 2>$null | |
Write-Host("[Info] Retrieving 1Password secret key: op://$VaultName/$AccountName/secret key") | |
$opUsername = op read "op://$VaultName/$AccountName/username" 2>$null | |
if (-not $opWebsite -or -not $opUsername -or -not $opSecretKey) { throw 'Unable to retrieve website, username, or secret key from 1Password account' } | |
$script = @" | |
Clear-Host | |
Write-Host("[Notice] Adding 1Password utility scripts to PowerShell profile...`n") -ForegroundColor Yellow | |
# Display available aliases and usage info | |
Write-Host("[Info] Available aliases:") -ForegroundColor White | |
Write-Host("- op! : Log in to 1Password account") -ForegroundColor White | |
Write-Host("`n") | |
<# | |
.SYNOPSIS | |
This function adds an account using the 'op' command-line tool. | |
.DESCRIPTION | |
The 'opup' function attempts to add an account using the 'op' command-line tool. It provides the necessary parameters for signing in, including the shorthand, address, email, and secret key. | |
.PARAMETER None | |
.EXAMPLE | |
opup | |
#> | |
function 1Password-Up() { | |
try { | |
op account add --signin --shorthand sandbox --address '$opWebsite' --email '$opUsername' --secret-key '$opSecretKey' | Invoke-Expression | |
} catch { | |
Write-Host("[Error] $_") -ForegroundColor Red | |
} | |
} | |
Set-Alias -Name "op!" -Value "1Password-Up" -Description "Add 1Password account to sandbox terminal session" -Option AllScope | |
"@ | |
$script | Out-File -FilePath .\Profile.ps1 -Force | |
$userProfile = Invoke-Command -Session $session -ScriptBlock { $env:UserProfile } | |
Copy-Item .\Profile.ps1 -Destination "$userProfile\scoop\apps\pwsh\current\Profile.ps1" -ToSession $session -ErrorAction Stop | |
} | |
catch { | |
Write-Host "[Error] $_" -ForegroundColor Red | |
} | |
finally { | |
Remove-Item -Path .\Profile.ps1 -Force | |
if ($session) { Remove-PSSession -Session $session -ErrorAction SilentlyContinue } | |
if ($Transcript) { Stop-Transcript } | |
$timer = New-Object System.Diagnostics.Stopwatch | |
$timer.Start() | |
$timeout = 3 | |
Write-Host ('[Done] Press any key to exit or wait 3 seconds...') -ForegroundColor Green | |
while (-not [Console]::KeyAvailable -and ($timeout -eq 0 -or $timer.Elapsed.Seconds -lt $timeout)) { | |
Start-Sleep -Milliseconds 50 | |
} | |
if ([Console]::KeyAvailable) { | |
[void][Console]::ReadKey($true) | |
} | |
exit 0 | |
} |
# Title: Windows 11 Sandbox deployment script - Install Codux application | |
# Author: B. van Wetten | |
# Last Update: 2024-01-18 | |
# Start of script | |
Using module ..\.setup\scripts\lib\utils.psm1 | |
Using module ..\.setup\scripts\lib\constants.psm1 | |
param( | |
[switch]$LogTranscript | |
) | |
$scriptName = $($MyInvocation.MyCommand.Name).Replace('.ps1', '') | |
$transcriptFile = "$PSScriptRoot\${scriptName}_transcript" | |
if ($LogTranscript) { | |
Start-Transcript -Path $transcriptFile | |
} | |
Set-StrictMode -Version 1.0 | |
Set-Variable -Name ProgressPreference -Value 'SilentlyContinue' # Default is "Continue" | |
Set-Variable -Name ErrorActionPreference -Value 'SilentlyContinue' # Default is "Continue" | |
try { | |
# Download and install Codux application | |
$coduxUrl = 'https://github.com/wixplosives/codux-versions/releases/download/15.17.2/Codux-15.17.2.x64.exe' | |
$coduxFile = "$downloadFolder\Codux-15.17.2.x64.exe" | |
if (-not (Test-Path $coduxFile)) { | |
Write-Host '[Info] Downloading Codux application' -ForegroundColor Blue | |
Invoke-WebRequest -Uri $coduxUrl -OutFile $coduxFile | |
} | |
Write-Host '[Info] Installing Codux application' -ForegroundColor Blue | |
Start-Process -FilePath $coduxFile -ArgumentList '/S /AllUsers' | |
} | |
catch { | |
Write-Host "[Error] $_" -ForegroundColor Red | |
} |
# Title: Windows 11 Sandbox deployment script - Install LibreCAD application | |
# Author: B. van Wetten | |
# Last Update: 2024-01-30 | |
# Start of script | |
Using module ..\.setup\scripts\lib\utils.psm1 | |
Using module ..\.setup\scripts\lib\constants.psm1 | |
param( | |
[switch]$LogTranscript | |
) | |
$scriptName = $($MyInvocation.MyCommand.Name).Replace('.ps1', '') | |
$transcriptFile = "$PSScriptRoot\${scriptName}_transcript" | |
if ($LogTranscript) { | |
Start-Transcript -Path $transcriptFile | |
} | |
Set-StrictMode -Version 1.0 | |
Set-Variable -Name ProgressPreference -Value 'SilentlyContinue' # Default is "Continue" | |
Set-Variable -Name ErrorActionPreference -Value 'SilentlyContinue' # Default is "Continue" | |
try { | |
# Download and install LibreCAD application | |
$downloadUrl = 'https://github.com/LibreCAD/LibreCAD/releases/download/2.2.0.2/LibreCAD-Installer-2.2.0.2.exe' | |
$downloadFile = "$downloadFolder\LibreCAD-Installer-2.2.0.2.exe" | |
if (-not (Test-Path $downloadFile)) { | |
Write-Host '[Info] Downloading LibrCAD application' -ForegroundColor Blue | |
Invoke-WebRequest -Uri $downloadUrl -OutFile $downloadFile | |
} | |
Write-Host '[Info] Installing LibreCAD application' -ForegroundColor Blue | |
Start-Process -FilePath $downloadFile -ArgumentList '/S /AllUsers' | |
} | |
catch { | |
Write-Host "[Error] $_" -ForegroundColor Red | |
} |
# Title: Windows 11 Sandbox deployment script - Install Audacity | |
# Author: B. van Wetten | |
# Last Update: 2024-01-18 | |
# Start of script | |
Using module ..\.setup\scripts\lib\utils.psm1 | |
Using module ..\.setup\scripts\lib\constants.psm1 | |
param( | |
[switch]$LogTranscript | |
) | |
$scriptName = $($MyInvocation.MyCommand.Name).Replace('.ps1', '') | |
$transcriptFile = "$PSScriptRoot\${scriptName}_transcript" | |
if ($LogTranscript) { | |
Start-Transcript -Path $transcriptFile | |
} | |
Set-StrictMode -Version 1.0 | |
Set-Variable -Name ProgressPreference -Value 'SilentlyContinue' # Default is "Continue" | |
Set-Variable -Name ErrorActionPreference -Value 'SilentlyContinue' # Default is "Continue" | |
# Example usage | |
$filePath = 'Path\To\TaskbarLayoutModification.xml' | |
$appPath = '%APPDATA%\Microsoft\Windows\Start Menu\Programs\YourApp.lnk' | |
try { | |
# Check that 'scoop' is installed | |
if (-not (Get-Command -Name scoop)) { | |
throw 'Scoop is not installed' | |
} | |
$sources = @('extras') | |
$pkgs = @( | |
'audacity' | |
) | |
# Add sources and install packages | |
$sources | ForEach-Object { | |
Write-Host "[Scoop] Adding scoop bucket '$_'..." -ForegroundColor DarkGray | |
scoop bucket add $_ *> $null | |
} | |
$pkgs | ForEach-Object { | |
Write-Host "[Scoop] Installing scoop package '$_'..." -ForegroundColor DarkGray | |
scoop install $_ *> $null | |
} | |
Write-Host "[Info] Appending 'Audacity' shortcut to taskbar layout" -ForegroundColor Blue | |
$xmlFilePath = "$dataFolder\TaskbarLayoutModification.xml" | |
[Utils]::AddAppToTaskbarPinList($xmlFilePath, '%APPDATA%\Microsoft\Windows\Start Menu\Programs\Scoop Apps\Audacity.lnk') | |
[Utils]::RestartExplorer() | |
} | |
catch { | |
Write-Host "[Error] $_" -ForegroundColor Red | |
} |
# Title: Windows 11 Sandbox deployment script - Install BlueStacks | |
# Author: B. van Wetten | |
# Last Update: 2024-03-10 | |
# Start of script | |
Using module ..\.setup\scripts\lib\utils.psm1 | |
Using module ..\.setup\scripts\lib\constants.psm1 | |
param( | |
[switch]$LogTranscript | |
) | |
$scriptName = $($MyInvocation.MyCommand.Name).Replace('.ps1', '') | |
$transcriptFile = "$PSScriptRoot\${scriptName}_transcript" | |
if ($LogTranscript) { | |
Start-Transcript -Path $transcriptFile | |
} | |
Set-StrictMode -Version 1.0 | |
Set-Variable -Name ProgressPreference -Value 'SilentlyContinue' # Default is "Continue" | |
Set-Variable -Name ErrorActionPreference -Value 'SilentlyContinue' # Default is "Continue" | |
try { | |
# Check that 'scoop' is installed | |
if (-not (Get-Command -Name scoop)) { | |
throw 'Scoop is not installed' | |
} | |
$sources = @('nonportable') | |
$pkgs = @( | |
'bluestacks-np' | |
) | |
# Add sources and install packages | |
$sources | ForEach-Object { | |
Write-Host "[Scoop] Adding scoop bucket '$_'..." -ForegroundColor DarkGray | |
scoop bucket add $_ *> $null | |
} | |
$pkgs | ForEach-Object { | |
Write-Host "[Scoop] Installing scoop package '$_'..." -ForegroundColor DarkGray | |
scoop install $_ *> $null | |
} | |
Write-Host "[Info] Appending 'BlueStacks' shortcut to taskbar layout" -ForegroundColor Blue | |
$xmlFilePath = "$dataFolder\TaskbarLayoutModification.xml" | |
[Utils]::AddAppToTaskbarPinList($xmlFilePath, "%CSIDL_COMMON_PROGRAMS%\Microsoft\Windows\Start Menu\Programs\BlueStacks 5.lnk") | |
[Utils]::RestartExplorer() | |
} | |
catch { | |
Write-Host "[Error] $_" -ForegroundColor Red | |
} |
# Title: Windows 11 Sandbox deployment script - Install Brave | |
# Author: B. van Wetten | |
# Last Update: 2024-01-18 | |
# Start of script | |
Using module ..\.setup\scripts\lib\utils.psm1 | |
Using module ..\.setup\scripts\lib\constants.psm1 | |
param( | |
[switch]$LogTranscript | |
) | |
$scriptName = $($MyInvocation.MyCommand.Name).Replace('.ps1', '') | |
$transcriptFile = "$PSScriptRoot\${scriptName}_transcript" | |
if ($LogTranscript) { | |
Start-Transcript -Path $transcriptFile | |
} | |
Set-StrictMode -Version 1.0 | |
Set-Variable -Name ProgressPreference -Value 'SilentlyContinue' # Default is "Continue" | |
Set-Variable -Name ErrorActionPreference -Value 'SilentlyContinue' # Default is "Continue" | |
try { | |
# Check that 'scoop' is installed | |
if (-not (Get-Command -Name scoop)) { | |
throw 'Scoop is not installed' | |
} | |
$sources = @('extras') | |
$pkgs = @( | |
'brave' | |
) | |
# Add sources and install packages | |
$sources | ForEach-Object { | |
Write-Host "[Scoop] Adding scoop bucket '$_'..." -ForegroundColor DarkGray | |
scoop bucket add $_ *> $null | |
} | |
$pkgs | ForEach-Object { | |
Write-Host "[Scoop] Installing scoop package '$_'..." -ForegroundColor DarkGray | |
scoop install $_ *> $null | |
} | |
Write-Host "[Info] Appending 'Brave' shortcut to taskbar layout" -ForegroundColor Blue | |
$xmlFilePath = "$dataFolder\TaskbarLayoutModification.xml" | |
[Utils]::AddAppToTaskbarPinList($xmlFilePath, "%APPDATA%\Microsoft\Windows\Start Menu\Programs\Scoop Apps\Brave.lnk") | |
[Utils]::RestartExplorer() | |
} | |
catch { | |
Write-Host "[Error] $_" -ForegroundColor Red | |
} |
# Title: Windows 11 Sandbox deployment script - Install development tools | |
# Author: B. van Wetten | |
# Last Update: 2024-01-11 | |
# Start of script | |
Using module ..\.setup\scripts\lib\utils.psm1 | |
Using module ..\.setup\scripts\lib\constants.psm1 | |
param( | |
[switch]$LogTranscript | |
) | |
$scriptName = $($MyInvocation.MyCommand.Name).Replace('.ps1', '') | |
$transcriptFile = "$PSScriptRoot\${scriptName}_transcript" | |
if ($LogTranscript) { | |
Start-Transcript -Path $transcriptFile | |
} | |
Set-StrictMode -Version 1.0 | |
Set-Variable -Name ProgressPreference -Value 'SilentlyContinue' # Default is "Continue" | |
Set-Variable -Name ErrorActionPreference -Value 'SilentlyContinue' # Default is "Continue" | |
try { | |
# Check that 'scoop' is installed | |
if (-not (Get-Command -Name scoop)) { | |
throw 'Scoop is not installed' | |
} | |
$sources = @('extras') | |
$pkgs = @( | |
'vscode', | |
'vcredist2022', | |
'openssh', | |
'nodejs', | |
'python', | |
'jq', | |
'1password-cli' | |
) | |
# Add sources and install packages | |
$sources | ForEach-Object { | |
Write-Host "[Scoop] Adding scoop bucket '$_'..." -ForegroundColor DarkGray | |
scoop bucket add $_ *> $null | |
} | |
$pkgs | ForEach-Object { | |
Write-Host "[Scoop] Installing scoop package '$_'..." -ForegroundColor DarkGray | |
scoop install $_ *> $null | |
} | |
# VSCode post-installation | |
Write-Host '[Info] Installing VSCode registry modifications' -ForegroundColor Blue | |
reg import "${env:USERPROFILE}\scoop\apps\vscode\current\install-associations.reg" *> $null | |
reg import "${env:USERPROFILE}\scoop\apps\vscode\current\install-context.reg" *> $null | |
# Restore VSCode settings | |
# Archive was created with: | |
# `tar -cf - \ | |
# --exclude=settings.json \ | |
# --exclude=*.backup \ | |
# --exclude=data/user-data/User/snippets \ | |
# --exclude=data/user-data/User/History \ | |
# data/user-data/User | gzip -c | base64 > vscode_user_data` | |
Write-Host '[Info] Restoring VSCode settings' -ForegroundColor Blue | |
[Utils]::WriteArchive("$dataFolder\vscode_user_data", "${env:USERPROFILE}\scoop\apps\vscode\current") | |
# VSCode settings | |
# { | |
# "workbench.startupEditor": "none", | |
# "security.workspace.trust.enabled": false | |
# } | |
$vscodeSettings = 'ew0KCSJ3b3JrYmVuY2guc3RhcnR1cEVkaXRvciI6ICJub25lIiwNCgkic2VjdXJpdHkud29ya3NwYWNlLnRydXN0LmVuYWJsZWQiOiBmYWxzZQ0KfQ0K' | |
$vsCodeSettingsLocation = "${env:USERPROFILE}\scoop\apps\vscode\current\data\user-data\User" | |
$vsCodeSettingsFile = "$vsCodeSettingsLocation\settings.json" | |
# Create VSCode settings file | |
Write-Host '[Info] Creating VSCode settings file' -ForegroundColor Blue | |
New-Item $vsCodeSettingsLocation -ItemType Directory -Force | Out-Null | |
[Utils]::WriteFile($vscodeSettings, $vsCodeSettingsFile) | Out-Null | |
# OpenSSH post-installation | |
Write-Host '[Info] Running OpenSSH post-install scripts' -ForegroundColor Blue | |
Start-Process -FilePath powershell.exe -ArgumentList "-ExecutionPolicy Bypass -File ${env:USERPROFILE}\scoop\apps\openssh\current\install-sshd.ps1" -Wait | |
Start-Service sshd | |
# Python post-installation | |
Write-Host '[Info] Installing Python registry modifications' -ForegroundColor Blue | |
reg import "${env:USERPROFILE}\scoop\apps\python\current\install-pep-514.reg" *> $null | |
Write-Host "[Info] Appending 'VSCode' shortcut to taskbar layout" -ForegroundColor Blue | |
$xmlFilePath = "$dataFolder\TaskbarLayoutModification.xml" | |
[Utils]::AddAppToTaskbarPinList($xmlFilePath, "%APPDATA%\Microsoft\Windows\Start Menu\Programs\Scoop Apps\Visual Studio Code.lnk") | |
[Utils]::RestartExplorer() | |
} | |
catch { | |
Write-Host "[Error] $_" -ForegroundColor Red | |
} |
# Title: Windows 11 Sandbox deployment script - Install Inkscape | |
# Author: B. van Wetten | |
# Last Update: 2024-01-30 | |
# Start of script | |
Using module ..\.setup\scripts\lib\utils.psm1 | |
Using module ..\.setup\scripts\lib\constants.psm1 | |
param( | |
[switch]$LogTranscript | |
) | |
$scriptName = $($MyInvocation.MyCommand.Name).Replace('.ps1', '') | |
$transcriptFile = "$PSScriptRoot\${scriptName}_transcript" | |
if ($LogTranscript) { | |
Start-Transcript -Path $transcriptFile | |
} | |
Set-StrictMode -Version 1.0 | |
Set-Variable -Name ProgressPreference -Value 'SilentlyContinue' # Default is "Continue" | |
Set-Variable -Name ErrorActionPreference -Value 'SilentlyContinue' # Default is "Continue" | |
# Example usage | |
$filePath = 'Path\To\TaskbarLayoutModification.xml' | |
$appPath = '%APPDATA%\Microsoft\Windows\Start Menu\Programs\YourApp.lnk' | |
try { | |
# Check that 'scoop' is installed | |
if (-not (Get-Command -Name scoop)) { | |
throw 'Scoop is not installed' | |
} | |
$sources = @('extras') | |
$pkgs = @( | |
'inkscape' | |
) | |
# Add sources and install packages | |
$sources | ForEach-Object { | |
Write-Host "[Scoop] Adding scoop bucket '$_'..." -ForegroundColor DarkGray | |
scoop bucket add $_ *> $null | |
} | |
$pkgs | ForEach-Object { | |
Write-Host "[Scoop] Installing scoop package '$_'..." -ForegroundColor DarkGray | |
scoop install $_ *> $null | |
} | |
Write-Host "[Info] Appending 'Inkscape' shortcut to taskbar layout" -ForegroundColor Blue | |
$xmlFilePath = "$dataFolder\TaskbarLayoutModification.xml" | |
[Utils]::AddAppToTaskbarPinList($xmlFilePath, '%APPDATA%\Microsoft\Windows\Start Menu\Programs\Scoop Apps\Inkscape.lnk') | |
[Utils]::RestartExplorer() | |
} | |
catch { | |
Write-Host "[Error] $_" -ForegroundColor Red | |
} |
# Title: Windows 11 Sandbox deployment script - Install Scratch | |
# Author: B. van Wetten | |
# Last Update: 2024-01-20 | |
# Start of script | |
Using module ..\.setup\scripts\lib\utils.psm1 | |
Using module ..\.setup\scripts\lib\constants.psm1 | |
param( | |
[switch]$LogTranscript | |
) | |
$scriptName = $($MyInvocation.MyCommand.Name).Replace('.ps1', '') | |
$transcriptFile = "$PSScriptRoot\${scriptName}_transcript" | |
if ($LogTranscript) { | |
Start-Transcript -Path $transcriptFile | |
} | |
Set-StrictMode -Version 1.0 | |
Set-Variable -Name ProgressPreference -Value 'SilentlyContinue' # Default is "Continue" | |
Set-Variable -Name ErrorActionPreference -Value 'SilentlyContinue' # Default is "Continue" | |
try { | |
# Check that 'scoop' is installed | |
if (-not (Get-Command -Name scoop)) { | |
throw 'Scoop is not installed' | |
} | |
$sources = @('extras') | |
$pkgs = @( | |
'scratch' | |
) | |
# Add sources and install packages | |
$sources | ForEach-Object { | |
Write-Host "[Scoop] Adding scoop bucket '$_'..." -ForegroundColor DarkGray | |
scoop bucket add $_ *> $null | |
} | |
$pkgs | ForEach-Object { | |
Write-Host "[Scoop] Installing scoop package '$_'..." -ForegroundColor DarkGray | |
scoop install $_ *> $null | |
} | |
Write-Host "[Info] Appending 'Scratch' shortcut to taskbar layout" -ForegroundColor Blue | |
$xmlFilePath = "$dataFolder\TaskbarLayoutModification.xml" | |
[Utils]::AddAppToTaskbarPinList($xmlFilePath, "%APPDATA%\Microsoft\Windows\Start Menu\Programs\Scoop Apps\Scratch 3.lnk") | |
[Utils]::RestartExplorer() | |
} | |
catch { | |
Write-Host "[Error] $_" -ForegroundColor Red | |
} |
# Title: Windows 11 Sandbox deployment script - Install Telegram | |
# Author: B. van Wetten | |
# Last Update: 2024-02-04 | |
# Start of script | |
Using module ..\.setup\scripts\lib\utils.psm1 | |
Using module ..\.setup\scripts\lib\constants.psm1 | |
param( | |
[switch]$LogTranscript | |
) | |
$scriptName = $($MyInvocation.MyCommand.Name).Replace('.ps1', '') | |
$transcriptFile = "$PSScriptRoot\${scriptName}_transcript" | |
if ($LogTranscript) { | |
Start-Transcript -Path $transcriptFile | |
} | |
Set-StrictMode -Version 1.0 | |
Set-Variable -Name ProgressPreference -Value 'SilentlyContinue' # Default is "Continue" | |
Set-Variable -Name ErrorActionPreference -Value 'SilentlyContinue' # Default is "Continue" | |
try { | |
# Check that 'scoop' is installed | |
if (-not (Get-Command -Name scoop)) { | |
throw 'Scoop is not installed' | |
} | |
$sources = @('extras') | |
$pkgs = @( | |
'telegram' | |
) | |
# Add sources and install packages | |
$sources | ForEach-Object { | |
Write-Host "[Scoop] Adding scoop bucket '$_'..." -ForegroundColor DarkGray | |
scoop bucket add $_ *> $null | |
} | |
$pkgs | ForEach-Object { | |
Write-Host "[Scoop] Installing scoop package '$_'..." -ForegroundColor DarkGray | |
scoop install $_ *> $null | |
} | |
Write-Host "[Info] Appending 'Telegram' shortcut to taskbar layout" -ForegroundColor Blue | |
$xmlFilePath = "$dataFolder\TaskbarLayoutModification.xml" | |
[Utils]::AddAppToTaskbarPinList($xmlFilePath, "%APPDATA%\Microsoft\Windows\Start Menu\Programs\Scoop Apps\Telegram.lnk") | |
[Utils]::RestartExplorer() | |
} | |
catch { | |
Write-Host "[Error] $_" -ForegroundColor Red | |
} |
# Title: Windows 11 Sandbox deployment script - Install Windows Terminal | |
# Author: B. van Wetten | |
# Last Update: 2024-01-18 | |
# Start of script | |
Using module ..\.setup\scripts\lib\utils.psm1 | |
Using module ..\.setup\scripts\lib\constants.psm1 | |
param( | |
[switch]$LogTranscript | |
) | |
$scriptName = $($MyInvocation.MyCommand.Name).Replace('.ps1', '') | |
$transcriptFile = "$PSScriptRoot\${scriptName}_transcript" | |
if ($LogTranscript) { | |
Start-Transcript -Path $transcriptFile | |
} | |
Set-StrictMode -Version 1.0 | |
Set-Variable -Name ProgressPreference -Value 'SilentlyContinue' # Default is "Continue" | |
Set-Variable -Name ErrorActionPreference -Value 'SilentlyContinue' # Default is "Continue" | |
try { | |
# Check that 'scoop' is installed | |
if (-not (Get-Command -Name scoop)) { | |
throw 'Scoop is not installed' | |
} | |
$sources = @('extras') | |
$pkgs = @( | |
'windows-terminal' | |
) | |
# Add sources and install packages | |
$sources | ForEach-Object { | |
Write-Host "[Scoop] Adding scoop bucket '$_'..." -ForegroundColor DarkGray | |
scoop bucket add $_ *> $null | |
} | |
$pkgs | ForEach-Object { | |
Write-Host "[Scoop] Installing scoop package '$_'..." -ForegroundColor DarkGray | |
scoop install $_ *> $null | |
} | |
# Windows Terminal post-installation | |
Write-Host '[Info] Installing Windows Terminal registry modifications' -ForegroundColor Blue | |
Copy-Item "$gistsFolder\windows-terminal-settings.json" "${env:USERPROFILE}\scoop\apps\windows-terminal\current\settings\settings.json" -Force -ErrorAction SilentlyContinue | Out-Null | |
reg import "${env:USERPROFILE}\scoop\apps\windows-terminal\current\install-context.reg" *> $null | |
Write-Host "[Info] Appending 'Windows Terminal' shortcut to taskbar layout" -ForegroundColor Blue | |
$xmlFilePath = "$dataFolder\TaskbarLayoutModification.xml" | |
[Utils]::AddAppToTaskbarPinList($xmlFilePath, "%APPDATA%\Microsoft\Windows\Start Menu\Programs\Scoop Apps\Windows Terminal.lnk") | |
[Utils]::RestartExplorer() | |
} | |
catch { | |
Write-Host "[Error] $_" -ForegroundColor Red | |
} |
# Title: Windows 11 Sandbox deployment script - Install Wireguard | |
# Author: B. van Wetten | |
# Last Update: 2024-02-05 | |
# Start of script | |
Using module ..\.setup\scripts\lib\utils.psm1 | |
Using module ..\.setup\scripts\lib\constants.psm1 | |
param( | |
[switch]$LogTranscript | |
) | |
$scriptName = $($MyInvocation.MyCommand.Name).Replace('.ps1', '') | |
$transcriptFile = "$PSScriptRoot\${scriptName}_transcript" | |
if ($LogTranscript) { | |
Start-Transcript -Path $transcriptFile | |
} | |
Set-StrictMode -Version 1.0 | |
Set-Variable -Name ProgressPreference -Value 'SilentlyContinue' # Default is "Continue" | |
Set-Variable -Name ErrorActionPreference -Value 'SilentlyContinue' # Default is "Continue" | |
try { | |
# Check that 'scoop' is installed | |
if (-not (Get-Command -Name scoop)) { | |
throw 'Scoop is not installed' | |
} | |
$sources = @('nonportable') | |
$pkgs = @( | |
'wireguard-np' | |
) | |
# Add sources and install packages | |
$sources | ForEach-Object { | |
Write-Host "[Scoop] Adding scoop bucket '$_'..." -ForegroundColor DarkGray | |
scoop bucket add $_ *> $null | |
} | |
$pkgs | ForEach-Object { | |
Write-Host "[Scoop] Installing scoop package '$_'..." -ForegroundColor DarkGray | |
scoop install $_ *> $null | |
} | |
Write-Host "[Info] Appending 'Wireguard' shortcut to taskbar layout" -ForegroundColor Blue | |
$xmlFilePath = "$dataFolder\TaskbarLayoutModification.xml" | |
[Utils]::AddAppToTaskbarPinList($xmlFilePath, "%CSIDL_COMMON_PROGRAMS%\Microsoft\Windows\Start Menu\Programs\Wireguard.lnk") | |
[Utils]::RestartExplorer() | |
} | |
catch { | |
Write-Host "[Error] $_" -ForegroundColor Red | |
} |
# Title: Windows 11 Sandbox deployment script | |
# Author: B. van Wetten | |
# Description: Deployment script Windows Sandbox | |
# Last Update: 2024-01-18 | |
# Start of script | |
Using module .\lib\utils.psm1 | |
Using module .\lib\constants.psm1 | |
param( | |
[switch]$LogTranscript | |
) | |
$scriptName = $($MyInvocation.MyCommand.Name).Replace('.ps1', '') | |
$transcriptFile = "$PSScriptRoot\${scriptName}_transcript" | |
if ($LogTranscript) { | |
Start-Transcript -Path $transcriptFile | |
} | |
Set-StrictMode -Version 1.0 | |
Set-Variable -Name ProgressPreference -Value 'SilentlyContinue' # Default is "Continue" | |
Set-Variable -Name ErrorActionPreference -Value 'SilentlyContinue' # Default is "Continue" | |
$global:CreateTaskbarLayout = $true | |
$global:CreateDesktopShortcut = $true | |
$global:ExecuteInstallScripts = $false | |
try { | |
# Set current working directory to user's home directory | |
Set-Location $downloadFolder | |
# Ensure required folders exist | |
New-Item -Path $gistsFolder -ItemType Directory | Out-Null | |
$sources = @('extras') | |
$pkgs = @() | |
# Check if scoop is installed: | |
try { | |
$null = Get-Command -Name scoop -ErrorAction Stop | |
Write-Host '[Info] scoop.exe is already installed.' -ForegroundColor Blue | |
} | |
catch { | |
Write-Host '[Info] scoop.exe is not installed. Installing...' -ForegroundColor Blue | |
Invoke-RestMethod -Uri https://get.scoop.sh | Invoke-Expression | |
# Configure scoop | |
Write-Host '[Scoop] Configuring scoop' -ForegroundColor DarkGray | |
scoop config aria2-warning-enabled false *> $null | |
scoop config cache_path "$scoopFolder" *> $null | |
# Use lessmsi | |
Write-Host '[Scoop] Using lessmsi' -ForegroundColor DarkGray | |
scoop config use_lessmsi `$true *> $null | |
# Install scoop essentials | |
Write-Host '[Scoop] Installing scoop essentials' -ForegroundColor DarkGray | |
scoop install lessmsi 7zip aria2 git *> $null | |
Write-Host '[Info] Installing Scoop apps registry modifications' -ForegroundColor Blue | |
reg import "${env:UserProfile}\scoop\apps\7zip\current\install-context.reg" *> $null | |
} | |
try { | |
# Add sources and install packages | |
$sources | ForEach-Object { | |
Write-Host "[Scoop] Adding scoop bucket '$_'..." -ForegroundColor DarkGray | |
scoop bucket add $_ *> $null | |
} | |
$pkgs | ForEach-Object { | |
Write-Host "[Scoop] Installing scoop package '$_'..." -ForegroundColor DarkGray | |
scoop install $_ *> $null | |
} | |
} | |
catch { | |
Write-Host "[Scoop:Error] $_" -ForegroundColor Red | |
} | |
# Download gists from GitHub | |
try { | |
Write-Host '[Gist] Downloading gists from GitHub...' -ForegroundColor DarkGray | |
if (-not (Test-Path "$gistsFolder\gist_urls")) { | |
Invoke-RestMethod -Uri "https://gist.githubusercontent.com/QNimbus/83a86ee072d2b4dbfd13f2fe901796df/raw/scripts---gist_urls" | Out-File -FilePath "$gistsFolder\gist_urls" -Force | |
} | |
$arguments = @("--dir=$gistsFolder", "--input-file=$gistsFolder\gist_urls", '--quiet', '--allow-overwrite=false', '--auto-file-renaming=false', '--file-allocation=none') | |
Start-Process -FilePath 'aria2c' -NoNewWindow -Wait -ArgumentList $arguments | Out-Null | |
} | |
catch { | |
Write-Host "[Gist:Error] $_" -ForegroundColor Red | |
} | |
# Get first image from folder and set as wallpaper | |
$wallpaper = Get-ChildItem -Path "$sandboxFolder\*" -Include *.jpg, *.png | Sort-Object LastWriteTime -Descending | Select-Object -First 1 | |
if ($wallpaper) { | |
Write-Host "[Info] Setting wallpaper to '$($wallpaper.Name)'..." -ForegroundColor Blue | |
UpdateWallpaper("$($wallpaper.FullName)") | |
} | |
else { | |
Write-Host "[Warning] No wallpaper found in '$sandboxFolder', downloading random wallpaper from Unsplash..." -ForegroundColor Yellow | |
# $url = 'https://source.unsplash.com/random/1920x1080/?wallpaper,dark,abstract,bokeh' | |
# $wallpaper = "$sandboxFolder\wallpaper.jpg" | |
# [Utils]::DownloadFile($url, $sandboxFolder, 'wallpaper.jpg') | |
# UpdateWallpaper($wallpaper) | |
} | |
# Performing Windows Registry hacks | |
Write-Host '[Info] Configuring Windows registry...' -ForegroundColor Blue | |
if ( -Not [Registry]::ConfigureWindows() ) { | |
Write-Host '[Error] Failed to configure Windows registry...' -ForegroundColor Red | |
} | |
# Create desktop shortcut to scripts folder (enabled) | |
if ($global:CreateDesktopShortcut) { | |
Write-Host "[Info] Creating desktop shortcut 'Home' for '${env:UserProfile}'" -ForegroundColor Magenta | |
[Utils]::NewShortcut("${env:UserProfile}", "${env:UserProfile}\Desktop\Home.lnk") | |
} | |
# Create desktop shortcut to scripts folder (enabled) | |
if ($global:CreateDesktopShortcut) { | |
Write-Host "[Info] Creating desktop shortcut 'Install scripts' for '$scriptsFolder\installers'" -ForegroundColor Magenta | |
[Utils]::NewShortcut("$installersFolder", "${env:UserProfile}\Desktop\Install scripts.lnk") | |
} | |
# Create appropriate taskbar layout (enabled) | |
if ($global:CreateTaskbarLayout) { | |
# <?xml version="1.0" encoding="utf-8"?> | |
# <LayoutModificationTemplate | |
# xmlns="http://schemas.microsoft.com/Start/2014/LayoutModification" | |
# xmlns:defaultlayout="http://schemas.microsoft.com/Start/2014/FullDefaultLayout" | |
# xmlns:start="http://schemas.microsoft.com/Start/2014/StartLayout" | |
# xmlns:taskbar="http://schemas.microsoft.com/Start/2014/TaskbarLayout" | |
# Version="1"> | |
# <CustomTaskbarLayoutCollection PinListPlacement="Replace"> | |
# <defaultlayout:TaskbarLayout> | |
# <taskbar:TaskbarPinList> | |
# <taskbar:DesktopApp DesktopApplicationID="Microsoft.Windows.Explorer" /> | |
# <taskbar:DesktopApp DesktopApplicationLinkPath="%PROGRAMDATA%\Microsoft\Windows\Start Menu\Programs\Microsoft Edge.lnk" /> | |
# </taskbar:TaskbarPinList> | |
# </defaultlayout:TaskbarLayout> | |
# </CustomTaskbarLayoutCollection> | |
# </LayoutModificationTemplate> | |
Write-Host '[Info] Creating taskbar layout' -ForegroundColor Blue | |
$taskbarLayoutModificationFileData = 'PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4NCjxMYXlvdXRNb2RpZmljYXRpb25UZW1wbGF0ZQ0KICAgIHhtbG5zPSJodHRwOi8vc2NoZW1hcy5taWNyb3NvZnQuY29tL1N0YXJ0LzIwMTQvTGF5b3V0TW9kaWZpY2F0aW9uIg0KICAgIHhtbG5zOmRlZmF1bHRsYXlvdXQ9Imh0dHA6Ly9zY2hlbWFzLm1pY3Jvc29mdC5jb20vU3RhcnQvMjAxNC9GdWxsRGVmYXVsdExheW91dCINCiAgICB4bWxuczpzdGFydD0iaHR0cDovL3NjaGVtYXMubWljcm9zb2Z0LmNvbS9TdGFydC8yMDE0L1N0YXJ0TGF5b3V0Ig0KICAgIHhtbG5zOnRhc2tiYXI9Imh0dHA6Ly9zY2hlbWFzLm1pY3Jvc29mdC5jb20vU3RhcnQvMjAxNC9UYXNrYmFyTGF5b3V0Ig0KICAgIFZlcnNpb249IjEiPg0KICA8Q3VzdG9tVGFza2JhckxheW91dENvbGxlY3Rpb24gUGluTGlzdFBsYWNlbWVudD0iUmVwbGFjZSI+DQogICAgPGRlZmF1bHRsYXlvdXQ6VGFza2JhckxheW91dD4NCiAgICAgIDx0YXNrYmFyOlRhc2tiYXJQaW5MaXN0Pg0KICAgICAgICA8dGFza2JhcjpEZXNrdG9wQXBwIERlc2t0b3BBcHBsaWNhdGlvbklEPSJNaWNyb3NvZnQuV2luZG93cy5FeHBsb3JlciIgLz4NCiAgICAgICAgPHRhc2tiYXI6RGVza3RvcEFwcCBEZXNrdG9wQXBwbGljYXRpb25MaW5rUGF0aD0iJVBST0dSQU1EQVRBJVxNaWNyb3NvZnRcV2luZG93c1xTdGFydCBNZW51XFByb2dyYW1zXE1pY3Jvc29mdCBFZGdlLmxuayIgLz4NCiAgICAgIDwvdGFza2JhcjpUYXNrYmFyUGluTGlzdD4NCiAgICA8L2RlZmF1bHRsYXlvdXQ6VGFza2JhckxheW91dD4NCiA8L0N1c3RvbVRhc2tiYXJMYXlvdXRDb2xsZWN0aW9uPg0KPC9MYXlvdXRNb2RpZmljYXRpb25UZW1wbGF0ZT4NCg==' | |
[Utils]::SetTaskbarLayout($dataFolder, $taskbarLayoutModificationFileData) | |
} | |
[Utils]::RestartExplorer() | |
} | |
catch { | |
Write-Host "[Error] $_" -ForegroundColor Red | |
} | |
finally { | |
Stop-Transcript | |
} | |
class Taskbar { | |
static [hashtable[]] $registry = @( | |
) | |
static [hashtable[]] $pinnedItems = @( | |
) | |
static [void] RestorePinnedTaskbarIcons() { | |
<# | |
.SYNOPSIS | |
Restores pinned taskbar icons. | |
.DESCRIPTION | |
This function restores the pinned taskbar icons by removing the relevant registry keys and shortcut files. | |
.PARAMETER None | |
This function does not accept any parameters. | |
.EXAMPLE | |
RestorePinnedTaskbarIcons | |
This example demonstrates how to use the RestorePinnedTaskbarIcons function to restore the pinned taskbar icons. | |
#> | |
Write-Host '[Info] Restoring pinned taskbar icons...' -ForegroundColor Blue | |
Remove-Item -Path 'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Taskband' -Recurse -ErrorAction SilentlyContinue | |
Remove-Item "$env:AppData\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar\*.lnk" -ErrorAction SilentlyContinue | |
try { | |
[Taskbar]::RestoreFiles() | |
[Utils]::RestoreRegistry([Taskbar]::registry) | |
} | |
catch { | |
throw $_.Exception.Message | |
} | |
} | |
static [void] RestoreFiles() { | |
foreach ($pinnedItem in [Taskbar]::pinnedItems) { | |
$filePath = [Utils]::WriteFile($pinnedItem.data, $pinnedItem.path) | |
Write-Host "[OK] Created '$($pinnedItem.name)' link" -ForegroundColor Green | |
} | |
} | |
} | |
class DesktopIcons { | |
static [hashtable[]] $registry = @( | |
@{path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\HideDesktopIcons\NewStartPanel'; displayName = 'My Computer'; name = '{20D04FE0-3AEA-1069-A2D8-08002B30309D}'; propertyType = 'DWord'; data = 0 } | |
@{path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\HideDesktopIcons\NewStartPanel'; displayName = 'Recycle bin'; name = '{645FF040-5081-101B-9F08-00AA002F954E}'; propertyType = 'DWord'; data = 1 } | |
@{path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\HideDesktopIcons\NewStartPanel'; displayName = "User's Files"; name = '{59031A47-3F72-44A7-89C5-5595FE6B30EE}'; propertyType = 'DWord'; data = 1 } | |
@{path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\HideDesktopIcons\NewStartPanel'; displayName = 'OneDrive'; name = '{018D5C66-4533-4307-9B53-224DE2ED1FE6}'; propertyType = 'DWord'; data = 1 } | |
) | |
static [void] RestoreDesktopIcons() { | |
<# | |
.SYNOPSIS | |
Restores desktop icons by removing all shortcut files from the Public and User desktops and restoring the registry settings. | |
.DESCRIPTION | |
This function removes all shortcut files from the Public and User desktops and then calls the RestoreRegistry method of the Utils class to restore the registry settings for desktop icons. | |
.PARAMETER None | |
This function does not accept any parameters. | |
.EXAMPLE | |
RestoreDesktopIcons | |
This example demonstrates how to use the RestoreDesktopIcons function to restore desktop icons. | |
#> | |
Write-Host '[Info] Removing desktop icons...' -ForegroundColor Blue | |
Remove-Item "$env:Public\Desktop\*.lnk" -ErrorAction SilentlyContinue | |
Remove-Item "$env:UserProfile\Desktop\*.lnk" -ErrorAction SilentlyContinue | |
[Utils]::RestoreRegistry([DesktopIcons]::registry) | |
} | |
} | |
class OtherRegistrySettings { | |
static [hashtable[]] $registry = @( | |
@{path = 'HKCU:\Control Panel\International\Geo'; name = 'Nation'; propertyType = 'String'; data = '176' } | |
@{path = 'HKCU:\Control Panel\International\Geo'; name = 'Name'; propertyType = 'String'; data = 'NL' } | |
@{path = 'HKCU:\Control Panel\International'; name = 'Locale'; propertyType = 'String'; data = '00000413' } | |
@{path = 'HKCU:\Control Panel\International'; name = 'LocaleName'; propertyType = 'String'; data = 'nl-NL' } | |
@{path = 'HKCU:\Control Panel\International'; name = 's1159'; propertyType = 'String'; data = '' } | |
@{path = 'HKCU:\Control Panel\International'; name = 's2359'; propertyType = 'String'; data = '' } | |
@{path = 'HKCU:\Control Panel\International'; name = 'sCurrency'; propertyType = 'String'; data = '€' } | |
@{path = 'HKCU:\Control Panel\International'; name = 'sDate'; propertyType = 'String'; data = '-' } | |
@{path = 'HKCU:\Control Panel\International'; name = 'sDecimal'; propertyType = 'String'; data = ',' } | |
@{path = 'HKCU:\Control Panel\International'; name = 'sLanguage'; propertyType = 'String'; data = 'NLD' } | |
@{path = 'HKCU:\Control Panel\International'; name = 'sList'; propertyType = 'String'; data = ';' } | |
@{path = 'HKCU:\Control Panel\International'; name = 'sLongDate'; propertyType = 'String'; data = 'dddd d MMMM yyyy' } | |
@{path = 'HKCU:\Control Panel\International'; name = 'sMonDecimalSep'; propertyType = 'String'; data = ',' } | |
@{path = 'HKCU:\Control Panel\International'; name = 'sMonThousandSep'; propertyType = 'String'; data = '.' } | |
@{path = 'HKCU:\Control Panel\International'; name = 'sShortDate'; propertyType = 'String'; data = 'd-M-yyyy' } | |
@{path = 'HKCU:\Control Panel\International'; name = 'sThousand'; propertyType = 'String'; data = '.' } | |
@{path = 'HKCU:\Control Panel\International'; name = 'iCountry'; propertyType = 'String'; data = '31' } | |
@{path = 'HKCU:\Control Panel\International'; name = 'iCurrency'; propertyType = 'String'; data = '2' } | |
@{path = 'HKCU:\Control Panel\International'; name = 'iFirstWeekOfYear'; propertyType = 'String'; data = '2' } | |
@{path = 'HKCU:\Control Panel\International'; name = 'iNegCurr'; propertyType = 'String'; data = '12' } | |
@{path = 'HKCU:\Control Panel\International'; name = 'sShortTime'; propertyType = 'String'; data = 'HH:mm' } | |
@{path = 'HKCU:\Control Panel\International'; name = 'sTimeFormat'; propertyType = 'String'; data = 'HH:mm:ss' } | |
@{path = 'HKCU:\Control Panel\Desktop'; name = 'PaintDesktopVersion'; propertyType = 'DWord'; data = 1 } | |
@{path = 'HKCU:\Control Panel\Desktop'; name = 'DragFullWindows'; propertyType = 'DWord'; data = 0 } | |
@{path = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\Explorer'; name = 'NoRecycleFiles'; propertyType = 'DWord'; data = 1 } | |
@{path = 'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced'; name = 'LaunchTo'; propertyType = 'DWord'; data = 1 } | |
@{path = 'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced'; name = 'NavPaneShowAllFolders'; propertyType = 'DWord'; data = 0 } | |
@{path = 'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced'; name = 'HideFileExt'; propertyType = 'DWord'; data = 0 } | |
@{path = 'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced'; name = 'ListviewAlphaSelect'; propertyType = 'DWord'; data = 0 } | |
@{path = 'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced'; name = 'ListviewShadow'; propertyType = 'DWord'; data = 0 } | |
@{path = 'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced'; name = 'TaskbarAnimations'; propertyType = 'DWord'; data = 0 } | |
@{path = 'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced'; name = 'ShowTaskViewButton'; propertyType = 'DWord'; data = 0 } | |
@{path = 'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VisualEffects'; name = 'VisualFXSetting'; propertyType = 'DWord'; data = 3 } | |
@{path = 'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Themes\Personalize'; name = 'AppsUseLightTheme'; propertyType = 'DWord'; data = 0 } | |
@{path = 'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Themes\Personalize'; name = 'SystemUsesLightTheme'; propertyType = 'DWord'; data = 0 } | |
@{path = 'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Themes\Personalize'; name = 'ColorPrevalence'; propertyType = 'DWord'; data = 0 } | |
@{path = 'HKCU:\SOFTWARE\Microsoft\Clipboard'; name = 'EnableClipboardHistory'; propertyType = 'DWord'; data = 1 } | |
@{path = 'HKCU:\SOFTWARE\Microsoft\Windows\DWM'; name = 'EnableAeroPeek'; propertyType = 'DWord'; data = 0 } | |
) | |
} | |
class Registry { | |
static [hashtable[]] $list = @( | |
@{name = 'HideTaskbarSearch' } | |
@{name = 'DisableTelemetry' } | |
@{name = 'DisableEdgeHubSidebar' } | |
@{name = 'DisableWebSearch' } | |
@{name = 'DisableMapUpdates' } | |
@{name = 'HideChatIcon' } | |
@{name = 'DisableWindowsSpotlightFeatures' } | |
@{name = 'DisableWindowsWidgets' } | |
@{name = 'SetLongDateFormat' } | |
@{name = 'SetShortDateFormat' } | |
) | |
static [bool] ConfigureWindows() { | |
try { | |
foreach ($method in [Registry]::list) { | |
try { | |
$expr = "[Registry]::$($method.name)()" | |
Invoke-Expression $expr | |
} | |
catch { | |
Write-Host "[Error] Unable to invoke static method [Registry]::$($method.name)()" -ForegroundColor Red | |
} | |
} | |
Write-Host '[Info] Restore pinned taskbar icons...' -ForegroundColor Blue | |
[Taskbar]::RestorePinnedTaskbarIcons() | |
Write-Host '[Info] Restore desktop icons...' -ForegroundColor Blue | |
[DesktopIcons]::RestoreDesktopIcons() | |
Write-Host '[Info] Setting other registry values...' -ForegroundColor Blue | |
[Utils]::RestoreRegistry([OtherRegistrySettings]::registry) | |
return $true | |
} | |
catch { | |
return $false | |
} | |
} | |
static [void] HideTaskbarSearch() { | |
Write-Host '[Info] Hiding Taskbar Search box / button...' -ForegroundColor Blue | |
Set-ItemProperty -Path 'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Search' -Name 'SearchboxTaskbarMode' -Type DWord -Value 0 | |
} | |
static [void] ShowTaskbarSearchIcon() { | |
Write-Host '[Info] Showing Taskbar Search icon...' -ForegroundColor Blue | |
Set-ItemProperty -Path 'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Search' -Name 'SearchboxTaskbarMode' -Type DWord -Value 1 | |
} | |
static [void] ShowTaskbarSearchBox() { | |
Write-Host '[Info] Showing Taskbar Search box...' -ForegroundColor Blue | |
Set-ItemProperty -Path 'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Search' -Name 'SearchboxTaskbarMode' -Type DWord -Value 2 | |
} | |
# Disable Telemetry | |
static [void] DisableTelemetry() { | |
Write-Host '[Info] Disabling Telemetry...' -ForegroundColor Blue | |
Set-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\DataCollection' -Name 'AllowTelemetry' -Type DWord -Value 0 | |
Set-ItemProperty -Path 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\DataCollection' -Name 'AllowTelemetry' -Type DWord -Value 0 | |
Set-ItemProperty -Path 'HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Policies\DataCollection' -Name 'AllowTelemetry' -Type DWord -Value 0 | |
Get-ScheduledTask -TaskPath '\Microsoft\Windows\Application Experience\' -TaskName 'Microsoft Compatibility Appraiser' -ErrorAction SilentlyContinue | Disable-ScheduledTask | Out-Null | |
Get-ScheduledTask -TaskPath '\Microsoft\Windows\Application Experience\' -TaskName 'ProgramDataUpdater' -ErrorAction SilentlyContinue | Disable-ScheduledTask | Out-Null | |
Get-ScheduledTask -TaskPath '\Microsoft\Windows\Autochk\' -TaskName 'Proxy' -ErrorAction SilentlyContinue | Disable-ScheduledTask | Out-Null | |
Get-ScheduledTask -TaskPath '\Microsoft\Windows\Customer Experience Improvement Program\' -TaskName 'Consolidator' -ErrorAction SilentlyContinue | Disable-ScheduledTask | Out-Null | |
Get-ScheduledTask -TaskPath '\Microsoft\Windows\Customer Experience Improvement Program\' -TaskName 'UsbCeip' -ErrorAction SilentlyContinue | Disable-ScheduledTask | Out-Null | |
Get-ScheduledTask -TaskPath '\Microsoft\Windows\DiskDiagnostic\' -TaskName 'Microsoft-Windows-DiskDiagnosticDataCollector' -ErrorAction SilentlyContinue | Disable-ScheduledTask | Out-Null | |
} | |
# Enable Telemetry | |
static [void] EnableTelemetry() { | |
Write-Host '[Info] Enabling Telemetry...' -ForegroundColor Blue | |
Set-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\DataCollection' -Name 'AllowTelemetry' -Type DWord -Value 3 | |
Set-ItemProperty -Path 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\DataCollection' -Name 'AllowTelemetry' -Type DWord -Value 3 | |
Set-ItemProperty -Path 'HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Policies\DataCollection' -Name 'AllowTelemetry' -Type DWord -Value 3 | |
Get-ScheduledTask -TaskPath '\Microsoft\Windows\Application Experience\' -TaskName 'Microsoft Compatibility Appraiser' -ErrorAction SilentlyContinue | Enable-ScheduledTask | Out-Null | |
Get-ScheduledTask -TaskPath '\Microsoft\Windows\Application Experience\' -TaskName 'ProgramDataUpdater' -ErrorAction SilentlyContinue | Enable-ScheduledTask | Out-Null | |
Get-ScheduledTask -TaskPath '\Microsoft\Windows\Autochk\' -TaskName 'Proxy' -ErrorAction SilentlyContinue | Enable-ScheduledTask | Out-Null | |
Get-ScheduledTask -TaskPath '\Microsoft\Windows\Customer Experience Improvement Program\' -TaskName 'Consolidator' -ErrorAction SilentlyContinue | Enable-ScheduledTask | Out-Null | |
Get-ScheduledTask -TaskPath '\Microsoft\Windows\Customer Experience Improvement Program\' -TaskName 'UsbCeip' -ErrorAction SilentlyContinue | Enable-ScheduledTask | Out-Null | |
Get-ScheduledTask -TaskPath '\Microsoft\Windows\DiskDiagnostic\' -TaskName 'Microsoft-Windows-DiskDiagnosticDataCollector' -ErrorAction SilentlyContinue | Enable-ScheduledTask | Out-Null | |
} | |
# Disable Web Search in Start Menu | |
static [void] DisableWebSearch() { | |
Write-Host '[Info] Disabling Bing Search in Start Menu...' -ForegroundColor Blue | |
Set-ItemProperty -Path 'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Search' -Name 'BingSearchEnabled' -Type DWord -Value 0 | |
If (!(Test-Path 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\Windows Search')) { | |
New-Item -Path 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\Windows Search' -Force | Out-Null | |
} | |
Set-ItemProperty -Path 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\Windows Search' -Name 'DisableWebSearch' -Type DWord -Value 1 | |
} | |
# Enable Web Search in Start Menu | |
static [void] EnableWebSearch() { | |
Write-Host '[Info] Enabling Bing Search in Start Menu...' -ForegroundColor Blue | |
Remove-ItemProperty -Path 'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Search' -Name 'BingSearchEnabled' -ErrorAction SilentlyContinue | |
Remove-ItemProperty -Path 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\Windows Search' -Name 'DisableWebSearch' -ErrorAction SilentlyContinue | |
} | |
# Disable Edge HubSidebar | |
static [void] DisableEdgeHubSidebar() { | |
Write-Host '[Info] Disabling Edge Hub Sidebar...' -ForegroundColor Blue | |
If (!(Test-Path 'HKLM:\SOFTWARE\Policies\Microsoft\Edge')) { | |
New-Item -Path 'HKLM:\SOFTWARE\Policies\Microsoft\Edge' -Force | Out-Null | |
} | |
Set-ItemProperty -Path 'HKLM:\SOFTWARE\Policies\Microsoft\Edge' -Name 'HubsSidebarEnabled' -Type DWord -Value 0 | |
} | |
# Enable Edge HubSidebar | |
static [void] EnableEdgeHubSidebar() { | |
Write-Host '[Info] Enabling Edge Hub Sidebar...' -ForegroundColor Blue | |
If (!(Test-Path 'HKLM:\SOFTWARE\Policies\Microsoft\Edge')) { | |
New-Item -Path 'HKLM:\SOFTWARE\Policies\Microsoft\Edge' -Force | Out-Null | |
} | |
Set-ItemProperty -Path 'HKLM:\SOFTWARE\Policies\Microsoft\Edge' -Name 'HubsSidebarEnabled' -Type DWord -Value 1 | |
} | |
# Disable Windows 11 widgets | |
static [void] DisableWindowsWidgets() { | |
Write-Host '[Info] Disabling Windows 11 widgets...' -ForegroundColor Blue | |
Set-ItemProperty -Path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced' -Name 'TaskbarDa' -Type DWord -Value 0 | |
} | |
# Enable Windows 11 widgets | |
static [void] EnableWindowsWidgets() { | |
Write-Host '[Info] Enabling Windows 11 widgets...' -ForegroundColor Blue | |
Set-ItemProperty -Path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced' -Name 'TaskbarDa' -Type DWord -Value 1 | |
} | |
# Disable automatic Maps updates | |
static [void] DisableMapUpdates() { | |
Write-Host '[Info] Disabling automatic Maps updates...' -ForegroundColor Blue | |
Set-ItemProperty -Path 'HKLM:\SYSTEM\Maps' -Name 'AutoUpdateEnabled' -Type DWord -Value 0 | |
} | |
# Enable automatic Maps updates | |
static [void] EnableMapUpdates() { | |
Write-Host '[Info] Enabling automatic Maps updates...' -ForegroundColor Blue | |
Remove-ItemProperty -Path 'HKLM:\SYSTEM\Maps' -Name 'AutoUpdateEnabled' -ErrorAction SilentlyContinue | |
} | |
# Hide chat icon | |
static [void] HideChatIcon() { | |
Write-Host '[Info] Hiding taskbar Chat icon...' -ForegroundColor Blue | |
Set-ItemProperty -Path 'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced' -Name 'TaskbarMn' -Type DWord -Value 0 | |
Set-ItemProperty -Path 'HKLM:\SOFTWARE\Policies\Microsoft\Windows' -Name 'ChatIcon' -Type DWord -Value 0x03 | |
} | |
# Show chat icon | |
static [void] ShowChatIcon() { | |
Write-Host '[Info] Showing taskbar Chat icon...' -ForegroundColor Blue | |
Set-ItemProperty -Path 'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced' -Name 'TaskbarMn' -Type DWord -Value 1 | |
Remove-ItemProperty -Path 'HKLM:\SOFTWARE\Policies\Microsoft\Windows' -Name 'ChatIcon' -ErrorAction SilentlyContinue | |
} | |
# Disable Windows Desktop Spotlight (DisableWindowsSpotlightFeatures) | |
static [void] DisableWindowsSpotlightFeatures() { | |
Write-Host "[Info] Disabling Windows Desktop Spotlight..." -ForegroundColor Blue | |
Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\CloudContent" -Name "DisableWindowsSpotlightFeatures" -Type DWord -Value 1 | |
} | |
# Enable Windows Desktop Spotlight (DisableWindowsSpotlightFeatures) | |
static [void] EnableWindowsSpotlightFeatures() { | |
Write-Host "[Info] Enabling Windows Desktop Spotlight..." -ForegroundColor Blue | |
Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\CloudContent" -Name "DisableWindowsSpotlightFeatures" -Type DWord -Value 0 | |
} | |
# Enable 'show file extensions' option | |
static [void] ShowFileExtensions() { | |
Write-Host "[Info] Enabling 'show file extensions' option..." -ForegroundColor Blue | |
Set-ItemProperty -Path 'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced' -Name 'HideFileExt' -Type DWord -Value 0 | |
} | |
# Disable 'show file extensions' option | |
static [void] HideFileExtensions() { | |
Write-Host "[Info] Disabling 'show file extensions' option..." -ForegroundColor Blue | |
Set-ItemProperty -Path 'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced' -Name 'HideFileExt' -Type DWord -Value 1 | |
} | |
static [void] SetShortTimeFormat() { | |
Write-Host '[Info] Setting short time format (HH:mm:ss)...' -ForegroundColor Blue | |
Set-ItemProperty -Path 'HKCU:\Control Panel\International' -Name sShortTime -Value 'hh:mm:ss' | |
} | |
static [void] SetLongTimeFormat() { | |
Write-Host '[Info] Setting long time format (HH:mm:ss)...' -ForegroundColor Blue | |
Set-ItemProperty -Path 'HKCU:\Control Panel\International' -Name sTimeFormat -Value 'hh:mm:ss' | |
} | |
static [void] SetLongDateFormat() { | |
Write-Host '[Info] Setting long date format (dddd, MMMM d, yyyy)...' -ForegroundColor Blue | |
Set-ItemProperty -Path 'HKCU:\Control Panel\International' -Name sLongDate -Value 'dddd, MMMM d, yyyy' | |
} | |
static [void] SetShortDateFormat() { | |
Write-Host '[Info] Setting short date format (d-M-yyyy)...' -ForegroundColor Blue | |
Set-ItemProperty -Path 'HKCU:\Control Panel\International' -Name sShortDate -Value 'd-M-yyyy' | |
} | |
} |
# Title: Utils class | |
# Author: B. van Wetten | |
# Last Update: 2024-01-03 | |
class Utils { | |
# Static variable to control debug mode | |
static [bool] $DebugMode = $false | |
# Method to output a debug message | |
static [void] OutputDebugMessage([string] $message) { | |
if ([Utils]::DebugMode) { | |
Write-Host "[Debug] $message" -ForegroundColor DarkGray | |
} | |
} | |
# Method to enable or disable debug mode | |
static [void] SetDebugMode([bool] $mode) { | |
[Utils]::DebugMode = $mode | |
} | |
static [void] CreateRegistryPath([string] $KeyPath) { | |
<# | |
.SYNOPSIS | |
Recursively creates a new registry path, creating any intermediate subkeys that do not exist. | |
.DESCRIPTION | |
This method works similarly to 'mkdir -p' for directories. It creates the specified registry path, including all intermediate subkeys that do not already exist. | |
.PARAMETER KeyPath | |
The full path of the registry key to create. | |
.EXAMPLE | |
Utils::CreateRegistryPath -KeyPath "HKCU:\Software\MyApp\Settings" | |
This example creates the registry path "HKCU:\Software\MyApp\Settings", including any intermediate subkeys that do not already exist. | |
#> | |
try { | |
# Split the KeyPath into individual keys | |
$keys = $KeyPath -split '\\' | |
$currentPath = '' | |
foreach ($key in $keys) { | |
# Build the current path incrementally | |
$currentPath = if ($currentPath) { $currentPath + '\' + $key } else { $key } | |
# Check if the current path exists, if not, create it | |
if (-not (Test-Path $currentPath)) { | |
New-Item -Path $currentPath -Force > $null | |
} | |
} | |
} | |
catch { | |
Write-Host "[Error] Failed to create registry path at $KeyPath. Error: $_" -ForegroundColor Red | |
} | |
} | |
static [void] SetRegistryValue([string] $KeyPath, [string] $Name, [string] $Value) { [Utils]::SetRegistryValue($KeyPath, $Name, $Value, "String") } | |
static [void] SetRegistryValue( | |
[string]$KeyPath, | |
[string]$Name, | |
[string]$Value, | |
[string]$Type = 'String' | |
) { | |
<# | |
.SYNOPSIS | |
Sets a registry value at the specified key path with the given name, value, and type. | |
.DESCRIPTION | |
This function sets a registry value at the specified key path with the given name, value, and type. It performs manual validation for the specified type and creates the registry key if it doesn't exist. | |
.PARAMETER KeyPath | |
The path of the registry key where the value will be set. | |
.PARAMETER Name | |
The name of the registry value. | |
.PARAMETER Value | |
The value to be set. | |
.PARAMETER Type | |
The type of the registry value. Valid options are: String, ExpandString, Binary, DWord, MultiString, QWord, None. Default is String. | |
.EXAMPLE | |
SetRegistryValue -KeyPath "HKCU:\Software\MyApp" -Name "Version" -Value "1.0" -Type String | |
This example sets a registry value named "Version" with the value "1.0" at the key path "HKCU:\Software\MyApp" using the default type (String). | |
#> | |
try { | |
# Manual validation for $Type | |
$validTypes = @('String', 'ExpandString', 'Binary', 'DWord', 'MultiString', 'QWord', 'None') | |
if ($Type -notin $validTypes) { | |
throw "Invalid Type specified. Valid options are: $($validTypes -join ', ')" | |
} | |
if (-not (Test-Path "$KeyPath")) { | |
[Utils]::CreateRegistryPath("$KeyPath") | |
} | |
Set-ItemProperty -Path "$KeyPath" -Name $Name -Value $Value -Type $Type | |
} | |
catch { | |
Write-Host "[Error] Failed to set registry value at path $KeyPath with name $Name. Error: $_" -ForegroundColor Red | |
} | |
} | |
static [void] DownloadFile([string]$fileUri, [string]$outputFolder) { [Utils]::DownloadFile($fileUri, $outputFolder, "") } | |
static [void] DownloadFile([string]$fileUri, [string]$outputFolder, [string] $fileName = "") { | |
<# | |
.SYNOPSIS | |
Downloads a file from a specified URL to a specified output folder. | |
.DESCRIPTION | |
The DownloadFile function downloads a file from the specified URL to the specified output folder. If the file already exists in the output folder, it displays an information message. If the download is successful, it displays a success message. If the download fails, it displays an error message. | |
.PARAMETER fileUri | |
The URL of the file to be downloaded. | |
.PARAMETER outputFolder | |
The path of the folder where the downloaded file will be saved. | |
.EXAMPLE | |
DownloadFile -fileUri "https://example.com/file.txt" -outputFolder "C:\Downloads" | |
Downloads the file from the specified URL and saves it to the specified output folder. | |
#> | |
if ($fileName -eq "") { | |
$fileName = Split-Path -Path $fileUri -Leaf | |
} | |
$outputPath = Join-Path -Path $outputFolder -ChildPath $fileName | |
$outputPath = Join-Path -Path $outputFolder -ChildPath $fileName | |
if (Test-Path $outputPath) { | |
Write-Host "[Info] $fileName already downloaded..." -ForegroundColor Magenta | |
} | |
else { | |
# Test if the folder exists, otherwise create it | |
if (-not (Test-Path $outputFolder)) { | |
New-Item -Path $outputFolder -ItemType Directory | Out-Null | |
} | |
$response = Invoke-WebRequest -Passthru -Uri $fileUri -OutFile $outputPath | |
if ($response.StatusCode -eq 200 -and (Test-Path $outputPath)) { | |
Write-Host "[OK] $fileName downloaded successfully..." -ForegroundColor Green | |
} | |
else { | |
Write-Host "[Error] Failed to download $fileName..." -ForegroundColor Red | |
} | |
} | |
} | |
static [void] WingetInstall([string] $packageId, [string] $wingetFolder) { | |
<# | |
.SYNOPSIS | |
Installs a package using winget with local caching. | |
.DESCRIPTION | |
This method installs a package using winget. If the package is already downloaded in the specified folder, it installs from there, otherwise downloads it. | |
.PARAMETER packageId | |
The ID of the package to install. | |
.PARAMETER wingetFolder | |
The folder to check for cached package installers. | |
.EXAMPLE | |
[Utils]::WingetInstall "Microsoft.VisualStudioCode" "C:\winget-cache" | |
Installs Visual Studio Code, using a local cache if available. | |
#> | |
Write-Host "[Info] Installing $packageId..." -ForegroundColor Blue | |
$packageDetails = winget.exe show -e --accept-source-agreements --id $packageId | |
$matches = [regex]::Matches($packageDetails, "Installer\sUrl:\s.*\/([^\/]+)(\.(?:exe|msi|msix))") | |
# Debug output | |
[Utils]::OutputDebugMessage("[Debug] packageId: $packageId") | |
[Utils]::OutputDebugMessage("[Debug] packageDetails: $packageDetails") | |
[Utils]::OutputDebugMessage("[Debug] matches: $matches") | |
if ($matches.Count -eq 1) { | |
$filename = $matches[0].Groups[1].Value | |
$filenameExt = $matches[0].Groups[2].Value | |
winget.exe install -h --exact --accept-source-agreements --accept-package-agreements --id $packageId | |
# # Debug output | |
# [Utils]::OutputDebugMessage("[Debug] filename: $filename") | |
# [Utils]::OutputDebugMessage("[Debug] filenameExt: $filenameExt") | |
# # Create the folder if it doesn't exist | |
# if (-not (Test-Path "$wingetFolder\$packageId")) { | |
# New-Item -Path "$wingetFolder\$packageId" -ItemType Directory | Out-Null | |
# Write-Host "[Info] Downloading $packageId..." -ForegroundColor Blue | |
# winget.exe download --exact --scope machine --accept-source-agreements --accept-package-agreements --id $packageId --download-directory "$wingetFolder\$packageId" | |
# } | |
# $manifestFile = $wingetFolder + "\" + $packageId + "\$packageId.yaml" | |
# $installerFile = $wingetFolder + "\" + $packageId + "\$packageId$filenameExt" | |
# # Debug output | |
# [Utils]::OutputDebugMessage("[Debug] manifestFile: $manifestFile") | |
# [Utils]::OutputDebugMessage("[Debug] installerFile: $installerFile") | |
# # Check if both files exist, otherwise throw an error | |
# if (-not (Test-Path $manifestFile) -or -not (Test-Path $installerFile)) { | |
# throw "Unable to find installer for package $packageId" | |
# } | |
# # Debug output | |
# [Utils]::OutputDebugMessage("[Debug] winget.exe install -h --exact --accept-source-agreements --accept-package-agreements --id $packageId '$installerFile'") | |
# # Install the package | |
# winget.exe install -h --exact --accept-source-agreements --accept-package-agreements --id $packageId "$installerFile" | |
} | |
else { | |
throw "Unable to find installer URL for package $packageId" | |
} | |
} | |
static [void] NewShortcut([String] $Target, [String] $Destination) { | |
<# | |
.SYNOPSIS | |
Creates a new shortcut. | |
.DESCRIPTION | |
This function creates a new shortcut using the Windows Scripting Shell. | |
.PARAMETER Target | |
The target path of the shortcut. | |
.PARAMETER Destination | |
The destination path where the shortcut will be saved. | |
.EXAMPLE | |
NewShortcut -Target "C:\Program Files\MyApp\MyApp.exe" -Destination "C:\Users\Username\Desktop\MyApp.lnk" | |
Creates a new shortcut for the application "MyApp" on the user's desktop. | |
.LINK | |
https://stackoverflow.com/a/9701907/16036749 | |
#> | |
$WScriptShell = New-Object -ComObject WScript.Shell | |
$Shortcut = $WScriptShell.CreateShortcut($Destination) | |
$Shortcut.TargetPath = $Target | |
$Shortcut.Save() | |
} | |
static [void] RestoreRegistry([hashtable[]] $registrySettings) { | |
<# | |
.SYNOPSIS | |
Restores registry settings based on the provided hashtable array. | |
.DESCRIPTION | |
This function restores registry settings by iterating through the provided hashtable array and creating or updating registry keys and values accordingly. | |
.PARAMETER registrySettings | |
An array of hashtables containing the registry settings to be restored. Each hashtable should have the following properties: | |
- path: The path of the registry key. | |
- name: The name of the registry value. | |
- propertyType: The type of the registry value. | |
- data: The data to be set for the registry value. | |
.EXAMPLE | |
$registrySettings = @( | |
@{ | |
path = "HKCU:\Software\MyApp" | |
name = "Version" | |
propertyType = "String" | |
data = "1.0" | |
}, | |
@{ | |
path = "HKLM:\Software\MyApp" | |
name = "InstallDir" | |
propertyType = "ExpandString" | |
data = "C:\Program Files\MyApp" | |
} | |
) | |
RestoreRegistry -registrySettings $registrySettings | |
#> | |
foreach ($registry in $registrySettings) { | |
If (!(Test-Path $registry.path)) { | |
New-Item -Path $registry.path -Force | Out-Null | |
} | |
[Utils]::OutputDebugMessage("Attempting to create '$('{0}\{1}' -f $registry.path, $registry.name)'") | |
switch ($registry.propertyType) { | |
'Binary' { [Utils]::SetRegistryValue($registry.path, $registry.name, ([byte[]]([System.Convert]::FromHexString($registry.data))), $registry.propertyType) } | |
'DWord' { [Utils]::SetRegistryValue($registry.path, $registry.name, ([byte]($registry.data)), $registry.propertyType) } | |
Default { [Utils]::SetRegistryValue($registry.path, $registry.name, ($registry.data), $registry.propertyType) } | |
} | |
} | |
} | |
static [void] Pause ([string] $msg) { [Utils]::Pause($msg, $null) } | |
static [void] Pause ([string] $msg, [int] $timeout = 0) { | |
<# | |
.SYNOPSIS | |
Pauses the script execution and waits for user input or a timeout. | |
.DESCRIPTION | |
The Pause function pauses the script execution and waits for user input or a timeout to occur. It displays a message in yellow color before waiting for input. | |
.PARAMETER msg | |
The message to display before waiting for input. | |
.PARAMETER timeout | |
The maximum time (in seconds) to wait for user input before timing out. If not specified, the function waits indefinitely. | |
.EXAMPLE | |
Pause "Press any key to continue..." 5 | |
Pauses the script execution and waits for 5 seconds for user input. If no input is received within the specified timeout, the function returns. | |
.EXAMPLE | |
Pause "Press any key to continue..." | |
Pauses the script execution and waits indefinitely for user input. | |
#> | |
try { | |
Write-Host "$msg" -ForegroundColor Yellow | |
$timer = New-Object System.Diagnostics.Stopwatch | |
$timer.Start() | |
while (-not [Console]::KeyAvailable -and ($timeout -eq 0 -or $timer.Elapsed.Seconds -lt $timeout)) { | |
Start-Sleep -Milliseconds 50 | |
} | |
if ([Console]::KeyAvailable) { | |
[void][Console]::ReadKey($true) | |
} | |
} | |
catch { | |
throw $_.Exception.Message | |
} | |
} | |
static [bool] RemoveApp([string] $appName) { | |
<# | |
.SYNOPSIS | |
Removes an app from Windows 11. | |
.DESCRIPTION | |
This function removes an app from Windows 11 by uninstalling the app package and removing the provisioned package. | |
.PARAMETER appName | |
The name of the app to be removed. | |
.EXAMPLE | |
RemoveApp -appName "Microsoft.WindowsAlarms" | |
#> | |
try { | |
Get-AppxPackage $appName -AllUsers | Remove-AppxPackage | |
Get-AppXProvisionedPackage -Online | Where-Object DisplayName -like $appName | Remove-AppxProvisionedPackage -Online | |
return $true | |
} | |
catch { | |
throw $_.Exception.Message | |
} | |
} | |
static [void] RestartExplorer() { | |
<# | |
.SYNOPSIS | |
Restarts Windows Explorer. | |
.DESCRIPTION | |
This function restarts the Windows Explorer process. It first stops the existing Explorer process, waits for a few seconds, and then verifies if the process has restarted. If the process is not found, it attempts to start the Explorer process again. If any errors occur during the process, an exception is thrown. | |
.PARAMETER None | |
This function does not accept any parameters. | |
.EXAMPLE | |
RestartExplorer | |
Restarts the Windows Explorer process. | |
#> | |
Get-Process -Name Explorer | Stop-Process -Force | |
# Give Windows Explorer time to start | |
Start-Sleep -Seconds 3 | |
# Verify that Windows Explorer has restarted | |
Try { | |
$p = Get-Process -Name Explorer -ErrorAction Stop | |
} | |
Catch { | |
Try { | |
Start-Process explorer.exe | |
} | |
Catch { | |
# This should never be called | |
Throw $_ | |
} | |
} | |
} | |
static [void] EnsureDockerRunning() { | |
<# | |
.SYNOPSIS | |
Ensures that Docker is running on the Windows 11 Sandbox. | |
.DESCRIPTION | |
This function checks if Docker is already running on the Windows 11 Sandbox. If Docker is not running, it starts Docker Desktop assuming the default installation path. It then waits for Docker to start running or until a timeout is reached. If Docker does not start within the specified time, an error message is displayed and the script exits with a non-zero exit code. | |
.PARAMETER None | |
.INPUTS | |
None | |
.OUTPUTS | |
None | |
.EXAMPLE | |
EnsureDockerRunning | |
This example demonstrates how to use the EnsureDockerRunning function to ensure that Docker is running on the Windows 11 Sandbox. | |
#> | |
function IsDockerRunning { | |
try { | |
docker info > $null 2>&1 | |
return $? | |
} | |
catch { | |
return $false | |
} | |
} | |
# Check if Docker is already running | |
if (IsDockerRunning) { exit 0 } | |
# Start Docker Desktop (assuming default installation path) | |
Start-Process "C:\Program Files\Docker\Docker\Docker Desktop.exe" | |
# Initialize variables | |
$timeoutMinutes = 1 | |
$elapsedSeconds = 0 | |
$isDockerRunning = $false | |
# Wait until Docker is running or timeout is reached | |
do { | |
# Check every 5 seconds | |
Start-Sleep -Seconds 5 | |
$elapsedSeconds += 5 | |
Write-Host "[Info] Waiting for Docker to start..." -ForegroundColor Blue | |
} while (-not (IsDockerRunning) -and $elapsedSeconds -lt ($timeoutMinutes * 60)) | |
if (-not (IsDockerRunning)) { | |
Write-Host "[Error] Docker failed to start within $timeoutMinutes minutes. Exiting..." -ForegroundColor Red | |
exit 1 | |
} | |
} | |
static [string] WriteFile([string] $encodedString) { return [Utils]::WriteFile($encodedString, ('{0}\{1}' -f $env:TEMP, [System.Guid]::NewGuid().ToString())) } | |
static [string] WriteFile([string] $encodedString, $file = ('{0}\{1}' -f $env:TEMP, [System.Guid]::NewGuid().ToString())) { | |
<# | |
.SYNOPSIS | |
Writes a file from a base64 encoded string. | |
.DESCRIPTION | |
This function takes a base64 encoded string and writes it to a file on the local system. The file path is generated using the current user's TEMP directory and a unique GUID. | |
.PARAMETER encodedString | |
The base64 encoded string representing the file content. | |
.PARAMETER path | |
The optional file path where the file will be written. If not provided, the file will be written to the current user's TEMP directory with a unique file name. | |
.EXAMPLE | |
$encodedString = "SGVsbG8gV29ybGQh" | |
$filePath = WriteFile -encodedString $encodedString | |
Write-Host "File written to: $filePath" | |
#> | |
try { | |
# Decode the base64 string | |
$decodedBytes = [System.Convert]::FromBase64String($encodedString) | |
# Ensure the directory exists | |
$directoryPath = [System.IO.Path]::GetDirectoryName($file) | |
if (-not (Test-Path $directoryPath)) { | |
New-Item -Path $directoryPath -ItemType Directory -Force | Out-Null | |
} | |
[System.IO.File]::WriteAllBytes($file, $decodedBytes) | |
return Get-Item -Path $file | |
} | |
catch { | |
Write-Host "[Error] Failed to write file from base64 string. Error: $_" -ForegroundColor Red | |
return $null | |
} | |
} | |
static [bool] WriteArchive([string] $archiveFilePath, [string] $extractPath) { | |
<# | |
.SYNOPSIS | |
Extracts a base64 encoded, gzipped, and tarred archive to a specified directory. | |
.DESCRIPTION | |
This function takes the path to a file containing a base64 encoded, gzipped, and tarred archive. It decodes the file, uncompresses it, and extracts the contents to the specified directory. | |
.PARAMETER archiveFilePath | |
The file path to the base64 encoded, gzipped, and tarred archive. | |
.PARAMETER extractPath | |
The directory path where the contents of the archive should be extracted. | |
.EXAMPLE | |
$archiveFilePath = "C:\path\to\encoded_archive.txt" | |
$extractPath = "C:\path\to\extract" | |
$result = [Utils]::WriteArchive($archiveFilePath, $extractPath) | |
if ($result) { Write-Host "Archive extracted successfully" } | |
else { Write-Host "Failed to extract archive" } | |
#> | |
try { | |
# Ensure that the archive file exists | |
if (-not (Test-Path $archiveFilePath)) { | |
Throw "Archive file not found at $archiveFilePath" | |
} | |
# Ensure the extract directory exists | |
if (-not (Test-Path $extractPath)) { | |
New-Item -Path $extractPath -ItemType Directory -Force | Out-Null | |
} | |
# Read the base64 encoded archive from file and decode it | |
$encodedString = Get-Content -Path $archiveFilePath | |
$decodedBytes = [System.Convert]::FromBase64String($encodedString) | |
# Write the decoded bytes to a temporary gzip file | |
$tempGzipPath = [System.IO.Path]::Combine($env:TEMP, [System.Guid]::NewGuid().ToString() + ".gz") | |
[System.IO.File]::WriteAllBytes($tempGzipPath, $decodedBytes) | |
# Use tar to extract the gzipped tarball | |
tar -xzf $tempGzipPath -C $extractPath | |
# Clean up the temporary gzip file | |
Remove-Item -Path $tempGzipPath | |
return $true | |
} | |
catch { | |
Write-Host "[Error] Failed to extract archive. Error: $_" -ForegroundColor Red | |
return $false | |
} | |
} | |
static SetTaskbarLayout([string] $filePath, [string] $encodedData) { | |
<# | |
.SYNOPSIS | |
Sets the taskbar layout by creating a 'TaskbarLayoutModification.xml' file and modifying the registry. | |
.DESCRIPTION | |
This function sets the taskbar layout by creating a 'TaskbarLayoutModification.xml' file and modifying the registry values related to the taskbar layout. It takes the file path and encoded data as input parameters. | |
.PARAMETER filePath | |
The path where the 'TaskbarLayoutModification.xml' file will be created. | |
.PARAMETER encodedData | |
The encoded data for the 'TaskbarLayoutModification.xml' file. | |
.EXAMPLE | |
SetTaskbarLayout -filePath "C:\Scripts" -encodedData "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4NCjxMYXlvdXRNb2RpZmljYXRpb25UZW1wbGF0ZQ0KICAgIHhtbG5zPSJodHRwOi8vc2NoZW1hcy5taWNyb3NvZnQuY29tL1N0YXJ0LzIwMTQvTGF5b3V0TW9kaWZpY2F0aW9uIg0KICAgIHhtbG5zOmRlZmF1bHRsYXlvdXQ9Imh0dHA6Ly9zY2hlbWFzLm1pY3Jvc29mdC5jb20vU3RhcnQvMjAxNC9GdWxsRGVmYXVsdExheW91dCINCiAgICB4bWxuczpzdGFydD0iaHR0cDovL3NjaGVtYXMubWljcm9zb2Z0LmNvbS9TdGFydC8yMDE0L1N0YXJ0TGF5b3V0Ig0KICAgIHhtbG5zOnRhc2tiYXI9Imh0dHA6Ly9zY2hlbWFzLm1pY3Jvc29mdC5jb20vU3RhcnQvMjAxNC9UYXNrYmFyTGF5b3V0Ig0KICAgIFZlcnNpb249IjEiPg0KICA8Q3VzdG9tVGFza2JhckxheW91dENvbGxlY3Rpb24+DQogICAgPGRlZmF1bHRsYXlvdXQ6VGFza2JhckxheW91dD4NCiAgICAgIDx0YXNrYmFyOlRhc2tiYXJQaW5MaXN0Pg0KICAgICAgICA8dGFza2JhcjpEZXNrdG9wQXBwIERlc2t0b3BBcHBsaWNhdGlvbklEPSJNaWNyb3NvZnQuV2luZG93cy5FeHBsb3JlciIgLz4NCiAgICAgICAgPHRhc2tiYXI6RGVza3RvcEFwcCBEZXNrdG9wQXBwbGljYXRpb25MaW5rUGF0aD0iJUFQUERBVEElXE1pY3Jvc29mdFxXaW5kb3dzXFN0YXJ0IE1lbnVcUHJvZ3JhbXNcU3lzdGVtIFRvb2xzXENvbW1hbmQgUHJvbXB0LmxuayIgLz4NCiAgICAgIDwvdGFza2JhcjpUYXNrYmFyUGluTGlzdD4NCiAgICA8L2RlZmF1bHRsYXlvdXQ6VGFza2JhckxheW91dD4NCiA8L0N1c3RvbVRhc2tiYXJMYXlvdXRDb2xsZWN0aW9uPg0KPC9MYXlvdXRNb2RpZmljYXRpb25UZW1wbGF0ZQ==" | |
#> | |
try { | |
# Create 'TaskbarLayoutModification.xml' file | |
$taskbarLayoutModificationFile = "$filePath\TaskbarLayoutModification.xml" | |
if (!(Test-Path $filePath)) { | |
# Create directory | |
New-Item $filePath -ItemType Directory -Force | Out-Null | |
} | |
Write-Host "[Info] Creating 'TaskbarLayoutModification.xml' file" -ForegroundColor Blue | |
[Utils]::WriteFile($encodedData, $taskbarLayoutModificationFile) | Out-Null | |
[Utils]::SetRegistryValue("HKCU:\Software\Microsoft\Windows\CurrentVersion\Group Policy Objects\{E0CC53D9-2FFF-4D2E-BECB-333B41615D7E}User\Software\Policies\Microsoft\Windows\Explorer", "LockedStartLayout", 0x01, "DWord") | |
[Utils]::SetRegistryValue("HKCU:\Software\Microsoft\Windows\CurrentVersion\Group Policy Objects\{E0CC53D9-2FFF-4D2E-BECB-333B41615D7E}User\Software\Policies\Microsoft\Windows\Explorer", "ReapplyStartLayoutEveryLogon", 0x01, "DWord") | |
[Utils]::SetRegistryValue("HKCU:\Software\Microsoft\Windows\CurrentVersion\Group Policy Objects\{E0CC53D9-2FFF-4D2E-BECB-333B41615D7E}User\Software\Policies\Microsoft\Windows\Explorer", "StartLayoutFile", $taskbarLayoutModificationFile) | |
[Utils]::SetRegistryValue("HKCU:\Software\Policies\Microsoft\Windows\Explorer", "LockedStartLayout", 0x01, "DWord") | |
[Utils]::SetRegistryValue("HKCU:\Software\Policies\Microsoft\Windows\Explorer", "ReapplyStartLayoutEveryLogon", 0x01, "DWord") | |
[Utils]::SetRegistryValue("HKCU:\Software\Policies\Microsoft\Windows\Explorer", "StartLayoutFile", $taskbarLayoutModificationFile) | |
} | |
catch { | |
Write-Host "[Error] Failed to set taskbar layout. Error: $_" -ForegroundColor Red | |
} | |
} | |
<# | |
.SYNOPSIS | |
Adds an application to the TaskbarPinList in an XML file. | |
.DESCRIPTION | |
This function adds an application to the TaskbarPinList in an XML file. It takes the path of the XML file and the path of the application link as input parameters. The function loads the XML file, finds the TaskbarPinList node, creates a new DesktopApp element, appends it to the TaskbarPinList, and saves the updated XML back to the file. | |
.PARAMETER XmlFilePath | |
The path of the XML file containing the TaskbarPinList. | |
.PARAMETER AppLinkPath | |
The path of the application link to be added to the TaskbarPinList. | |
.EXAMPLE | |
AddAppToTaskbarPinList -XmlFilePath "C:\Layout.xml" -AppLinkPath "C:\Applications\MyApp.lnk" | |
Adds the application link "C:\Applications\MyApp.lnk" to the TaskbarPinList in the XML file "C:\Layout.xml". | |
.NOTES | |
This function requires the XML file to have the appropriate schema and namespace for the TaskbarPinList element. | |
#> | |
static [void] AddAppToTaskbarPinList([string] $XmlFilePath, [string] $AppLinkPath) { | |
try { | |
# Check if the XML file exists | |
if (-not (Test-Path $XmlFilePath)) { | |
throw "XML file not found at $XmlFilePath" | |
} | |
# Load the XML file | |
[xml]$xml = Get-Content -Path $XmlFilePath | |
# Define the namespace to handle the prefixed elements | |
$ns = New-Object System.Xml.XmlNamespaceManager($xml.NameTable) | |
$ns.AddNamespace('taskbar', 'http://schemas.microsoft.com/Start/2014/TaskbarLayout') | |
# Find the TaskbarPinList node | |
$taskbarPinListNode = $xml.SelectSingleNode('//taskbar:TaskbarPinList', $ns) | |
if ($null -eq $taskbarPinListNode) { | |
throw "TaskbarPinList node not found in $XmlFilePath" | |
} | |
# Create a new DesktopApp element | |
$newAppNode = $xml.CreateElement('DesktopApp', 'http://schemas.microsoft.com/Start/2014/TaskbarLayout') | |
$newAppNode.SetAttribute('DesktopApplicationLinkPath', $AppLinkPath) | |
# Append the new app to the TaskbarPinList | |
$taskbarPinListNode.AppendChild($newAppNode) | |
# Save the updated XML back to the file | |
$xml.Save($XmlFilePath) | |
} | |
catch { | |
Write-Host "[Error] Failed to add app to TaskbarPinList. Error: $_" -ForegroundColor Red | |
} | |
} | |
static [string] GetFileBase64([string] $path) { | |
<# | |
.SYNOPSIS | |
Converts a file to Base64 encoding. | |
.DESCRIPTION | |
This function reads the contents of a file and converts it to a Base64 string. | |
.PARAMETER path | |
The path of the file to be converted. | |
.EXAMPLE | |
GetFileBase64 -path "C:\path\to\file.txt" | |
This example converts the file located at "C:\path\to\file.txt" to Base64 encoding. | |
#> | |
try { | |
$file = [System.IO.File]::ReadAllBytes($path) | |
return [System.Convert]::ToBase64String($file) | |
} | |
catch { | |
throw $_.Exception.Message | |
} | |
} | |
static [void] RemoveFiles([hashtable[]] $fileList) { | |
<# | |
.SYNOPSIS | |
Removes specified files and directories. | |
.DESCRIPTION | |
This function removes the files and directories specified in the input parameter. | |
.PARAMETER fileList | |
An array of hashtables, each containing the 'path' and 'recursive' keys. | |
.EXAMPLE | |
$list = @( | |
@{path = "C:\Dell"; recursive = $True}, | |
@{path = "C:\Intel"; recursive = $True}, | |
@{path = "C:\PerfLogs"; recursive = $True} | |
) | |
RemoveFiles -fileList $list | |
#> | |
foreach ($item in $fileList) { | |
if (Test-Path $item.path) { | |
try { | |
if ($item.recursive) { | |
Remove-Item -Path $item.path -Recurse -Force -ErrorAction Stop | |
} | |
else { | |
Remove-Item -Path $item.path -Force -ErrorAction Stop | |
} | |
Write-Host "[OK] Successfully removed '$($item.path)'" -ForegroundColor Green | |
} | |
catch { | |
Write-Host "[Error] Failed to remove '$($item.path)': $_" -ForegroundColor Red | |
} | |
} | |
else { | |
Write-Host "[Warning] Path '$($item.path)' not found" -ForegroundColor Magenta | |
} | |
} | |
} | |
} | |
Function UpdateWallpaper([String] $Image) { | |
<# | |
.SYNOPSIS | |
Updates the wallpaper of the Windows 11 Sandbox. | |
.DESCRIPTION | |
This function updates the wallpaper of the Windows 11 Sandbox by calling the SystemParametersInfo function from the User32.dll. | |
.PARAMETER Image | |
The path of the image file to set as the wallpaper. | |
.EXAMPLE | |
UpdateWallpaper -Image "C:\Path\To\Image.jpg" | |
Updates the wallpaper of the Windows 11 Sandbox with the specified image. | |
.LINK | |
https://www.joseespitia.com/2017/09/15/set-wallpaper-powershell-function/ | |
#> | |
Add-Type -TypeDefinition @' | |
using System; | |
using System.Runtime.InteropServices; | |
public class Params { | |
[DllImport("User32.dll",CharSet=CharSet.Unicode)] | |
public static extern int SystemParametersInfo (Int32 uAction, Int32 uParam, String lpvParam, Int32 fuWinIni); | |
} | |
'@ | |
$SPI_SETDESKWALLPAPER = 0x0014 | |
$UpdateIniFile = 0x01 | |
$SendChangeEvent = 0x02 | |
$fWinIni = $UpdateIniFile -bor $SendChangeEvent | |
$ret = [Params]::SystemParametersInfo($SPI_SETDESKWALLPAPER, 0, $Image, $fWinIni) | |
} |
# Title: Remote Visual Studio Code development on a Windows 11 Sandbox VM | |
# Author: B. van Wetten | |
# Last Update: 2024-01-10 | |
# | |
# Usage: PowerShell.exe -ExecutionPolicy Bypass { Invoke-RestMethod -Uri https://gist.githubusercontent.com/QNimbus/83a86ee072d2b4dbfd13f2fe901796df/raw/scripts---vscode_sandbox.ps1 | Invoke-Expression } | |
# Start of script | |
Set-StrictMode -Version 1.0 | |
Set-Variable -Name ProgressPreference -Value "SilentlyContinue" # Default is "Continue" | |
Set-Variable -Name ErrorActionPreference -Value "Stop" # Default is "Continue" | |
$global:VSCodeSandboxVersion = "1.0.0" | |
$global:TempFolder = "$env:Temp" | |
$global:TempFolderRemote = "C:\Users\WDAGUtilityAccount\AppData\Local\Temp" | |
$global:VSCodeSandboxUserProfile = "$env:UserProfile" | |
$global:VSCodeSandboxUserProfileRemote = "C:\Users\WDAGUtilityAccount" | |
$global:VSCodeSandboxPath = "$env:UserProfile\.vscode_sandbox" | |
$global:VSCodeSandboxPathRemote = "C:\Users\WDAGUtilityAccount\Desktop\VSCodeSandbox" | |
$global:VSCodeSandboxPathWorkspace = "$global:VSCodeSandboxPath\workspace" | |
$global:VSCodeSandboxPathWorkspaceRemote = "$global:VSCodeSandboxPathRemote\workspace" | |
$global:VSCodeSandboxScript = "$global:VSCodeSandboxPath\.setup\sandbox_vscode.ps1" | |
$global:VSCodeSandboxScriptRemote = "$global:VSCodeSandboxPathRemote\.setup\sandbox_vscode.ps1" | |
$global:OpenSSHMSI = "OpenSSH-Win64-v9.5.0.0.msi" | |
$global:OpenSSHURL = "https://github.com/PowerShell/Win32-OpenSSH/releases/download/v9.5.0.0p1-Beta/$global:OpenSSHMSI" | |
$global:Use1PasswordCLI = $false | |
try { | |
# Clear the screen | |
Clear-Host | |
# Check if Windows Sandbox is installed | |
try { | |
# Requires elevation: Get-WindowsOptionalFeature -Online -FeatureName Containers-DisposableClientVM -ErrorAction Stop | Out-Null | |
Get-Command -Name WindowsSandbox -ErrorAction Stop | Out-Null | |
Write-Host ("[OK] Windows Sandbox Feature is installed, continuing...") -ForegroundColor Green | |
} | |
catch { | |
Throw "Windows Sandbox Feature is not installed, exiting..." | |
} | |
# Check if Sandbox is already running, exit if it is | |
if ((Get-Process -Name WindowsSandbox -ErrorAction SilentlyContinue).Length -gt 0) { | |
Throw "Windows Sandbox is already running, exiting..." | |
} | |
# Check if VSCode is installed, exit if not | |
if (code --help) { | |
Write-Host ("[OK] Visual Studio Code is installed, continuing...") -ForegroundColor Green | |
} | |
else { | |
Throw "Visual Studio Code is not installed, exiting..." | |
} | |
# Check if OpenSSH client is installed, exit if not | |
if (-not (Get-Command ssh-keygen -ErrorAction SilentlyContinue)) { | |
Throw "OpenSSH client not found, exiting..." | |
} | |
# Check if .ssh folder exists, create if not | |
if (-not (Test-Path -Path $env:UserProfile\.ssh)) { | |
New-Item -ItemType Directory -Path $env:UserProfile\.ssh -Force | Out-Null | |
} | |
# Check if Remote-SSH extension is installed, install if not | |
if ((code --list-extensions | Select-String 'ms-vscode-remote.remote-ssh').Length -gt 0) { | |
Write-Host ("[OK] Remote-SSH extension is installed, continuing...") -ForegroundColor Green | |
} | |
else { | |
Write-Host ("[Info] Installing Remote-SSH extension...") -ForegroundColor DarkGray | |
code --install-extension ms-vscode-remote.remote-ssh | Out-Null | |
} | |
# Create a $global:VSCodeSandboxPath/.setup folder if it does not exist | |
if (-not (Test-Path -Path $global:VSCodeSandboxPath\.setup)) { | |
New-Item -Type Directory -Path $global:VSCodeSandboxPath\.setup -Force | Out-Null | |
Write-Host ("[Info] Created $global:VSCodeSandboxPath\.setup folder") -ForegroundColor DarkGray | |
} | |
else { | |
Write-Host ("[OK] '$global:VSCodeSandboxPath\.setup' already exists, continuing...") -ForegroundColor Green | |
} | |
# Create SSH keys for connecting to Windows Sandbox | |
if ($global:Use1PasswordCLI) { | |
# Check if 1Password CLI is installed, exit if not installed | |
if (-not (Get-Command op -ErrorAction SilentlyContinue)) { | |
Throw "1Password CLI not found, exiting..." | |
} | |
# Fetch ssh keys (op item list --tags vscode-sandbox,ssh --categories SSHKey) | |
# $id = (op item list --tags vscode-sandbox,ssh --categories SSHKey --format json | ConvertFrom-Json | Select-Object -First 1).id | |
try { | |
$id = Invoke-Command -ErrorAction SilentlyContinue -ScriptBlock { op item list --tags vscode-sandbox, ssh --categories SSHKey --format json | ConvertFrom-Json | Select-Object -First 1 } | |
Write-Host ("`$id = $id") -ForegroundColor DarkGray | |
# $id = (op item list --tags vscode-sandbox,ssh --categories SSHKey --format json -ErrorAction Stop | ConvertFrom-Json | Select-Object -First 1).id | |
Write-Host ("Found SSH keys in 1Password, importing private key and copying .pub file to C:\VSCodeSandbox...") -ForegroundColor Green | |
} | |
catch { | |
# Handle the error | |
Write-Output "An error occurred: $_" | |
} | |
} | |
else { | |
try { | |
if (-not (Test-Path -Path $env:UserProfile\.ssh\id_ed25519_vscode)) { | |
# Create SSH keys using ssh-keygen.exe | |
Invoke-Command -ScriptBlock { ssh-keygen.exe -t ed25519 -f $env:UserProfile\.ssh\id_ed25519_vscode -q -N "" } | Out-Null | |
# Check if ssh-agent is running and if it is running, add the SSH key to the agent | |
if ((Get-Service ssh-agent).Status -eq "Running") { | |
& (Get-Command ssh-add).Source $env:UserProfile\.ssh\id_ed25519_vscode *> $null | |
} | |
Write-Host ("[Info] Created SSH keys...") -ForegroundColor DarkGray | |
} | |
else { | |
Write-Host ("[OK] SSH Keys already exist, continuing...") -ForegroundColor Green | |
} | |
# Copy .gitconfig file to $global:VSCodeSandboxUserProfileRemote\.gitconfig | |
Write-Host ("[Info] Copying .gitconfig file to $global:VSCodeSandboxUserProfileRemote\.gitconfig...") -ForegroundColor DarkGray | |
Copy-Item $env:UserProfile\.gitconfig -Destination $global:VSCodeSandboxPath\.setup\.gitconfig -Force | |
# Copy public key to $global:VSCodeSandboxPath | |
Write-Host ("[Info] Copying public key to $global:VSCodeSandboxPath\.setup") -ForegroundColor DarkGray | |
Copy-Item $env:UserProfile\.ssh\id_ed25519_vscode.pub $global:VSCodeSandboxPath\.setup\sandbox_pubkey -Force:$true -Confirm:$false | |
} | |
catch { | |
Write-Host ("[Error] $($_.Exception.Message)") -ForegroundColor Red | |
Throw "Error creating SSH keys, exiting..." | |
} | |
} | |
# Remove previous sandbox_ip | |
if (Test-Path -Path "$global:VSCodeSandboxPath\.setup\sandbox_ip") { | |
Write-Host ("[Info] Removing previous $global:VSCodeSandboxPath\.setup\sandbox_ip file...") -ForegroundColor DarkGray | |
Remove-Item -Path "$global:VSCodeSandboxPath\.setup\sandbox_ip" -Force:$true -Confirm:$false | |
} | |
# Create a VSCode.wsb file in C:\Windows\Temp\VSCodeSandbox | |
$wsb = @" | |
<Configuration> | |
<VGpu>Enable</VGpu> | |
<Networking>Enable</Networking> | |
<MappedFolders> | |
<MappedFolder> | |
<HostFolder>$global:VSCodeSandboxUserProfile\.ssh</HostFolder> | |
<SandboxFolder>$global:VSCodeSandboxPathRemote\.setup\.ssh</SandboxFolder> | |
<ReadOnly>true</ReadOnly> | |
</MappedFolder> | |
<MappedFolder> | |
<HostFolder>$global:VSCodeSandboxPath</HostFolder> | |
<SandboxFolder>$global:VSCodeSandboxPathRemote</SandboxFolder> | |
<ReadOnly>false</ReadOnly> | |
</MappedFolder> | |
</MappedFolders> | |
<LogonCommand> | |
<Command>powershell -NoProfile -ExecutionPolicy Unrestricted -File "$global:VSCodeSandboxScriptRemote"</Command> | |
</LogonCommand> | |
</Configuration> | |
"@ | |
$wsb | Out-File "$global:TempFolder\vscode.wsb" -Force -Confirm:$false | |
# Create the sandbox_vscode.ps1 for installation of OpenSSH Server, creation of local vscode admin account and vscodesshfile SSH Key | |
# Logging can be found in C:\Users\WDAGUtilityAccount\Desktop\VSCodeSandbox\.setup\sandbox_transcript if needed in the Windows Sandbox VM | |
$sandbox_vscode = @" | |
# Start of script | |
Start-Transcript $global:VSCodeSandboxPathRemote\.setup\sandbox_transcript | |
`$job = Start-Job -ArgumentList "$global:VSCodeSandboxPathRemote", "$global:VSCodeSandboxUserProfileRemote" -ScriptBlock { | |
Param(`$VSCodeSandboxPathRemote, `$VSCodeSandboxUserProfileRemote) | |
New-Item -Type Directory -Path "`$VSCodeSandboxPathRemote\.scoop" -Force | Out-Null | |
Invoke-RestMethod -Uri "https://get.scoop.sh" | Invoke-Expression | |
scoop config cache_path "`$VSCodeSandboxPathRemote\.scoop" | |
scoop config aria2-warning-enabled false | |
scoop config use_lessmsi `$true | |
scoop install lessmsi | |
scoop install 7zip aria2 git | |
scoop install nodejs python | |
reg import "`$VSCodeSandboxUserProfileRemote\scoop\apps\7zip\current\install-context.reg" | |
} | |
# Download OpenSSH MSI if it does not exist | |
if (-not (Test-Path "$global:VSCodeSandboxPathRemote\.setup\$global:OpenSSHMSI")) { | |
Invoke-WebRequest -Uri "$global:OpenSSHURL" -OutFile "$global:VSCodeSandboxPathRemote\.setup\$global:OpenSSHMSI" | |
} | |
# Install OpenSSH Client & Server | |
Start-Process -FilePath "msiexec.exe" -Verb RunAs -Wait -ArgumentList "/qn /i ``"$global:VSCodeSandboxPathRemote\.setup\$global:OpenSSHMSI``"" | |
# Modify local user account WDAGUtilityAccount with password "vscode" | |
Set-LocalUser -Name WDAGUtilityAccount -PasswordNeverExpires 1 -Password ("vscode" | ConvertTo-SecureString -AsPlainText -Force) | |
# Create several folders | |
New-Item -Type Directory -Path C:\ProgramData\ssh -Force | Out-Null | |
New-Item -Type Directory -Path "$global:VSCodeSandboxPathRemote\.vscode-server" -Force | Out-Null | |
New-Item -Type Directory -Path "$global:VSCodeSandboxPathWorkspaceRemote" -Force | Out-Null | |
# Create symbolic link to .vscode-server folder | |
New-Item -Type SymbolicLink -Path "$global:VSCodeSandboxUserProfileRemote\.vscode-server" -Target "$global:VSCodeSandboxPathRemote\.vscode-server" -Force | Out-Null | |
# Copy .ssh folder to C:\Users\WDAGUtilityAccount and create symbolic link | |
Copy-Item -Path "$global:VSCodeSandboxPathRemote\.setup\.ssh" -Destination "$global:VSCodeSandboxUserProfileRemote" -Recurse -Force | |
# Create symbolic link to .gitconfig file | |
Copy-Item -Path "$global:VSCodeSandboxPathRemote\.setup\.gitconfig" -Destination "$global:VSCodeSandboxUserProfileRemote" -Force | |
# Copy public key to C:\ProgramData\ssh\administrators_authorized_keys | |
Copy-Item "$global:VSCodeSandboxPathRemote\.setup\sandbox_pubkey" C:\ProgramData\ssh\administrators_authorized_keys | |
# Store current ip address of Sandbox in $global:VSCodeSandboxPathRemote\.setup\sandbox_ip | |
(Get-NetIPAddress -InterfaceAlias Ethernet -AddressFamily IPv4).IPAddress | Out-File "$global:VSCodeSandboxPathRemote\.setup\sandbox_ip" -Force | |
# Wait for asynchronous job to finish | |
Receive-Job -Job `$job -Wait | |
Stop-Transcript | |
"@ | |
$sandbox_vscode | Out-File $global:VSCodeSandboxScript -Force | |
# Start Windows Sandbox using the VSCode.wsb file | |
Write-Host ("[Info] Starting Windows Sandbox...") -ForegroundColor DarkGray | |
Start-Process -FilePath $(Get-Command -Name WindowsSandbox).Source -ArgumentList "$global:TempFolder\vscode.wsb" | Out-Null | |
# Wait for installation of OpenSSH server and creation of sandbox_ip file | |
$interval = 0 | |
while (-not (Test-Path -Path $global:VSCodeSandboxPath\.setup\sandbox_ip)) { | |
# Perform modulo on $interval to check if it is a multiple of 5 | |
if (($interval++ % 15) -eq 0) { | |
Write-Host ("[Info] Waiting for creation of $global:VSCodeSandboxPath\.setup\sandbox_ip file...") -ForegroundColor DarkGray | |
} | |
Start-Sleep -Seconds 1 | |
if ($interval -gt 60) { | |
Throw "Error creating $global:VSCodeSandboxPath\.setup\sandbox_ip file, exiting..." | |
} | |
} | |
# Check each service for status "Running" and wait until all services are running (Get-Service -Name ssh*).Status -eq "Running" | |
$interval = 0 | |
while ((Get-Service -Name ssh* | Where-Object { $_.Status -eq 'Running' }).Count -ge 1) { | |
# Perform modulo on $interval to check if it is a multiple of 5 | |
if (($interval++ % 15) -eq 0) { | |
Write-Host ("[Info] Waiting for OpenSSH services to start...") -ForegroundColor DarkGray | |
} | |
Start-Sleep -Seconds 1 | |
if ($interval -gt 60) { | |
Throw "Error starting OpenSSH services, exiting..." | |
} | |
} | |
# Retrieve current ip address of Sandbox from $global:VSCodeSandboxPath\.setup\sandbox_ip | |
$sandbox_ip = Get-Content $global:VSCodeSandboxPath\.setup\sandbox_ip | |
# If ip address is not in the 172.0.0.0/8 range, exit | |
if ($sandbox_ip -notmatch "^172\.\d{1,3}\.\d{1,3}\.\d{1,3}$") { | |
Throw "Error retrieving Sandbox IP address, exiting..." | |
} | |
Write-Host ("[OK] Installation done, continuing...") -ForegroundColor Green | |
# Check if .ssh\config file exists, if not create it | |
if (-not (Test-Path -Path $env:UserProfile\.ssh\config)) { | |
New-Item -ItemType File -Path $env:UserProfile\.ssh\config | Out-Null | |
} | |
try { | |
$newConfig = @" | |
# Auto-generated by vscode_sandbox.ps1 - Version $global:VSCodeSandboxVersion | |
# Last updated: $(Get-Date -Format "yyyy-MM-dd HH:mm:ss") | |
# !!! - Do not edit this section manually - !!! | |
Host sandbox | |
User WDAGUtilityAccount | |
CheckHostIP no | |
Hostname $sandbox_ip | |
StrictHostKeyChecking no | |
UserKnownHostsFile /dev/null | |
PreferredAuthentications publickey | |
IdentityFile $env:UserProfile\.ssh\id_ed25519_vscode | |
"@ | |
$configPath = "$env:UserProfile\.ssh\config" | |
$configContent = Get-Content -Path $configPath -Raw | |
$pattern = "(?m)((?:^#.*$[\r\n]){3}Host sandbox[\r\n\s\S]+?)(?=(?:[\r\n\s]+^Host)|[\r\n\s]+\z)" | |
# Use regex to check if the configuration already exists | |
$configExists = $configContent -match $pattern | |
if ($configExists -and (Get-Variable Matches)) { | |
# Replace the existing configuration | |
$configContent = $configContent.Replace($Matches[0], "$newConfig") | |
} | |
else { | |
# Append the new configuration | |
$configContent += "`n$newConfig" | |
} | |
$configContent.TrimEnd() | Set-Content -Path "$configPath" | |
} | |
catch { | |
Write-Host ("[Error] $($_.Exception.Message)") -ForegroundColor Red | |
Throw "Error updating $env:UserProfile\.ssh\config file, exiting..." | |
} | |
# Start new VSCode session to Sandbox using SSH key | |
Write-Host ("[Info] Connecting to Windows Sandbox at $sandbox_ip...") -ForegroundColor DarkGray | |
& (Get-Command -Name code).Source --profile Sandbox --remote ssh-remote+WDAGUtilityAccount@sandbox $global:VSCodeSandboxPathWorkspaceRemote | |
} | |
catch { | |
Write-Host "[Error] $($_.Exception.Message)" -ForegroundColor Red | |
# Get sandbox process and kill it | |
$sandboxProcess = Get-Process -Name WindowsSandboxClient -ErrorAction SilentlyContinue | |
if ($sandboxProcess) { | |
Write-Host ("[Info] Killing Windows Sandbox process...") -ForegroundColor DarkGray | |
$sandboxProcess | Stop-Process -Force:$true -Confirm:$false | |
} | |
exit 1 | |
} |
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 |
# Title: Windows 11 Deployment Script | |
# Filename: win11.ps1 | |
# Author: B. van Wetten | |
# Description: Deployment script for Windows 11 that also performs | |
# some basic configuration and removes Windows bloatware. | |
# Last Update: 2024-01-07 | |
# | |
# Prerequisites: See: https://gist.github.com/QNimbus/83a86ee072d2b4dbfd13f2fe901796df#file-provisioning-md | |
# | |
# Download only: Invoke-WebRequest -Uri https://gist.githubusercontent.com/QNimbus/83a86ee072d2b4dbfd13f2fe901796df/raw/scripts---win11.ps1 -OutFile $env:userprofile\Downloads\win11.ps1 | |
# Usage (bootstrap): PowerShell.exe -ExecutionPolicy Bypass { Invoke-RestMethod -Uri https://gist.githubusercontent.com/QNimbus/83a86ee072d2b4dbfd13f2fe901796df/raw/scripts---bootstrap.ps1 | Invoke-Expression } | |
# Start of script | |
Using module .\lib\utils.psm1 | |
Set-StrictMode -Version 1.0 | |
Set-Variable -Name ProgressPreference -Value "SilentlyContinue" # Default is "Continue" | |
Set-Variable -Name ErrorActionPreference -Value "Continue" # Default is "Continue" | |
$global:InstallWinGet = $true | |
$global:CreateTaskbarLayout = $true | |
[Main]::Start() | |
class Main { | |
static [void] Start() { | |
try { | |
$global:errorOccurred = $true | |
# Check to make sure script is run as administrator | |
Write-Host "[Info] Checking if script is running as administrator..." -ForegroundColor Blue | |
$currentPrincipal = New-Object Security.Principal.WindowsPrincipal( [Security.Principal.WindowsIdentity]::GetCurrent() ) | |
if (-Not $currentPrincipal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) { | |
Throw "Script must be run as administrator" | |
} | |
# Winget installation (disabled) | |
if ($global:InstallWinGet) { | |
# Install WinGet | |
Write-Host "[Info] Downloading WinGet and its dependencies..." -ForegroundColor Blue | |
# Check if WinGet is already installed | |
try { | |
$wingetCommand = Get-Command winget -ErrorAction Stop | |
Write-Host "[Info] winget.exe is already installed." -ForegroundColor Blue | |
} | |
catch { | |
Write-Host "[Info] winget.exe is not installed. Installing..." -ForegroundColor Blue | |
# Download WinGet and its dependencies | |
[Utils]::DownloadFile("https://aka.ms/getwinget", "${env:USERPROFILE}\Downloads", "Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.msixbundle") | |
[Utils]::DownloadFile("https://aka.ms/Microsoft.VCLibs.x64.14.00.Desktop.appx", "${env:USERPROFILE}\Downloads") | |
[Utils]::DownloadFile("https://github.com/microsoft/microsoft-ui-xaml/releases/download/v2.7.3/Microsoft.UI.Xaml.2.7.x64.appx", "${env:USERPROFILE}\Downloads") | |
Start-Process -FilePath "powershell.exe" -NoNewWindow -Wait -ArgumentList "-NoProfile { `$ProgressPreference = `"SilentlyContinue`"; Add-AppxPackage `$args[0] } -args `"${env:USERPROFILE}\Downloads\Microsoft.UI.Xaml.2.7.x64.appx`"" | Out-Null | |
Start-Process -FilePath "powershell.exe" -NoNewWindow -Wait -ArgumentList "-NoProfile { `$ProgressPreference = `"SilentlyContinue`"; Add-AppxPackage `$args[0] } -args `"${env:USERPROFILE}\Downloads\Microsoft.VCLibs.x64.14.00.Desktop.appx`"" | Out-Null | |
Start-Process -FilePath "powershell.exe" -NoNewWindow -Wait -ArgumentList "-NoProfile { `$ProgressPreference = `"SilentlyContinue`"; Add-AppxPackage `$args[0] } -args `"${env:USERPROFILE}\Downloads\Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.msixbundle`"" | Out-Null | |
} | |
Write-Host "[Info] Updating WinGet repository..." -ForegroundColor Blue | |
winget.exe source update *> $null | |
} | |
Write-Host "[Info] Removing bloatware" -ForegroundColor Blue | |
if ( -Not [Bloatware]::Remove() ) { | |
Write-Host "[Error] Failed to remove bloatware" -ForegroundColor Red | |
} | |
Write-Host "[Info] Installing apps" -ForegroundColor Blue | |
if ( -Not [Apps]::Install() ) { | |
Write-Host "[Error] Failed to install apps" -ForegroundColor Red | |
} | |
Write-Host "[Info] Enabling Windows features" -ForegroundColor Blue | |
if ( -Not [WindowsFeatures]::Enable() ) { | |
Write-Host "[Error] Failed to enable Windows features" -ForegroundColor Red | |
} | |
Write-Host "[Info] Configuring Windows services" -ForegroundColor Blue | |
if ( -Not [WindowsServices]::Configure() ) { | |
Write-Host "[Error] Failed to configure Windows services" -ForegroundColor Red | |
} | |
Write-Host "[Info] Setting up Windows Subsystem for Linux (WSL2)" -ForegroundColor Blue | |
if ( -Not [WSL2]::Setup() ) { | |
Write-Host "[Error] Failed to set up WSL2" -ForegroundColor Red | |
} | |
Write-Host "[Info] Configuring Windows registry" -ForegroundColor Blue | |
if ( -Not [Registry]::ConfigureWindows() ) { | |
Write-Host "[Error] Failed to configure Windows registry" -ForegroundColor Red | |
} | |
Write-Host "[Info] Configuring network profile (Private)" -ForegroundColor Blue | |
Set-NetConnectionProfile -InterfaceAlias $(Get-NetConnectionProfile).InterfaceAlias -NetworkCategory "Private" | |
Write-Host "[Info] Performing cleanup" -ForegroundColor Blue | |
$list = @( | |
@{path = "C:\Dell"; recursive = $True}, | |
@{path = "C:\Intel"; recursive = $True}, | |
@{path = "C:\PerfLogs"; recursive = $True} | |
) | |
[Utils]::RemoveFiles($list) | |
Write-Host "[Info] Restarting explorer.exe" -ForegroundColor Blue | |
[Utils]::RestartExplorer() | |
$global:errorOccurred = $false | |
} | |
catch { | |
Write-Host "[Error] $_" -ForegroundColor Red | |
} | |
finally { | |
if ($global:errorOccurred) { | |
# Wait for user input | |
[Utils]::Pause("Press any key to exit") | |
} | |
else { | |
[Utils]::Pause("Press any key to exit", 3) | |
} | |
} | |
} | |
} | |
class Bloatware { | |
static [string[]] $list = @( | |
"MicrosoftTeams" | |
"Microsoft.WindowsAlarms" | |
"Microsoft.windowscommunicationsapps" | |
"Microsoft.Todos" | |
"Microsoft.BingFinance" | |
"Microsoft.3DBuilder" | |
"Microsoft.BingNews" | |
"Microsoft.BingSports" | |
"Microsoft.BingWeather" | |
"Microsoft.CommsPhone" | |
"Microsoft.Getstarted" | |
"Microsoft.WindowsMaps" | |
"*MarchofEmpires*" | |
"Microsoft.GetHelp" | |
"Microsoft.Messaging" | |
"*Minecraft*" | |
"Microsoft.OutlookForWindows" | |
"Microsoft.MicrosoftOfficeHub" | |
"Microsoft.OneConnect" | |
"Microsoft.WindowsPhone" | |
"Microsoft.Windows.Photos" | |
"Microsoft.WindowsSoundRecorder" | |
"*Solitaire*" | |
"Microsoft.MicrosoftStickyNotes" | |
"Microsoft.Office.Sway" | |
"Microsoft.XboxApp" | |
"Microsoft.XboxIdentityProvider" | |
"Microsoft.ZuneMusic" | |
"Microsoft.ZuneVideo" | |
"Microsoft.NetworkSpeedTest" | |
"Microsoft.FreshPaint" | |
"Microsoft.Print3D" | |
"Microsoft.People*" | |
"Microsoft.Microsoft3DViewer" | |
"Microsoft.MixedReality.Portal*" | |
"Clipchamp.Clipchamp" | |
"*Skype*" | |
"*Autodesk*" | |
"*BubbleWitch*" | |
"king.com*" | |
"G5*" | |
"*Dell*" | |
"*Facebook*" | |
"*Keeper*" | |
"*Netflix*" | |
"*Twitter*" | |
"*Plex*" | |
# "XBox*" | |
# "Microsoft.XboxGameOverlay" | |
# "Microsoft.XboxGamingOverlay" | |
) | |
static [bool] Remove() { | |
try { | |
foreach ($app in [Bloatware]::list) { | |
if ([Utils]::RemoveApp($app)) { | |
Write-Host "[OK] Removed $app" -ForegroundColor Green | |
} else { | |
Write-Host "[Error] Failed to remove $app" -ForegroundColor Red | |
} | |
} | |
return $true | |
} catch { | |
Write-Host "[Error] Error: $_" -ForegroundColor Red | |
return $false | |
} | |
} | |
} | |
class Apps { | |
static [hashtable[]] $list = @( | |
@{id = "Git.Git" }, | |
@{id = "gerardog.gsudo" }, | |
@{id = "Microsoft.VisualStudioCode" }, | |
@{id = "Microsoft.WindowsTerminal" }, | |
@{id = "GPSoftware.DirectoryOpus" }, | |
@{id = "RoyalApps.RoyalTS.V7" }, | |
@{id = "Docker.DockerDesktop" }, | |
@{id = "tailscale.tailscale" }, | |
@{id = "WireGuard.WireGuard" }, | |
@{id = "AgileBits.1Password" }, | |
@{id = "AgileBits.1Password.CLI" }, | |
@{id = "evernote.evernote" }, | |
@{id = "eMClient.eMClient" }, | |
@{id = "Valve.Steam" }, | |
@{id = "TechPowerUp.NVCleanstall" }, | |
@{id = "KurtZimmermann.RegCool" }, | |
@{id = "9NKSQGP7F2NH"; name = "WhatsApp" } | |
# @{id = "JanDeDobbeleer.OhMyPosh" }, | |
# @{id = "EpicGames.EpicGamesLauncher" } | |
# @{id = "Microsoft.Office"; override = "/configure ""C:\Users\bas\Downloads\Office 365 config.xml""" } | |
# @{id = "9PD11RQ8QC9K"; name = "Dell Power Manager" } | |
# @{id = "Microsoft.PowerShell" }, | |
# @{id = "Spotify.Spotify"; asUser = $true } | |
) | |
static [bool] Install() { | |
try { | |
foreach ($app in [Apps]::list) { | |
if ($app.id) { | |
$appName = $app.id | |
} else { | |
$appName = $app.name | |
} | |
if ($app.name) { | |
$appDisplayName = $app.name | |
} else { | |
$appDisplayName = $app.id | |
} | |
$listApp = $(winget list --exact -q "$appName") | |
if (![String]::Join("", $listApp).Contains($appName)) { | |
if ( -Not $app.asUser) { | |
Write-Host "[Info] Attempting to install globally '$($appDisplayName)' " -NoNewline -ForegroundColor Blue | |
if ($app.override) { | |
winget install -h --accept-source-agreements --accept-package-agreements "$appName" --override "$($app.override)" | Out-Null | |
} else { | |
winget install -h --accept-source-agreements --accept-package-agreements "$appName" | Out-Null | |
} | |
if ($?) { | |
Write-Host "success" -ForegroundColor Green | |
} else { | |
Write-Host "failed" -ForegroundColor Red | |
} | |
} else { | |
Write-Host "`[Info] Attempting to install '$($appDisplayName)' for user '$([System.Environment]::UserName)' " -NoNewline -ForegroundColor Blue | |
$credential = Get-WinCredential -Title $($appDisplayName) -Message "Please provide credentials for installation" -UserName $([System.Environment]::UserName) | |
$result = Start-Job -Credential $credential -ArgumentList "$appName" -ScriptBlock { | |
param([string] $appName) | |
if ($app.override) { | |
winget install -h --scope user --accept-source-agreements --accept-package-agreements $appName --override "$($app.override)" | Out-Null | |
} else { | |
winget install -h --scope user --accept-source-agreements --accept-package-agreements $appName | Out-Null | |
} | |
return [bool] $? | |
} | Wait-Job | Receive-Job | |
if ([bool] $result) { | |
Write-Host "success" -ForegroundColor Green | |
} else { | |
Write-Host "failed" -ForegroundColor Red | |
} | |
} | |
} else { | |
Write-host "[Info] Already installed, skipping '$($appDisplayName)'" -ForegroundColor Blue | |
} | |
} | |
return $true | |
} catch { | |
Write-Host "[Error] Error: $_" -ForegroundColor Red | |
return $false | |
} | |
} | |
} | |
class WindowsFeatures { | |
static [hashtable[]] $list = @( | |
@{name = "OpenSSH.Client~~~~0.0.1.0"; isCapability = $True }, | |
@{name = "OpenSSH.Server~~~~0.0.1.0"; isCapability = $True }, | |
@{name = "NetFx3" }, | |
@{name = "VirtualMachinePlatform" }, | |
@{name = "Microsoft-Windows-Subsystem-Linux" }, | |
@{name = "Containers-DisposableClientVM" } | |
); | |
static [bool] Enable() { | |
try { | |
foreach ($feature in [WindowsFeatures]::list) { | |
if ($($feature.isCapability)) { | |
If ((Get-WindowsCapability -Online -Name $($feature.name)).State -ne 'Installed') { | |
Write-Host "[Info] Attempting to install Windows capability '$($feature.name)'" -ForegroundColor Blue | |
Add-WindowsCapability -Online -Name $($feature.name) | |
} else { | |
Write-Host "[Info] Windows capability '$($feature.name)' already installed" -ForegroundColor Blue | |
} | |
} else { | |
If ((Get-WindowsOptionalFeature -Online -FeatureName $($feature.name)).State -ne 'Enabled') { | |
Write-Host "[Info] Attempting to enable Windows optional feature '$($feature.name)'" -ForegroundColor Blue | |
Enable-WindowsOptionalFeature -Online -FeatureName $($feature.name) -All -NoRestart -ErrorAction SilentlyContinue | |
} else { | |
Write-Host "[Info] Windows optional feature '$($feature.name)' already enabled" -ForegroundColor Blue | |
} | |
} | |
} | |
return $True | |
} catch { | |
Write-Host $_ | |
return $False | |
} | |
} | |
} | |
class Registry { | |
static [hashtable[]] $list = @( | |
@{name = "HideTaskbarSearch" } | |
@{name = "DisableTelemetry" } | |
@{name = "DisableEdgeHubSidebar" } | |
@{name = "DisableWebSearch" } | |
@{name = "DisableMapUpdates" } | |
@{name = "HideChatIcon" } | |
@{name = "DisableWindowsWidgets" } | |
@{name = "SetLongDateFormat" } | |
@{name = "SetShortDateFormat" } | |
) | |
static [bool] ConfigureWindows() { | |
try { | |
foreach ($method in [Registry]::list) { | |
try { | |
$expr = "[Registry]::$($method.name)()" | |
Invoke-Expression $expr | |
} catch { | |
Write-Host "[Error] Unable to invoke static method [Registry]::$($method.name)()" -ForegroundColor Red | |
} | |
} | |
# Write-Host "[Info] Restore pinned taskbar icons..." -ForegroundColor Blue | |
# [Utils]::RestorePinnedTaskbarIcons() | |
# Create appropriate taskbar layout (enabled) | |
if ($global:CreateTaskbarLayout) { | |
# <?xml version="1.0" encoding="utf-8"?> | |
# <LayoutModificationTemplate | |
# xmlns="http://schemas.microsoft.com/Start/2014/LayoutModification" | |
# xmlns:defaultlayout="http://schemas.microsoft.com/Start/2014/FullDefaultLayout" | |
# xmlns:start="http://schemas.microsoft.com/Start/2014/StartLayout" | |
# xmlns:taskbar="http://schemas.microsoft.com/Start/2014/TaskbarLayout" | |
# Version="1"> | |
# <CustomTaskbarLayoutCollection> | |
# <defaultlayout:TaskbarLayout> | |
# <taskbar:TaskbarPinList> | |
# <taskbar:DesktopApp DesktopApplicationID="Microsoft.Windows.Explorer" /> | |
# <taskbar:DesktopApp DesktopApplicationID="Microsoft.Windows.Terminal" /> | |
# <taskbar:DesktopApp DesktopApplicationLinkPath="%PROGRAMDATA%\Microsoft\Windows\Start Menu\Programs\Microsoft Edge.lnk" /> | |
# </taskbar:TaskbarPinList> | |
# </defaultlayout:TaskbarLayout> | |
# </CustomTaskbarLayoutCollection> | |
# </LayoutModificationTemplate> | |
Write-Host "[Info] Creating taskbar layout" -ForegroundColor Blue | |
$taskbarLayoutModificationFileData = 'PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4NCjxMYXlvdXRNb2RpZmljYXRpb25UZW1wbGF0ZQ0KICAgIHhtbG5zPSJodHRwOi8vc2NoZW1hcy5taWNyb3NvZnQuY29tL1N0YXJ0LzIwMTQvTGF5b3V0TW9kaWZpY2F0aW9uIg0KICAgIHhtbG5zOmRlZmF1bHRsYXlvdXQ9Imh0dHA6Ly9zY2hlbWFzLm1pY3Jvc29mdC5jb20vU3RhcnQvMjAxNC9GdWxsRGVmYXVsdExheW91dCINCiAgICB4bWxuczpzdGFydD0iaHR0cDovL3NjaGVtYXMubWljcm9zb2Z0LmNvbS9TdGFydC8yMDE0L1N0YXJ0TGF5b3V0Ig0KICAgIHhtbG5zOnRhc2tiYXI9Imh0dHA6Ly9zY2hlbWFzLm1pY3Jvc29mdC5jb20vU3RhcnQvMjAxNC9UYXNrYmFyTGF5b3V0Ig0KICAgIFZlcnNpb249IjEiPg0KICA8Q3VzdG9tVGFza2JhckxheW91dENvbGxlY3Rpb24+DQogICAgPGRlZmF1bHRsYXlvdXQ6VGFza2JhckxheW91dD4NCiAgICAgIDx0YXNrYmFyOlRhc2tiYXJQaW5MaXN0Pg0KICAgICAgICA8dGFza2JhcjpEZXNrdG9wQXBwIERlc2t0b3BBcHBsaWNhdGlvbklEPSJNaWNyb3NvZnQuV2luZG93cy5FeHBsb3JlciIgLz4NCiAgICAgICAgPHRhc2tiYXI6RGVza3RvcEFwcCBEZXNrdG9wQXBwbGljYXRpb25JRD0iTWljcm9zb2Z0LldpbmRvd3MuVGVybWluYWwiIC8+DQogICAgICAgIDx0YXNrYmFyOkRlc2t0b3BBcHAgRGVza3RvcEFwcGxpY2F0aW9uTGlua1BhdGg9IiVQUk9HUkFNREFUQSVcTWljcm9zb2Z0XFdpbmRvd3NcU3RhcnQgTWVudVxQcm9ncmFtc1xNaWNyb3NvZnQgRWRnZS5sbmsiIC8+DQogICAgICA8L3Rhc2tiYXI6VGFza2JhclBpbkxpc3Q+DQogICAgPC9kZWZhdWx0bGF5b3V0OlRhc2tiYXJMYXlvdXQ+DQogPC9DdXN0b21UYXNrYmFyTGF5b3V0Q29sbGVjdGlvbj4NCjwvTGF5b3V0TW9kaWZpY2F0aW9uVGVtcGxhdGU+DQo=' | |
[Utils]::SetTaskbarLayout("$env:UserProfile", $taskbarLayoutModificationFileData) | |
} | |
Write-Host "[Info] Restore desktop icons..." -ForegroundColor Blue | |
[DesktopIcons]::RestoreDesktopIcons() | |
Write-Host "[Info] Setting other registry values..." -ForegroundColor Blue | |
[Utils]::RestoreRegistry([OtherRegistrySettings]::registry) | |
return $true | |
} catch { | |
Write-Error $_ | |
return $false | |
} | |
} | |
static [void] HideTaskbarSearch() { | |
Write-Host "[Info] Hiding Taskbar Search box / button..." -ForegroundColor Blue | |
Set-ItemProperty -Path "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Search" -Name "SearchboxTaskbarMode" -Type DWord -Value 0 | |
} | |
static [void] ShowTaskbarSearchIcon() { | |
Write-Host "[Info] Showing Taskbar Search icon..." -ForegroundColor Blue | |
Set-ItemProperty -Path "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Search" -Name "SearchboxTaskbarMode" -Type DWord -Value 1 | |
} | |
static [void] ShowTaskbarSearchBox() { | |
Write-Host "[Info] Showing Taskbar Search box..." -ForegroundColor Blue | |
Set-ItemProperty -Path "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Search" -Name "SearchboxTaskbarMode" -Type DWord -Value 2 | |
} | |
# Disable Telemetry | |
static [void] DisableTelemetry() { | |
Write-Host "[Info] Disabling Telemetry..." -ForegroundColor Blue | |
Set-ItemProperty -Path "HKLM:\Software\Microsoft\Windows\CurrentVersion\Policies\DataCollection" -Name "AllowTelemetry" -Type DWord -Value 0 | |
Set-ItemProperty -Path "HKLM:\Software\Policies\Microsoft\Windows\DataCollection" -Name "AllowTelemetry" -Type DWord -Value 0 | |
Set-ItemProperty -Path "HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Policies\DataCollection" -Name "AllowTelemetry" -Type DWord -Value 0 | |
Set-ItemProperty -Path "HKCU:\Software\Policies\Microsoft\Windows\CloudContent" -Name "DisableTailoredExperiencesWithDiagnosticData" -Type DWord -Value 0 | |
Get-ScheduledTask -TaskPath "\Microsoft\Windows\Application Experience\" -TaskName "Microsoft Compatibility Appraiser" -ErrorAction SilentlyContinue | Disable-ScheduledTask | Out-Null | |
Get-ScheduledTask -TaskPath "\Microsoft\Windows\Application Experience\" -TaskName "ProgramDataUpdater" -ErrorAction SilentlyContinue | Disable-ScheduledTask | Out-Null | |
Get-ScheduledTask -TaskPath "\Microsoft\Windows\Autochk\" -TaskName "Proxy" -ErrorAction SilentlyContinue | Disable-ScheduledTask | Out-Null | |
Get-ScheduledTask -TaskPath "\Microsoft\Windows\Customer Experience Improvement Program\" -TaskName "Consolidator" -ErrorAction SilentlyContinue | Disable-ScheduledTask | Out-Null | |
Get-ScheduledTask -TaskPath "\Microsoft\Windows\Customer Experience Improvement Program\" -TaskName "UsbCeip" -ErrorAction SilentlyContinue | Disable-ScheduledTask | Out-Null | |
Get-ScheduledTask -TaskPath "\Microsoft\Windows\DiskDiagnostic\" -TaskName "Microsoft-Windows-DiskDiagnosticDataCollector" -ErrorAction SilentlyContinue | Disable-ScheduledTask | Out-Null | |
} | |
# Enable Telemetry | |
static [void] EnableTelemetry() { | |
Write-Host "[Info] Enabling Telemetry..." -ForegroundColor Blue | |
Set-ItemProperty -Path "HKLM:\Software\Microsoft\Windows\CurrentVersion\Policies\DataCollection" -Name "AllowTelemetry" -Type DWord -Value 3 | |
Set-ItemProperty -Path "HKLM:\Software\Policies\Microsoft\Windows\DataCollection" -Name "AllowTelemetry" -Type DWord -Value 3 | |
Set-ItemProperty -Path "HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Policies\DataCollection" -Name "AllowTelemetry" -Type DWord -Value 3 | |
Set-ItemProperty -Path "HKCU:\Software\Policies\Microsoft\Windows\CloudContent" -Name "DisableTailoredExperiencesWithDiagnosticData" -Type DWord -Value 1 | |
Get-ScheduledTask -TaskPath "\Microsoft\Windows\Application Experience\" -TaskName "Microsoft Compatibility Appraiser" -ErrorAction SilentlyContinue | Enable-ScheduledTask | Out-Null | |
Get-ScheduledTask -TaskPath "\Microsoft\Windows\Application Experience\" -TaskName "ProgramDataUpdater" -ErrorAction SilentlyContinue | Enable-ScheduledTask | Out-Null | |
Get-ScheduledTask -TaskPath "\Microsoft\Windows\Autochk\" -TaskName "Proxy" -ErrorAction SilentlyContinue | Enable-ScheduledTask | Out-Null | |
Get-ScheduledTask -TaskPath "\Microsoft\Windows\Customer Experience Improvement Program\" -TaskName "Consolidator" -ErrorAction SilentlyContinue | Enable-ScheduledTask | Out-Null | |
Get-ScheduledTask -TaskPath "\Microsoft\Windows\Customer Experience Improvement Program\" -TaskName "UsbCeip" -ErrorAction SilentlyContinue | Enable-ScheduledTask | Out-Null | |
Get-ScheduledTask -TaskPath "\Microsoft\Windows\DiskDiagnostic\" -TaskName "Microsoft-Windows-DiskDiagnosticDataCollector" -ErrorAction SilentlyContinue | Enable-ScheduledTask | Out-Null | |
} | |
# Disable Web Search in Start Menu | |
static [void] DisableWebSearch() { | |
Write-Host "[Info] Disabling Bing Search in Start Menu..." -ForegroundColor Blue | |
Set-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Search" -Name "BingSearchEnabled" -Type DWord -Value 0 | |
If (!(Test-Path "HKLM:\Software\Policies\Microsoft\Windows\Windows Search")) { | |
New-Item -Path "HKLM:\Software\Policies\Microsoft\Windows\Windows Search" -Force | Out-Null | |
} | |
Set-ItemProperty -Path "HKLM:\Software\Policies\Microsoft\Windows\Windows Search" -Name "DisableWebSearch" -Type DWord -Value 1 | |
} | |
# Enable Web Search in Start Menu | |
static [void] EnableWebSearch() { | |
Write-Host "[Info] Enabling Bing Search in Start Menu..." -ForegroundColor Blue | |
Remove-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Search" -Name "BingSearchEnabled" -ErrorAction SilentlyContinue | |
Remove-ItemProperty -Path "HKLM:\Software\Policies\Microsoft\Windows\Windows Search" -Name "DisableWebSearch" -ErrorAction SilentlyContinue | |
} | |
# Disable Edge HubSidebar | |
static [void] DisableEdgeHubSidebar() { | |
Write-Host "[Info] Disabling Edge Hub Sidebar..." -ForegroundColor Blue | |
If (!(Test-Path "HKLM:\Software\Policies\Microsoft\Edge")) { | |
New-Item -Path "HKLM:\Software\Policies\Microsoft\Edge" -Force | Out-Null | |
} | |
Set-ItemProperty -Path "HKLM:\Software\Policies\Microsoft\Edge" -Name "HubsSidebarEnabled" -Type DWord -Value 0 | |
} | |
# Enable Edge HubSidebar | |
static [void] EnableEdgeHubSidebar() { | |
Write-Host "[Info] Enabling Edge Hub Sidebar..." -ForegroundColor Blue | |
If (!(Test-Path "HKLM:\Software\Policies\Microsoft\Edge")) { | |
New-Item -Path "HKLM:\Software\Policies\Microsoft\Edge" -Force | Out-Null | |
} | |
Set-ItemProperty -Path "HKLM:\Software\Policies\Microsoft\Edge" -Name "HubsSidebarEnabled" -Type DWord -Value 1 | |
} | |
# Disable Windows 11 widgets | |
static [void] DisableWindowsWidgets() { | |
Write-Host "[Info] Disabling Windows 11 widgets..." -ForegroundColor Blue | |
Set-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced" -Name "TaskbarDa" -Type DWord -Value 0 | |
} | |
# Enable Windows 11 widgets | |
static [void] EnableWindowsWidgets() { | |
Write-Host "[Info] Enabling Windows 11 widgets..." -ForegroundColor Blue | |
Set-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced" -Name "TaskbarDa" -Type DWord -Value 1 | |
} | |
# Disable automatic Maps updates | |
static [void] DisableMapUpdates() { | |
Write-Host "[Info] Disabling automatic Maps updates..." -ForegroundColor Blue | |
Set-ItemProperty -Path "HKLM:\SYSTEM\Maps" -Name "AutoUpdateEnabled" -Type DWord -Value 0 | |
} | |
# Enable automatic Maps updates | |
static [void] EnableMapUpdates() { | |
Write-Host "[Info] Enabling automatic Maps updates..." -ForegroundColor Blue | |
Remove-ItemProperty -Path "HKLM:\SYSTEM\Maps" -Name "AutoUpdateEnabled" -ErrorAction SilentlyContinue | |
} | |
# Hide chat icon | |
static [void] HideChatIcon() { | |
Write-Host "[Info] Hiding taskbar Chat icon..." -ForegroundColor Blue | |
Set-ItemProperty -Path "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced" -Name "TaskbarMn" -Type DWord -Value 0 | |
Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows" -Name "ChatIcon" -Type DWord -Value 0x03 | |
} | |
# Show chat icon | |
static [void] ShowChatIcon() { | |
Write-Host "[Info] Showing taskbar Chat icon..." -ForegroundColor Blue | |
Set-ItemProperty -Path "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced" -Name "TaskbarMn" -Type DWord -Value 1 | |
Remove-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows" -Name "ChatIcon" -ErrorAction SilentlyContinue | |
} | |
# Disable Windows Desktop Spotlight (DisableWindowsSpotlightFeatures) | |
static [void] DisableWindowsSpotlightFeatures() { | |
Write-Host "[Info] Disabling Windows Desktop Spotlight..." -ForegroundColor Blue | |
Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\CloudContent" -Name "DisableWindowsSpotlightFeatures" -Type DWord -Value 1 | |
} | |
# Enable Windows Desktop Spotlight (DisableWindowsSpotlightFeatures) | |
static [void] EnableWindowsSpotlightFeatures() { | |
Write-Host "[Info] Enabling Windows Desktop Spotlight..." -ForegroundColor Blue | |
Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\CloudContent" -Name "DisableWindowsSpotlightFeatures" -Type DWord -Value 0 | |
} | |
# Enable 'show file extensions' option | |
static [void] ShowFileExtensions() { | |
Write-Host "[Info] Enabling 'show file extensions' option..." -ForegroundColor Blue | |
Set-ItemProperty -Path "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced" -Name "HideFileExt" -Type DWord -Value 0 | |
} | |
# Disable 'show file extensions' option | |
static [void] HideFileExtensions() { | |
Write-Host "[Info] Disabling 'show file extensions' option..." -ForegroundColor Blue | |
Set-ItemProperty -Path "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced" -Name "HideFileExt" -Type DWord -Value 1 | |
} | |
static [void] SetShortTimeFormat() { | |
Write-Host "[Info] Setting short time format (HH:mm:ss)..." -ForegroundColor Blue | |
Set-ItemProperty -Path "HKCU:\Control Panel\International" -name sShortTime -value "hh:mm:ss" | |
} | |
static [void] SetLongTimeFormat() { | |
Write-Host "[Info] Setting long time format (HH:mm:ss)..." -ForegroundColor Blue | |
Set-ItemProperty -Path "HKCU:\Control Panel\International" -name sTimeFormat -value "hh:mm:ss" | |
} | |
static [void] SetLongDateFormat() { | |
Write-Host "[Info] Setting long date format (dddd, MMMM d, yyyy)..." -ForegroundColor Blue | |
Set-ItemProperty -Path "HKCU:\Control Panel\International" -name sLongDate -value "dddd, MMMM d, yyyy" | |
} | |
static [void] SetShortDateFormat() { | |
Write-Host "[Info] Setting short date format (d-M-yyyy)..." -ForegroundColor Blue | |
Set-ItemProperty -Path "HKCU:\Control Panel\International" -name sShortDate -value "d-M-yyyy" | |
} | |
} | |
class WindowsServices { | |
static [hashtable[]] $list = @( | |
@{name = "ssh-agent"; startupType = "disabled"; start = $False } | |
@{name = "KAPSService"; startupType = "disabled"; start = $False } | |
@{name = "Killer Analytics Service"; startupType = "disabled"; start = $False } | |
@{name = "Killer Network Service"; startupType = "disabled"; start = $False } | |
@{name = "KNDBWM"; startupType = "disabled"; start = $False } | |
) | |
static [bool] Configure() { | |
try { | |
foreach ($service in [WindowsServices]::list) { | |
$displayName = $(Get-service -Name $service.name).DisplayName | |
if ($?) { | |
Set-Service $service.name -StartupType $service.startupType | |
if ($service.start) { | |
Write-Host "[Info] Attempt to start service '$displayName': " -NoNewline -ForegroundColor Blue | |
Start-Service $service.name -WarningAction SilentlyContinue | |
if ($?) { | |
Write-Host "success" -ForegroundColor Green | |
} else { | |
Write-Host "failed" -ForegroundColor Red | |
} | |
} else { | |
Write-Host "[Info] Attempt to stop service '$displayName': " -NoNewline -ForegroundColor Blue | |
Stop-Service $service.name -WarningAction SilentlyContinue | |
if ($?) { | |
Write-Host "success" -ForegroundColor Green | |
} else { | |
Write-Host "failed" -ForegroundColor Red | |
} | |
} | |
} | |
} | |
return $true | |
} catch { | |
return $false | |
} | |
} | |
} | |
class WSL2 { | |
static [bool] Setup() { | |
try { | |
wsl --set-default-version 2 | |
wsl --install --no-launch --distribution Ubuntu-22.04 | |
return $True | |
} catch { | |
return $False | |
} | |
} | |
} | |
class OtherRegistrySettings { | |
<# | |
- Locale registry settings for Dutch (Netherlands) | |
#> | |
static [hashtable[]] $registry = @( | |
@{path = "HKCU:\Control Panel\International\Geo"; name = "Nation"; propertyType = "String"; data = "176" } | |
@{path = "HKCU:\Control Panel\International\Geo"; name = "Name"; propertyType = "String"; data = "NL" } | |
@{path = "HKCU:\Control Panel\International"; name = "Locale"; propertyType = "String"; data = "00000413" } | |
@{path = "HKCU:\Control Panel\International"; name = "LocaleName"; propertyType = "String"; data = "nl-NL" } | |
@{path = "HKCU:\Control Panel\International"; name = "s1159"; propertyType = "String"; data = "" } | |
@{path = "HKCU:\Control Panel\International"; name = "s2359"; propertyType = "String"; data = "" } | |
@{path = "HKCU:\Control Panel\International"; name = "sCurrency"; propertyType = "String"; data = "€" } | |
@{path = "HKCU:\Control Panel\International"; name = "sDate"; propertyType = "String"; data = "-" } | |
@{path = "HKCU:\Control Panel\International"; name = "sDecimal"; propertyType = "String"; data = "," } | |
@{path = "HKCU:\Control Panel\International"; name = "sLanguage"; propertyType = "String"; data = "NLD" } | |
@{path = "HKCU:\Control Panel\International"; name = "sList"; propertyType = "String"; data = ";" } | |
@{path = "HKCU:\Control Panel\International"; name = "sLongDate"; propertyType = "String"; data = "dddd d MMMM yyyy" } | |
@{path = "HKCU:\Control Panel\International"; name = "sMonDecimalSep"; propertyType = "String"; data = "," } | |
@{path = "HKCU:\Control Panel\International"; name = "sMonThousandSep"; propertyType = "String"; data = "." } | |
@{path = "HKCU:\Control Panel\International"; name = "sShortDate"; propertyType = "String"; data = "d-M-yyyy" } | |
@{path = "HKCU:\Control Panel\International"; name = "sThousand"; propertyType = "String"; data = "." } | |
@{path = "HKCU:\Control Panel\International"; name = "iCountry"; propertyType = "String"; data = "31" } | |
@{path = "HKCU:\Control Panel\International"; name = "iCurrency"; propertyType = "String"; data = "2" } | |
@{path = "HKCU:\Control Panel\International"; name = "iFirstWeekOfYear"; propertyType = "String"; data = "2" } | |
@{path = "HKCU:\Control Panel\International"; name = "iNegCurr"; propertyType = "String"; data = "12" } | |
@{path = "HKCU:\Control Panel\International"; name = "sShortTime"; propertyType = "String"; data = "HH:mm" } | |
@{path = "HKCU:\Control Panel\International"; name = "sTimeFormat"; propertyType = "String"; data = "HH:mm:ss" } | |
) | |
} | |
class Taskbar { | |
static [hashtable[]] $registry = @( | |
@{path = "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Taskband"; name = "Favorites"; propertyType = "Binary"; data = "001206000014001f809bd434424502f34db7803893943456e1fc050000fa0441505053e80408000300000000000000780200003153505355284c9f799f394ba8d0e1d42de1d5f36100000011000000001f000000280000004d006900630072006f0073006f00660074002e00570069006e0064006f00770073005400650072006d0069006e0061006c005f003800770065006b0079006200330064003800620062007700650000001100000027000000000b000000ffff0000110000000e00000000130000000200000011000000190000000013000000010000008500000015000000001f000000390000004d006900630072006f0073006f00660074002e00570069006e0064006f00770073005400650072006d0069006e0061006c005f0031002e00310038002e0033003100380031002e0030005f007800360034005f005f003800770065006b00790062003300640038006200620077006500000000006900000005000000001f0000002c0000004d006900630072006f0073006f00660074002e00570069006e0064006f00770073005400650072006d0069006e0061006c005f003800770065006b0079006200330064003800620062007700650021004100700070000000bd0000000f000000001f0000005600000043003a005c00500072006f006700720061006d002000460069006c00650073005c00570069006e0064006f007700730041007000700073005c004d006900630072006f0073006f00660074002e00570069006e0064006f00770073005400650072006d0069006e0061006c005f0031002e00310038002e0033003100380031002e0030005f007800360034005f005f003800770065006b0079006200330064003800620062007700650000001d000000200000000048000000e55f9bd0c945b542a874c452684c8cb400000000cd010000315350534d0bd48669903c44819a2a54090dccec4d0000000c000000001f0000001d00000049006d0061006700650073005c0053007100750061007200650031003500300078003100350030004c006f0067006f002e0070006e006700000000004900000002000000001f0000001b00000049006d0061006700650073005c00530071007500610072006500340034007800340034004c006f0067006f002e0070006e00670000000000490000000d000000001f0000001b00000049006d0061006700650073005c00570069006400650033003100300078003100350030004c006f0067006f002e0070006e00670000000000110000000400000000130000000078d4ff11000000050000000013000000ffffffff3d00000013000000001f0000001500000049006d0061006700650073005c004c006100720067006500540069006c0065002e0070006e00670000000000110000000e0000000013000000a1040000250000000b000000001f000000090000005400650072006d0069006e0061006c00000000003d00000014000000001f0000001500000049006d0061006700650073005c0053006d0061006c006c00540069006c0065002e0070006e00670000000000000000003100000031535053b1166d44ad8d7048a748402ea43d788c15000000640000000015000000f70400000000000000000000410000003153505330f125b7ef471a10a5f102608c9eebac250000000a000000001f000000090000005400650072006d0069006e0061006c0000000000000000002d00000031535053b377ed0d14c66c45ae5b285b38d7b01b110000000700000000130000000000000000000000000000000000120000002b00efbe11da88d7203bda010005640000001d00efbe02004d006900630072006f0073006f00660074002e00570069006e0064006f00770073005400650072006d0069006e0061006c005f003800770065006b00790062003300640038006200620077006500210041007000700000000005220000001e00efbe02005500730065007200500069006e006e006500640000000005640000001d00efbe02004d006900630072006f0073006f00660074002e00570069006e0064006f00770073005400650072006d0069006e0061006c005f003800770065006b00790062003300640038006200620077006500210041007000700000000005000000760100003a001f80c827341f105c1042aa032ee45287d668260001002600efbe12000000053783fdb757d90127e55b24b857d9010bd0b1309a5cd901140056003100000000007556d4a411005461736b42617200400009000400efbe70563d1c7656cc3d2e000000498501000000010000000000000000000000000000001715e0005400610073006b0042006100720000001600e4003200790500007656454520004449524543547e312e4c4e4b0000560009000400efbe76564545765645452e000000e501060000002a0000000000000000000000000000009ae23e004400690072006500630074006f007200790020004f007000750073002e006c006e006b0000001c00120000002b00efbe2b08b3309a5cd9011c00220000001e00efbe02005500730065007200500069006e006e006500640000001c003e0000001d00efbe02004700500053006f006600740077006100720065002e004400690072006500630074006f00720079004f0070007500730000001c00000000520100003a001f80c827341f105c1042aa032ee45287d668260001002600efbe12000000cf27cefc0a3bda0168fa3d2e0b3bda01214f580c213bda01140056003100000000009e57d36811005461736b42617200400009000400efbe9e57c9539e57d3682e000000c2c00100000001000000000000000000000000000000fad900015400610073006b0042006100720000001600c0003200860900009e57935320004d4943524f537e312e4c4e4b0000560009000400efbe9e57ac639e57d9682e000000dc50020000000a000000000000000000000000000000f9762a014d006900630072006f0073006f0066007400200045006400670065002e006c006e006b0000001c00120000002b00efbe214f580c213bda011c00220000001e00efbe02005500730065007200500069006e006e006500640000001c001a0000001d00efbe02004d005300450064006700650000001c00000000500100003a001f80c827341f105c1042aa032ee45287d668260001002600efbe12000000cf27cefc0a3bda0168fa3d2e0b3bda012b82f657263bda01140056003100000000009e57936d11005461736b42617200400009000400efbe9e57c9539e57936d2e000000c2c00100000001000000000000000000000000000000a6be39005400610073006b0042006100720000001600be003200500400009e5703562000454d434c49457e312e4c4e4b00004c0009000400efbe9e575b679e57966d2e000000ad520200000007000000000000000000000000000000ab301b0165004d00200043006c00690065006e0074002e006c006e006b0000001c00120000002b00efbe2b82f657263bda011c00220000001d00efbe02004d00610069006c0043006c00690065006e00740000001c00220000001e00efbe02005500730065007200500069006e006e006500640000001c00000000820100003a001f80c827341f105c1042aa032ee45287d668260001002600efbe12000000cf27cefc0a3bda0168fa3d2e0b3bda01d144ae71263bda01140056003100000000009e57ac6d11005461736b42617200400009000400efbe9e57c9539e57ac6d2e000000c2c001000000010000000000000000000000000000000d7e27005400610073006b0042006100720000001600f0003200800500009e570a55200056495355414c7e312e4c4e4b00005e0009000400efbe9e5733569e57ae6d2e00000013b401000000040000000000000000000000000000009b443600560069007300750061006c002000530074007500640069006f00200043006f00640065002e006c006e006b0000001c00120000002b00efbed144ae71263bda011c00420000001d00efbe02004d006900630072006f0073006f00660074002e00560069007300750061006c00530074007500640069006f0043006f006400650000001c00220000001e00efbe02005500730065007200500069006e006e006500640000001c000000ff" } | |
@{path = "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Taskband"; name = "FavoritesResolve"; propertyType = "Binary"; data = "640600004c0000000114020000000000c0000000000000468100800000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000120614001f809bd434424502f34db7803893943456e1fc050000fa0441505053e80408000300000000000000780200003153505355284c9f799f394ba8d0e1d42de1d5f36100000011000000001f000000280000004d006900630072006f0073006f00660074002e00570069006e0064006f00770073005400650072006d0069006e0061006c005f003800770065006b0079006200330064003800620062007700650000001100000027000000000b000000ffff0000110000000e00000000130000000200000011000000190000000013000000010000008500000015000000001f000000390000004d006900630072006f0073006f00660074002e00570069006e0064006f00770073005400650072006d0069006e0061006c005f0031002e00310038002e0033003100380031002e0030005f007800360034005f005f003800770065006b00790062003300640038006200620077006500000000006900000005000000001f0000002c0000004d006900630072006f0073006f00660074002e00570069006e0064006f00770073005400650072006d0069006e0061006c005f003800770065006b0079006200330064003800620062007700650021004100700070000000bd0000000f000000001f0000005600000043003a005c00500072006f006700720061006d002000460069006c00650073005c00570069006e0064006f007700730041007000700073005c004d006900630072006f0073006f00660074002e00570069006e0064006f00770073005400650072006d0069006e0061006c005f0031002e00310038002e0033003100380031002e0030005f007800360034005f005f003800770065006b0079006200330064003800620062007700650000001d000000200000000048000000e55f9bd0c945b542a874c452684c8cb400000000cd010000315350534d0bd48669903c44819a2a54090dccec4d0000000c000000001f0000001d00000049006d0061006700650073005c0053007100750061007200650031003500300078003100350030004c006f0067006f002e0070006e006700000000004900000002000000001f0000001b00000049006d0061006700650073005c00530071007500610072006500340034007800340034004c006f0067006f002e0070006e00670000000000490000000d000000001f0000001b00000049006d0061006700650073005c00570069006400650033003100300078003100350030004c006f0067006f002e0070006e00670000000000110000000400000000130000000078d4ff11000000050000000013000000ffffffff3d00000013000000001f0000001500000049006d0061006700650073005c004c006100720067006500540069006c0065002e0070006e00670000000000110000000e0000000013000000a1040000250000000b000000001f000000090000005400650072006d0069006e0061006c00000000003d00000014000000001f0000001500000049006d0061006700650073005c0053006d0061006c006c00540069006c0065002e0070006e00670000000000000000003100000031535053b1166d44ad8d7048a748402ea43d788c15000000640000000015000000f70400000000000000000000410000003153505330f125b7ef471a10a5f102608c9eebac250000000a000000001f000000090000005400650072006d0069006e0061006c0000000000000000002d00000031535053b377ed0d14c66c45ae5b285b38d7b01b110000000700000000130000000000000000000000000000000000640000001d00efbe02004d006900630072006f0073006f00660074002e00570069006e0064006f00770073005400650072006d0069006e0061006c005f003800770065006b00790062003300640038006200620077006500210041007000700000000005220000001e00efbe02005500730065007200500069006e006e006500640000000005120000002b00efbe11da88d7203bda010005640000001d00efbe02004d006900630072006f0073006f00660074002e00570069006e0064006f00770073005400650072006d0069006e0061006c005f003800770065006b00790062003300640038006200620077006500210041007000700000000005000000000000080300004c0000000114020000000000c00000000000004683008000200000004645b2309a5cd9012b08b3309a5cd90166bab2309a5cd90179050000000000000100000000000000000000000000000076013a001f80c827341f105c1042aa032ee45287d668260001002600efbe12000000053783fdb757d90127e55b24b857d9010bd0b1309a5cd901140056003100000000007556d4a411005461736b42617200400009000400efbe70563d1c7656cc3d2e000000498501000000010000000000000000000000000000001715e0005400610073006b0042006100720000001600e4003200790500007656454520004449524543547e312e4c4e4b0000560009000400efbe76564545765645452e000000e501060000002a0000000000000000000000000000009ae23e004400690072006500630074006f007200790020004f007000750073002e006c006e006b0000001c00220000001e00efbe02005500730065007200500069006e006e006500640000001c00120000002b00efbe2b08b3309a5cd9011c003e0000001d00efbe02004700500053006f006600740077006100720065002e004400690072006500630074006f00720079004f0070007500730000001c0000009b0000001c000000010000001c0000002d000000000000009a0000001100000003000000f3e6ee6a1000000000433a5c55736572735c6261735c417070446174615c526f616d696e675c4d6963726f736f66745c496e7465726e6574204578706c6f7265725c517569636b204c61756e63685c557365722050696e6e65645c5461736b4261725c4469726563746f7279204f7075732e6c6e6b000060000000030000a058000000000000006c6170746f70000000000000000000003c0f4e300424bb478d1c94f009ee61d308cdd1081dc8ed11bc204c796ed737593c0f4e300424bb478d1c94f009ee61d308cdd1081dc8ed11bc204c796ed7375945000000090000a03900000031535053b1166d44ad8d7048a748402ea43d788c1d000000680000000048000000d15c644bd685944f94138d6eb0ee6668000000000000000000000000e40200004c0000000114020000000000c000000000000046830080002000000011783fd21b3bda01214f580c213bda0107d839f20a3bda0186090000000000000100000000000000000000000000000052013a001f80c827341f105c1042aa032ee45287d668260001002600efbe12000000cf27cefc0a3bda0168fa3d2e0b3bda01214f580c213bda01140056003100000000009e57d36811005461736b42617200400009000400efbe9e57c9539e57d3682e000000c2c00100000001000000000000000000000000000000fad900015400610073006b0042006100720000001600c0003200860900009e57935320004d4943524f537e312e4c4e4b0000560009000400efbe9e57ac639e57d9682e000000dc50020000000a000000000000000000000000000000f9762a014d006900630072006f0073006f0066007400200045006400670065002e006c006e006b0000001c00220000001e00efbe02005500730065007200500069006e006e006500640000001c00120000002b00efbe214f580c213bda011c001a0000001d00efbe02004d005300450064006700650000001c0000009b0000001c000000010000001c0000002d000000000000009a00000011000000030000000071aad41000000000433a5c55736572735c6261735c417070446174615c526f616d696e675c4d6963726f736f66745c496e7465726e6574204578706c6f7265725c517569636b204c61756e63685c557365722050696e6e65645c5461736b4261725c4d6963726f736f667420456467652e6c6e6b000060000000030000a058000000000000006c6170746f7000000000000000000000c08e6f6ba16fa64d8494a43bb12427acf8f035630da7ee11a7e6d0374504eef3c08e6f6ba16fa64d8494a43bb12427acf8f035630da7ee11a7e6d0374504eef345000000090000a03900000031535053b1166d44ad8d7048a748402ea43d788c1d0000006800000000480000006714ec02933fe84687afa5163d9e9559000000000000000000000000dd0200004c0000000114020000000000c0000000000000468300800020000000ada022f11f3bda012b82f657263bda0155c677aa0d3bda0150040000000000000100000000000000000000000000000050013a001f80c827341f105c1042aa032ee45287d668260001002600efbe12000000cf27cefc0a3bda0168fa3d2e0b3bda012b82f657263bda01140056003100000000009e57936d11005461736b42617200400009000400efbe9e57c9539e57936d2e000000c2c00100000001000000000000000000000000000000a6be39005400610073006b0042006100720000001600be003200500400009e5703562000454d434c49457e312e4c4e4b00004c0009000400efbe9e575b679e57966d2e000000ad520200000007000000000000000000000000000000ab301b0165004d00200043006c00690065006e0074002e006c006e006b0000001c00220000001e00efbe02005500730065007200500069006e006e006500640000001c00120000002b00efbe2b82f657263bda011c00220000001d00efbe02004d00610069006c0043006c00690065006e00740000001c000000960000001c000000010000001c0000002d000000000000009500000011000000030000000071aad41000000000433a5c55736572735c6261735c417070446174615c526f616d696e675c4d6963726f736f66745c496e7465726e6574204578706c6f7265725c517569636b204c61756e63685c557365722050696e6e65645c5461736b4261725c654d20436c69656e742e6c6e6b000060000000030000a058000000000000006c6170746f7000000000000000000000c08e6f6ba16fa64d8494a43bb12427ace3f735630da7ee11a7e6d0374504eef3c08e6f6ba16fa64d8494a43bb12427ace3f735630da7ee11a7e6d0374504eef345000000090000a03900000031535053b1166d44ad8d7048a748402ea43d788c1d0000006800000000480000006714ec02933fe84687afa5163d9e9559000000000000000000000000180300004c0000000114020000000000c0000000000000468300800020000000511c63e10d3bda019fa9b071263bda0165bd9a950c3bda0180050000000000000100000000000000000000000000000082013a001f80c827341f105c1042aa032ee45287d668260001002600efbe12000000cf27cefc0a3bda0168fa3d2e0b3bda01d144ae71263bda01140056003100000000009e57ac6d11005461736b42617200400009000400efbe9e57c9539e57ac6d2e000000c2c001000000010000000000000000000000000000000d7e27005400610073006b0042006100720000001600f0003200800500009e570a55200056495355414c7e312e4c4e4b00005e0009000400efbe9e5733569e57ae6d2e00000013b401000000040000000000000000000000000000009b443600560069007300750061006c002000530074007500640069006f00200043006f00640065002e006c006e006b0000001c00220000001e00efbe02005500730065007200500069006e006e006500640000001c00120000002b00efbed144ae71263bda011c00420000001d00efbe02004d006900630072006f0073006f00660074002e00560069007300750061006c00530074007500640069006f0043006f006400650000001c0000009f0000001c000000010000001c0000002d000000000000009e00000011000000030000000071aad41000000000433a5c55736572735c6261735c417070446174615c526f616d696e675c4d6963726f736f66745c496e7465726e6574204578706c6f7265725c517569636b204c61756e63685c557365722050696e6e65645c5461736b4261725c56697375616c2053747564696f20436f64652e6c6e6b000060000000030000a058000000000000006c6170746f7000000000000000000000c08e6f6ba16fa64d8494a43bb12427ac02f835630da7ee11a7e6d0374504eef3c08e6f6ba16fa64d8494a43bb12427ac02f835630da7ee11a7e6d0374504eef345000000090000a03900000031535053b1166d44ad8d7048a748402ea43d788c1d0000006800000000480000006714ec02933fe84687afa5163d9e9559000000000000000000000000" } | |
@{path = "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Taskband"; name = "FavoritesChanges"; propertyType = "DWord"; data = 0x0D } | |
@{path = "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Taskband"; name = "FavoritesVersion"; propertyType = "DWord"; data = 0x03 } | |
) | |
static [hashtable[]] $pinnedItems = @( | |
@{name = "Microsoft Edge"; path = "$env:AppData\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar\Microsoft Edge.lnk"; data = "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" } | |
@{name = "Directory Opus"; path = "$env:AppData\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar\Directory Opus.lnk"; data = "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" } | |
@{name = "eM Client"; path = "$env:AppData\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar\eM Client.lnk"; data = "TAAAAAEUAgAAAAAAwAAAAAAAAEabAAAAIAAAAACie8eJ+9kBwGumqA072gEAonvHifvZAVAGBAAAAAAAAQAAAAAAAAAAAAAAAAAAAI0BFAAfUOBP0CDqOmkQotgIACswMJ0ZAC9DOlwAAAAAAAAAAAAAAAAAAAAAAAAAmAAxAAAAAACeVwFWEQBQUk9HUkF+MgAAgAAJAAQA776nVBornlcBVi4AAAC5BgAAAAABAAAAAAAAAAAAVgAAAAAA8NHDAFAAcgBvAGcAcgBhAG0AIABGAGkAbABlAHMAIAAoAHgAOAA2ACkAAABAAHMAaABlAGwAbAAzADIALgBkAGwAbAAsAC0AMgAxADgAMQA3AAAAGABcADEAAAAAAJ5XA1YQAEVNQ0xJRX4xAABEAAkABADvvp5XAVaeVwNWLgAAAKURBAAAAAEAAAAAAAAAAAAAAAAAAAAtxCEBZQBNACAAQwBsAGkAZQBuAHQAAAAYAGoAMgBQBgQASlfodiAATUFJTENMfjEuRVhFAABOAAkABADvvkpX6HaeVwFWLgAAAPuvAgAAAAMAAAAAAAAAAAAAAAAAAAAAAAAATQBhAGkAbABDAGwAaQBlAG4AdAAuAGUAeABlAAAAHAAAAF4AAAAcAAAAAQAAABwAAAAtAAAAAAAAAF0AAAARAAAAAwAAAABxqtQQAAAAAEM6XFByb2dyYW0gRmlsZXMgKHg4NilcZU0gQ2xpZW50XE1haWxDbGllbnQuZXhlAAA7AC4ALgBcAC4ALgBcAC4ALgBcAC4ALgBcAC4ALgBcAFAAcgBvAGcAcgBhAG0AIABGAGkAbABlAHMAIAAoAHgAOAA2ACkAXABlAE0AIABDAGwAaQBlAG4AdABcAE0AYQBpAGwAQwBsAGkAZQBuAHQALgBlAHgAZQAhAEMAOgBcAFAAcgBvAGcAcgBhAG0AIABGAGkAbABlAHMAIAAoAHgAOAA2ACkAXABlAE0AIABDAGwAaQBlAG4AdABcABAAAAAFAACgKgAAAMUAAAAcAAAACwAAoO9AWnz7oPxLh0rA8uC5+o7FAAAAYAAAAAMAAKBYAAAAAAAAAGRlc2t0b3AtMXQ2NzljMwDAjm9roW+mTYSUpDuxJCesZCschEmn7hGn49A3RQTu88COb2uhb6ZNhJSkO7EkJ6xkKxyESafuEafj0DdFBO7zywAAAAkAAKBBAAAAMVNQU+KKWEa8TDhDu/wTkyaYbc4lAAAABAAAAAAfAAAACQAAAFMALQAxAC0ANQAtADEAOAAAAAAAAAAAAEUAAAAxU1BTVShMn3mfOUuo0OHULeHV8ykAAAAFAAAAAB8AAAALAAAATQBhAGkAbABDAGwAaQBlAG4AdAAAAAAAAAAAADkAAAAxU1BTsRZtRK2NcEinSEAupD14jB0AAABoAAAAAEgAAABnFOwCkz/oRoevpRY9npVZAAAAAAAAAAAAAAAA" } | |
@{name = "Visual Studio Code"; path = "$env:AppData\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar\Visual Studio Code.lnk"; data = "TAAAAAEUAgAAAAAAwAAAAAAAAEabAAAAIAAAABKnspAMO9oBNibBkgw72gEAALRlpS3aAbB/OAkAAAAAAQAAAAAAAAAAAAAAAAAAAC4COgAfSUcaA1lyP6dEicVVlf5rMO4mAAEAJgDvvhAAAABWLuj7CjvaAbEnsigMO9oBFfmKlQw72gEUAIIAdAAcAENGU0YWADEAAAAAAJ5Xm1MSAEFwcERhdGEAAAB0Gllelt/TSI1nFzO87ii6xc36359nVkGJR8XHa8C2f0AACQAEAO++nlebU55X+FQuAAAABLkBAAAAAgAAAAAAAAAAAAAAAAAAAM4p9wBBAHAAcABEAGEAdABhAAAAQgBQADEAAAAAAJ5XBFUQAExvY2FsADwACQAEAO++nlebU55XBFUuAAAAGLkBAAAAAgAAAAAAAAAAAAAAAAAAAGS0NQBMAG8AYwBhAGwAAAAUAFoAMQAAAAAAnlcGVRAAUHJvZ3JhbXMAAEIACQAEAO++nlfvVJ5XBlUuAAAAXQEAAAAAAgAAAAAAAAAAAAAAAAAAAAWhYgBQAHIAbwBnAHIAYQBtAHMAAAAYAGwAMQAAAAAAnlcJVTAATUlDUk9TfjEAAFQACQAEAO++nlcGVZ5XClUuAAAAVAMCAAAAAQAAAAAANAEAAAAAAAAAAEy+vQBNAGkAYwByAG8AcwBvAGYAdAAgAFYAUwAgAEMAbwBkAGUAAAAYAFoAMgCwfzgJjVdcSiAAQ29kZS5leGUAAEIACQAEAO++nlcGVZ5XCFUuAAAAWgMCAAAAAQAAAAAABAIAAAAAAAAAAAAAAABDAG8AZABlAC4AZQB4AGUAAAAYAAAAbQAAABwAAAABAAAAHAAAAC0AAAAAAAAAbAAAABEAAAADAAAAAHGq1BAAAAAAQzpcVXNlcnNcYmFzXEFwcERhdGFcTG9jYWxcUHJvZ3JhbXNcTWljcm9zb2Z0IFZTIENvZGVcQ29kZS5leGUAADsALgAuAFwALgAuAFwALgAuAFwALgAuAFwALgAuAFwALgAuAFwATABvAGMAYQBsAFwAUAByAG8AZwByAGEAbQBzAFwATQBpAGMAcgBvAHMAbwBmAHQAIABWAFMAIABDAG8AZABlAFwAQwBvAGQAZQAuAGUAeABlADUAQwA6AFwAVQBzAGUAcgBzAFwAYgBhAHMAXABBAHAAcABEAGEAdABhAFwATABvAGMAYQBsAFwAUAByAG8AZwByAGEAbQBzAFwATQBpAGMAcgBvAHMAbwBmAHQAIABWAFMAIABDAG8AZABlABwAAAALAACgfA/O8wFJzEqGSNXUSwTvjzoAAABgAAAAAwAAoFgAAAAAAAAAZGVza3RvcC0xdDY3OWMzAMCOb2uhb6ZNhJSkO7EkJ6wTJByESafuEafj0DdFBO7zwI5va6Fvpk2ElKQ7sSQnrBMkHIRJp+4Rp+PQN0UE7vMzAQAACQAAoIkAAAAxU1BT4opYRrxMOEO7/BOTJphtzm0AAAAEAAAAAB8AAAAuAAAAUwAtADEALQA1AC0AMgAxAC0AMgA0ADQANAA1ADYAMgA5ADAAMgAtADIAMAA3ADIAMQA1ADIAMgAzAC0ANAAxADMAOAAzADIANgAzADAAMgAtADEAMAAwADAAAAAAAAAAZQAAADFTUFNVKEyfeZ85S6jQ4dQt4dXzSQAAAAUAAAAACAAAADYAAABNAGkAYwByAG8AcwBvAGYAdAAuAFYAaQBzAHUAYQBsAFMAdAB1AGQAaQBvAEMAbwBkAGUAAAAAAAAAAAA5AAAAMVNQU7EWbUStjXBIp0hALqQ9eIwdAAAAaAAAAABIAAAAZxTsApM/6EaHr6UWPZ6VWQAAAAAAAAAAAAAAAA==" } | |
) | |
static [void] RestoreFiles() { | |
foreach ($pinnedItem in [Taskbar]::pinnedItems) { | |
$filePath = [Utils]::WriteFile($pinnedItem.data, $pinnedItem.path) | |
Write-Host "[OK] Created '$($pinnedItem.name)' link" -ForegroundColor Green | |
} | |
} | |
} | |
class DesktopIcons { | |
static [hashtable[]] $registry = @( | |
@{path = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\HideDesktopIcons\NewStartPanel"; displayName = "My Computer"; name = '{20D04FE0-3AEA-1069-A2D8-08002B30309D}'; propertyType = "DWord"; data = 0 } | |
@{path = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\HideDesktopIcons\NewStartPanel"; displayName = "Recycle bin"; name = '{645FF040-5081-101B-9F08-00AA002F954E}'; propertyType = "DWord"; data = 1 } | |
@{path = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\HideDesktopIcons\NewStartPanel"; displayName = "User's Files"; name = '{59031A47-3F72-44A7-89C5-5595FE6B30EE}'; propertyType = "DWord"; data = 1 } | |
@{path = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\HideDesktopIcons\NewStartPanel"; displayName = "OneDrive"; name = '{018D5C66-4533-4307-9B53-224DE2ED1FE6}'; propertyType = "DWord"; data = 1 } | |
) | |
static [void] RestoreDesktopIcons() { | |
<# | |
.SYNOPSIS | |
Restores desktop icons by removing all shortcut files from the Public and User desktops and restoring the registry settings. | |
.DESCRIPTION | |
This function removes all shortcut files from the Public and User desktops and then calls the RestoreRegistry method of the Utils class to restore the registry settings for desktop icons. | |
.PARAMETER None | |
This function does not accept any parameters. | |
.EXAMPLE | |
RestoreDesktopIcons | |
This example demonstrates how to use the RestoreDesktopIcons function to restore desktop icons. | |
#> | |
Write-Host "[Info] Removing desktop icons..." -ForegroundColor Blue | |
Remove-Item "$env:Public\Desktop\*.lnk" -ErrorAction SilentlyContinue | |
Remove-Item "$env:UserProfile\Desktop\*.lnk" -ErrorAction SilentlyContinue | |
[Utils]::RestoreRegistry([DesktopIcons]::registry) | |
} | |
} |
<Configuration> | |
<vGPU>Enable</vGPU> | |
<Networking>Default</Networking> | |
<AudioInput>Disable</AudioInput> | |
<VideoInput>Disable</VideoInput> | |
<PrinterRedirection>Disable</PrinterRedirection> | |
<ClipboardRedirection>Default</ClipboardRedirection> | |
<ProtectedClient>Enable</ProtectedClient> | |
<MappedFolders> | |
<MappedFolder> | |
<HostFolder>C:\Users\bas\Downloads\.sandbox</HostFolder> | |
<SandboxFolder>C:\Users\WDAGUtilityAccount\Downloads</SandboxFolder> | |
<ReadOnly>False</ReadOnly> | |
</MappedFolder> | |
</MappedFolders> | |
<LogonCommand> | |
<Command>powershell -executionpolicy Unrestricted -Command "start powershell { -Command \"Set-ExecutionPolicy Unrestricted -Scope LocalMachine -Force; Invoke-WebRequest -UseBasicParsing -Uri 'https://gist.githubusercontent.com/QNimbus/83a86ee072d2b4dbfd13f2fe901796df/raw/scripts---bootstrap_sandbox.ps1' | Select-Object -ExpandProperty Content | Invoke-Expression \"}"</Command> | |
</LogonCommand> | |
</Configuration> |