|
# Last Update : 08/03/2024 |
|
# LM1LC3NT |
|
# Script version 2.4 |
|
|
|
# |
|
# Changelog: |
|
# v2.x |
|
# Minor updates |
|
# |
|
# v2.0 |
|
# Switching from mainly chocolatey to winget, as this tool is included to Windows 11 and seems more powerfull. |
|
# Finaly, wingetUI allows automatic and background checks and updates. A lot better than the Microsoft Store |
|
# than does not really update apps (or every months, not days). |
|
# |
|
|
|
# Execute the script NOT as admin. Elevated prompts will be generated when needed. |
|
# Note: a folder will be created on the same path, see variable "$destFolderName" bellow. |
|
# Command: |
|
# powershell -ExecutionPolicy Bypass -File Setup_app_new_windows.ps1 |
|
|
|
# |
|
# Microsoft Store vs Standard apps? |
|
# Some apps in the MS Store are the same than their standard installer version. |
|
# In that case, prefer to use the MS Store, as it will constantly and in background update them (in theory at least). |
|
# In other cases, UWP app are just lighter or PWA versions, so way less interesing / performant than |
|
# their standard alternative versions (for example, VLC). |
|
# |
|
|
|
# |
|
# Automating software updates using winget, without WingetUI: |
|
# winget update --all |
|
# |
|
|
|
# OTHER TOOLS NICE TO HAVE, but can't apply it now in one file script |
|
# Context Menu for Hash Calculation with PS: https://www.tenforums.com/tutorials/78681-add-file-hash-context-menu-windows-8-10-a.html |
|
|
|
# ----- |
|
# CONFIGURATION |
|
# ----- |
|
|
|
### MANUAL APP TO INSTALL : Download to folder |
|
$destFolderName = "_Manual_Install_Softwares" |
|
$DownloadOnlyAppList = @( |
|
@("Outline-Client.exe", "https://s3.amazonaws.com/outline-releases/client/windows/stable/Outline-Client.exe") # OutlineVPN Client |
|
) |
|
|
|
### APPLICATION INSTALLED FROM MICROSOFT STORE |
|
# Get ID from Microsoft Store Online (check URL). Example: https://apps.microsoft.com/store/detail/powershell/9MZ1SNWT0N5D |
|
$storeAppListID = @( |
|
"9NVN9SZ8KFD7", # LibreWolf |
|
"9N0DX20HK701", # Terminal |
|
"xp8k0hkjfrxgck", # Oh My Posh |
|
"XP89DCGQ3K6VLD", # PowerToys |
|
"9MZ1SNWT0N5D", # PowerShell |
|
"9NBLGGH516XP", # EarTrumpet |
|
"XP9KHM4BK9FZ7Q", # VSCode |
|
"XP8C9QZMS2PC1T", # Brave Browser |
|
"9P781RW2VM6G", # WSL Tray Monitor |
|
"9NDGGX7M2H0V" # WSL Toolbox |
|
) |
|
|
|
$wingetAppList_base = @( |
|
"SomePythonThings.WingetUIStore", |
|
"Notepad++.Notepad++", |
|
"mcmilk.7zip-zstd", # (alternative avec plus de lib de compression, sinon " 7zip.7zip") |
|
"NextDNS.NextDNS.Desktop", |
|
"Mobatek.MobaXterm", |
|
"VideoLAN.VLC", |
|
"Foxit.FoxitReader", |
|
"JGraph.Draw", |
|
"undergroundwires.privacy.sexy", # enforce privacy & security best-practices on Windows |
|
"TeamSophia.SophiApp" # open source tweaker for fine-tuning of W10 + W11 |
|
) |
|
|
|
$wingetAppList_poweruser = @( |
|
"Microsoft.VisualStudioCode", |
|
"ShareX.ShareX", # (ou FastStone.Capture) |
|
"FilesCommunity.Files", |
|
"Git.Git", |
|
"Safing.Portmaster", |
|
"Microsoft.Powershell", |
|
"JanDeDobbeleer.OhMyPosh" |
|
) |
|
|
|
|
|
# ------------------------------------------------------------- |
|
|
|
|
|
# ----- |
|
# FUNCTIONS |
|
# ----- |
|
|
|
function print.err { |
|
Param( |
|
[Parameter()] |
|
[String] |
|
$Message |
|
) |
|
Write-Host -ForegroundColor Red "[ERROR] $Message" |
|
} |
|
|
|
function print.warn { |
|
Param( |
|
[Parameter()] |
|
[String] |
|
$Message |
|
) |
|
Write-Host -ForegroundColor Yellow "$Message" |
|
} |
|
|
|
function print.success { |
|
Param( |
|
[Parameter()] |
|
[String] |
|
$Message |
|
) |
|
Write-Host -ForegroundColor Green "$Message" |
|
} |
|
|
|
function print.info { |
|
Param( |
|
[Parameter()] |
|
[String] |
|
$Message |
|
) |
|
Write-Host "$Message" |
|
} |
|
|
|
function wingetInstallFromListFromMsstore($list, $existingApps){ |
|
foreach ($app in $list) { |
|
# Check if app exist or install it |
|
if (!($existingApps | findstr $app)) { |
|
print.info "Installing $app from Microsoft Store..." |
|
try { winget install --exact --id $app --source msstore --silent --accept-package-agreements --accept-package-agreements } |
|
catch { print.err "Error: $_" } |
|
} else { |
|
print.info "$app is already installed" |
|
} |
|
} |
|
print.info |
|
} |
|
|
|
function wingetInstallFromListFromWinget($list, $existingApps){ |
|
foreach ($app in $list) { |
|
# Check if app exist or install it |
|
if (!($existingApps | findstr $app)) { |
|
print.info "Installing $app from Winget..." |
|
try { winget install --exact --id $app --source winget --silent --accept-source-agreements --accept-package-agreements } |
|
catch { print.err "Error: $_" } |
|
} else { |
|
print.info "$app is already installed" |
|
} |
|
} |
|
print.info |
|
} |
|
|
|
|
|
# ------------------------------------------------------------- |
|
|
|
|
|
# ----- |
|
# CHECK DEPENCIES |
|
# ----- |
|
|
|
|
|
# Check for winget |
|
# https://github.com/microsoft/winget-cli/releases/ |
|
|
|
$wingetPath = Get-Command -Name winget |
|
if ($wingetPath) { |
|
print.success "[OK] Winget is installed." |
|
} else { |
|
print.err "Winget is not installed." |
|
print.info "Download and install the last release from GitHub or azure:" |
|
print.info "https://github.com/microsoft/winget-cli/releases/ or https://winget.azureedge.net/cache/source.msix" |
|
print.info |
|
Exit-PSSession |
|
} |
|
print.info |
|
|
|
# Check for gsudo |
|
# This will be used then to install apps using admin rights when they need to |
|
|
|
$sudoPath = Get-Command -Name gsudo |
|
if ($sudoPath) { |
|
print.success "[OK] gsudo is installed." |
|
} else { |
|
print.warn "gsudo is not installed." |
|
print.info "Starting installation using winget..." |
|
winget install -e --id gerardog.gsudo --silent --accept-source-agreements --accept-package-agreements |
|
|
|
# Test error |
|
if ($?) { |
|
print.warn "gsudo installed, you must open a new shell and restart the script to continue." |
|
} else { |
|
print.err "gsudo installation error." |
|
} |
|
print.info |
|
Exit-PSSession |
|
} |
|
print.info |
|
|
|
# Refreshing installed local packages list |
|
print.success "[INFO] Refreshing list of installed packages." |
|
$existingApps = winget list |
|
print.info |
|
|
|
# Ask once to elevate |
|
print.success "[INFO] Temporary caching admin privileges." |
|
gsudo cache on |
|
print.info |
|
|
|
# Update winget cache and solve problems |
|
# known issue: https://github.com/microsoft/winget-cli/issues/2686 |
|
print.success "[INFO] Updating winget source" |
|
Add-AppxPackage -RegisterByFamilyName -MainPackage Microsoft.Winget.Source_8wekyb3d8bbwe |
|
winget source reset |
|
winget source update |
|
#winget source update --name winget |
|
# Other solution: https://github.com/microsoft/winget-cli/issues/3652#issuecomment-1956699129 |
|
# winget install -s msstore --id 9NBLGGH4NNS1 |
|
print.info |
|
|
|
|
|
# ------------------------------------------------------------- |
|
|
|
|
|
# ----- |
|
# Export bitlocker key |
|
# ----- |
|
|
|
|
|
# Check if bitlocker is enabled and export recovery key on the desktop |
|
print.success "[INFO] Checking bitlocker for C:" |
|
$blinfo = sudo { Get-BitlockerVolume -MountPoint "C:" } |
|
$BLexportPath = "$env:USERPROFILE\Desktop" |
|
|
|
if($blinfo.ProtectionStatus -eq 1){ |
|
print.info "Exporting Bitlocker key for disk C: to $BLexportPath\bitlocker_recovery.txt" |
|
|
|
(sudo { Get-BitLockerVolume -MountPoint C}).KeyProtector.KeyProtectorId >> $BLexportPath\bitlocker_recovery.txt |
|
(sudo { Get-BitLockerVolume -MountPoint C}).KeyProtector.recoverypassword >> $BLexportPath\bitlocker_recovery.txt |
|
|
|
# Test error |
|
if ($?) { |
|
print.success "[OK] Bitlocker recovery key for disk C: exported to $BLexportPath\bitlocker_recovery.txt." |
|
print.info |
|
} else { |
|
print.err "Error while exporting the bitlocker recovery key for disk C: to $BLexportPath\bitlocker_recovery.txt." |
|
print.info |
|
} |
|
} else { |
|
print.warn "Bitlocker not detected for disk C:" |
|
print.info |
|
} |
|
|
|
|
|
|
|
# ------------------------------------------------------------- |
|
|
|
|
|
# ----- |
|
# Disable Cortana + Bing in start menu |
|
# ----- |
|
|
|
|
|
# Source: https://theohbrothers.com/posts/disable-bing-search-and-cortana-on-windows-11/ |
|
print.success "[INFO] Disabling Bing search in start menu and disabling cortana globally." |
|
####################### |
|
# Disable Bing Search # |
|
####################### |
|
if (!(sudo Get-Item -Path 'HKCU:\SOFTWARE\Policies\Microsoft\Windows\Explorer' -ErrorAction SilentlyContinue)) { |
|
sudo New-Item -Path 'HKCU:\SOFTWARE\Policies\Microsoft\Windows\Explorer' |
|
} |
|
if (!(sudo Get-Item -Path 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\Explorer' -ErrorAction SilentlyContinue)) { |
|
sudo New-Item -Path 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\Explorer' |
|
} |
|
sudo New-ItemProperty -Path 'HKCU:\Software\Policies\Microsoft\Windows\Explorer' -Name 'DisableSearchBoxSuggestions' -Value 1 -PropertyType DWORD -Force |
|
sudo New-ItemProperty -Path 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\Explorer' -Name 'DisableSearchBoxSuggestions' -Value 1 -PropertyType DWORD -Force |
|
|
|
# 1903 and later, applies to Microsoft and local user accounts |
|
# Apply to current MS account |
|
if (!(sudo Get-Item -Path 'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Search' -ErrorAction SilentlyContinue)) { |
|
sudo New-Item Path 'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Search' |
|
} |
|
sudo New-ItemProperty -Path 'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Search' -Name 'BingSearchEnabled' -Value 0 -PropertyType DWORD -Force |
|
# Apply to all MS accounts (Does not work) |
|
if (!(sudo Get-Item -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Search' -ErrorAction SilentlyContinue)) { |
|
sudo New-Item -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Search' |
|
} |
|
sudo New-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Search' -Name 'BingSearchEnabled' -Value 0 -PropertyType DWORD -Force |
|
print.info |
|
|
|
# ---------------------------------------------------------- |
|
# --------------Disable Cortana in start menu--------------- |
|
# ---------------------------------------------------------- |
|
# Source: Privacy.sexy |
|
echo --- Disable Cortana in start menu |
|
sudo { reg add "HKCU\Software\Microsoft\Windows\CurrentVersion\Search" /v "CortanaEnabled" /t "REG_DWORD" /d "0" /f } |
|
sudo { reg add "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Search" /v "CortanaEnabled" /t "REG_DWORD" /d "0" /f } |
|
# ---------------------------------------------------------- |
|
# ---------------------------------------------------------- |
|
# ----------Disable web results in Windows Search----------- |
|
# ---------------------------------------------------------- |
|
echo --- Disable web results in Windows Search |
|
sudo { reg add "HKLM\SOFTWARE\Policies\Microsoft\Windows\Windows Search" /v "ConnectedSearchUseWeb" /t "REG_DWORD" /d "0" /f } |
|
sudo { reg add "HKLM\SOFTWARE\Policies\Microsoft\Windows\Windows Search" /v "ConnectedSearchUseWebOverMeteredConnections" /t "REG_DWORD" /d "0" /f } |
|
# ---------------------------------------------------------- |
|
|
|
|
|
# ------------------------------------------------------------- |
|
|
|
|
|
# ----- |
|
# Downloading apps manually |
|
# ----- |
|
|
|
|
|
print.success "[INFO] Downloading apps that can't be automatically installed using winget or Microsoft Store." |
|
$destinationFolder = $PSScriptRoot + "\" + $destFolderName + "\" |
|
$validUrlPattern = "^(https?|ftp)://[^\s/$.?#].[^\s]*$" |
|
|
|
# Folder creation |
|
print.info "Creating folder to download installers: $destinationFolder" |
|
New-Item -Path $destinationFolder -ItemType Directory -Force -ErrorAction SilentlyContinue > $null |
|
|
|
# DL files |
|
foreach ($row in $DownloadOnlyAppList) { |
|
$url = $row[1] |
|
$filename = $row[0] |
|
$destinationPath = $destinationFolder + $filename |
|
|
|
if ($url -match $validUrlPattern) { |
|
print.info "Downloading $filename from $url ..." |
|
try { (New-Object System.Net.WebClient).DownloadFile($url, $destinationPath) } |
|
catch { print.err "Error: $_" } |
|
} else { |
|
print.err "Invalid URL: $url" |
|
} |
|
} |
|
print.info |
|
|
|
|
|
|
|
# ------------------------------------------------------------- |
|
|
|
|
|
# ----- |
|
# Installing & Activating Hyper-V |
|
# ----- |
|
|
|
print.success "[INFO] Installing and activating optional feature: Microsoft-Hyper-V" |
|
$featureInstalled = sudo { Get-WmiObject -query "select * from win32_optionalfeature where installstate= 1 and name = 'Microsoft-Hyper-V'" } |
|
If (-not $featureInstalled) { |
|
# Feature not installed, installing |
|
# Hyper-V |
|
sudo dism /online /enable-feature /all /featurename:Microsoft-Hyper-V /norestart |
|
# Test error |
|
if (!$?) { |
|
print.err "Error: $_" |
|
print.info |
|
} |
|
sudo dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart |
|
# Test error |
|
if ($?) { |
|
print.success "[OK] Hyper-V installed" |
|
} else { |
|
print.err "Error: $_" |
|
} |
|
} else { |
|
# Feature already installed |
|
print.info "Feature is already installed." |
|
} |
|
print.info |
|
|
|
|
|
|
|
# ------------------------------------------------------------- |
|
|
|
# ----- |
|
# Updating and installing Microsoft Store apps |
|
# ----- |
|
|
|
# Updating Microsoft Store apps |
|
# Source: https://github.com/microsoft/winget-cli/issues/2854#issuecomment-1435369342 |
|
print.success "[INFO] Updating apps from Microsoft Store (using winget)" |
|
sudo { Get-CimInstance -Namespace "Root\cimv2\mdm\dmmap" -ClassName "MDM_EnterpriseModernAppManagement_AppManagement01" | Invoke-CimMethod -MethodName UpdateScanMethod } |
|
|
|
# Installing Microsoft Store apps |
|
print.success "[INFO] Installing apps from Microsoft Store (using winget)" |
|
wingetInstallFromListFromMsstore $storeAppListID $existingApps |
|
|
|
|
|
# ------------------------------------------------------------- |
|
|
|
|
|
# ----- |
|
# Installing apps with winget |
|
# ----- |
|
|
|
|
|
print.success "[INFO] Installing winget apps using list: wingetAppList_base" |
|
wingetInstallFromListFromWinget $wingetAppList_base $existingApps |
|
print.info |
|
|
|
print.success "[INFO] Installing winget apps using list: wingetAppList_poweruser" |
|
wingetInstallFromListFromWinget $wingetAppList_poweruser $existingApps |
|
print.info |
|
|
|
# Update all |
|
# Source: https://github.com/microsoft/winget-cli/issues/2854#issuecomment-1386272357 |
|
print.success "[INFO] Updating all local packages using winget." |
|
try { winget upgrade --all --include-unknown } |
|
catch { print.err "Error: $_" } |
|
print.info |
|
|
|
|
|
# ------------------------------------------------------------- |
|
|
|
|
|
# ----- |
|
# Installing Sandbox |
|
# ----- |
|
print.success "[INFO] Installing and activating Windows Sandbox." |
|
dism /online /enable-feature /featurename:"Containers-DisposableClientVM" /all /norestart |
|
print.info |
|
|
|
|
|
|
|
# ------------------------------------------------------------- |
|
|
|
|
|
# ----- |
|
# Installing WSL |
|
# ----- |
|
|
|
print.success "[INFO] Installing and activating WSL 2." |
|
|
|
# Activate WSL |
|
## * https://docs.microsoft.com/fr-fr/windows/wsl/install-win10) |
|
## * https://support.rstudio.com/hc/en-us/articles/360049776974-Using-RStudio-Server-in-Windows-WSL2 |
|
|
|
# Manual installation of WSL 2. |
|
# Sometimes this does not work with an elevated CMD, it will prompt again a password admin |
|
# Which is a problem sometimes, when using "BeyondTrust" for example |
|
# wsl --install --no-launch |
|
# alternative that works well: |
|
|
|
## WSL 2 |
|
sudo dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart |
|
# Test error |
|
if (!$?) { |
|
print.err "Error: $_" |
|
} |
|
print.info |
|
|
|
## restart |
|
## update kernel : https://docs.microsoft.com/fr-fr/windows/wsl/wsl2-kernel |
|
## Install ubuntu from winstore and run it to install |
|
## Source: https://learn.microsoft.com/en-us/windows/wsl/install-manual |
|
print.success "[INFO] Installing wsl 2 with default Linux distribution" |
|
wsl --set-default-version 2 |
|
# Test error |
|
if (!$?) { |
|
print.err "Error: $_" |
|
print.info |
|
} |
|
print.info |
|
|
|
print.success "[INFO] Downloading and installing Ubuntu 22.04 LTS" |
|
wsl --install --distribution Ubuntu-22.04 |
|
# Test error |
|
if (!$?) { |
|
print.warn "[ERROR] A reboot is probably needed. After a reboot, run the following command to install a WSL distro." |
|
print.info "wsl --install --distribution Ubuntu-22.04" |
|
print.err "Error: $_" |
|
print.info |
|
} |
|
print.info |
|
|
|
|
|
# ------------------------------------------------------------- |
|
|
|
|
|
# ----- |
|
# OTHER: Configuring long path, intializing git, installing oh my posh and fonts, |
|
# configuring explorer to show extensions by default |
|
# ----- |
|
|
|
print.success "[INFO] Configuring long path & intialising git " |
|
# Long path |
|
sudo Set-ItemProperty 'HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem' -Name 'LongPathsEnabled' -Value 1 |
|
print.info |
|
|
|
# Git init |
|
print.success "[INFO] Setting up git config globaly" |
|
$name = Read-Host "What is your name :" |
|
$email = Read-Host "What is your email :" |
|
sudo git config --global user.name $name |
|
sudo git config --global user.email $email |
|
print.info |
|
|
|
# Installing oh-my-posh |
|
# Source: https://ohmyposh.dev/docs/installation/windows |
|
print.success "[INFO] Insatalling Oh-my-posh and setting it up as default Powershell config." |
|
Set-ExecutionPolicy Bypass -Scope Process -Force; Invoke-Expression ((New-Object System.Net.WebClient).DownloadString('https://ohmyposh.dev/install.ps1')) |
|
# Add prompt on powershell startup for current user and admin |
|
Add-Content -Path $PROFILE "`noh-my-posh init pwsh --config ""$env:POSH_THEMES_PATH\jandedobbeleer.omp.json"" | Invoke-Expression" |
|
sudo Add-Content -Path $PROFILE "`noh-my-posh init pwsh --config ""$env:POSH_THEMES_PATH\jandedobbeleer.omp.json"" | Invoke-Expression" |
|
print.info |
|
|
|
# Installing fonts using oh-my-posh in a new powershell session (to reload env and use oh-my-posh) |
|
print.success "[INFO] Insatalling fonts globally using Oh-my-posh." |
|
print.info "Installing font 1/4" |
|
start powershell { sudo oh-my-posh font install RobotoMono } |
|
print.info "Installing font 2/4" |
|
start powershell { sudo oh-my-posh font install Hack } |
|
print.info "Installing font 3/4" |
|
start powershell { sudo oh-my-posh font install UbuntuMono } |
|
print.info "Installing font 4/4" |
|
start powershell { sudo oh-my-posh font install Meslo } |
|
|
|
# Configuring explorer to show file extensions by default |
|
$key = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced' |
|
Set-ItemProperty $key Hidden 1 |
|
Set-ItemProperty $key HideFileExt 0 |
|
Set-ItemProperty $key ShowSuperHidden 1 |
|
Stop-Process -processname explorer |
|
|
|
# ------------------------------------------------------------- |
|
|
|
|
|
# stop sudo cache |
|
sudo cache off |
|
|
|
print.info |
|
print.success "Script end!" |
|
|
|
|
|
exit |