2026-03-07 20:28:48 +01:00
|
|
|
# Replace the startmenu for all users, when using the default startmenuTemplate this clears all pinned apps
|
|
|
|
|
# Credit: https://lazyadmin.nl/win-11/customize-windows-11-start-menu-layout/
|
|
|
|
|
function ReplaceStartMenuForAllUsers {
|
|
|
|
|
param (
|
2026-05-08 21:19:52 +02:00
|
|
|
$startMenuTemplate = "$script:AssetsPath\Start\start2.bin"
|
2026-03-07 20:28:48 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
Write-Host "> Removing all pinned apps from the start menu for all users..."
|
|
|
|
|
|
|
|
|
|
# Check if template bin file exists
|
|
|
|
|
if (-not (Test-Path $startMenuTemplate)) {
|
|
|
|
|
Write-Host "Error: Unable to clear start menu, start2.bin file missing from script folder" -ForegroundColor Red
|
|
|
|
|
Write-Host ""
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# Get path to start menu file for all users
|
|
|
|
|
$userPathString = GetUserDirectory -userName "*" -fileName "AppData\Local\Packages\Microsoft.Windows.StartMenuExperienceHost_cw5n1h2txyewy\LocalState"
|
2026-05-08 21:19:52 +02:00
|
|
|
$usersStartMenuPaths = Get-ChildItem -Path $userPathString -ErrorAction SilentlyContinue
|
2026-03-07 20:28:48 +01:00
|
|
|
|
|
|
|
|
# Go through all users and replace the start menu file
|
|
|
|
|
ForEach ($startMenuPath in $usersStartMenuPaths) {
|
|
|
|
|
ReplaceStartMenu $startMenuTemplate "$($startMenuPath.Fullname)\start2.bin"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# Also replace the start menu file for the default user profile
|
|
|
|
|
$defaultStartMenuPath = GetUserDirectory -userName "Default" -fileName "AppData\Local\Packages\Microsoft.Windows.StartMenuExperienceHost_cw5n1h2txyewy\LocalState" -exitIfPathNotFound $false
|
|
|
|
|
|
|
|
|
|
# Create folder if it doesn't exist
|
|
|
|
|
if (-not (Test-Path $defaultStartMenuPath)) {
|
|
|
|
|
new-item $defaultStartMenuPath -ItemType Directory -Force | Out-Null
|
|
|
|
|
Write-Host "Created LocalState folder for default user profile"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# Copy template to default profile
|
|
|
|
|
Copy-Item -Path $startMenuTemplate -Destination $defaultStartMenuPath -Force
|
|
|
|
|
Write-Host "Replaced start menu for the default user profile"
|
|
|
|
|
Write-Host ""
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Replace the startmenu for all users, when using the default startmenuTemplate this clears all pinned apps
|
|
|
|
|
# Credit: https://lazyadmin.nl/win-11/customize-windows-11-start-menu-layout/
|
|
|
|
|
function ReplaceStartMenu {
|
|
|
|
|
param (
|
2026-05-08 21:19:52 +02:00
|
|
|
$startMenuTemplate = "$script:AssetsPath\Start\start2.bin",
|
2026-03-07 20:28:48 +01:00
|
|
|
$startMenuBinFile = "$env:LOCALAPPDATA\Packages\Microsoft.Windows.StartMenuExperienceHost_cw5n1h2txyewy\LocalState\start2.bin"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
# Change path to correct user if a user was specified
|
|
|
|
|
if ($script:Params.ContainsKey("User")) {
|
2026-05-08 21:19:52 +02:00
|
|
|
$startMenuBinFile = GetStartMenuBinPathForUser -UserName (GetUserName)
|
2026-03-07 20:28:48 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# Check if template bin file exists
|
|
|
|
|
if (-not (Test-Path $startMenuTemplate)) {
|
|
|
|
|
Write-Host "Error: Unable to replace start menu, template file not found" -ForegroundColor Red
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ([IO.Path]::GetExtension($startMenuTemplate) -ne ".bin" ) {
|
|
|
|
|
Write-Host "Error: Unable to replace start menu, template file is not a valid .bin file" -ForegroundColor Red
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-08 21:19:52 +02:00
|
|
|
$userName = GetStartMenuUserNameFromPath -StartMenuBinFile $startMenuBinFile
|
2026-03-07 20:28:48 +01:00
|
|
|
|
|
|
|
|
$backupBinFile = $startMenuBinFile + ".bak"
|
|
|
|
|
|
|
|
|
|
if (Test-Path $startMenuBinFile) {
|
|
|
|
|
# Backup current start menu file
|
|
|
|
|
Move-Item -Path $startMenuBinFile -Destination $backupBinFile -Force
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
Write-Host "Unable to find original start2.bin file for user $userName, no backup was created for this user" -ForegroundColor Yellow
|
|
|
|
|
New-Item -ItemType File -Path $startMenuBinFile -Force
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# Copy template file
|
|
|
|
|
Copy-Item -Path $startMenuTemplate -Destination $startMenuBinFile -Force
|
|
|
|
|
|
|
|
|
|
Write-Host "Replaced start menu for user $userName"
|
2026-05-08 21:19:52 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function GetStartMenuBinPathForUser {
|
|
|
|
|
param(
|
|
|
|
|
[string]$UserName
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
if ([string]::IsNullOrWhiteSpace($UserName)) {
|
|
|
|
|
return "$env:LOCALAPPDATA\Packages\Microsoft.Windows.StartMenuExperienceHost_cw5n1h2txyewy\LocalState\start2.bin"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return (GetUserDirectory -userName $UserName -fileName "AppData\Local\Packages\Microsoft.Windows.StartMenuExperienceHost_cw5n1h2txyewy\LocalState\start2.bin" -exitIfPathNotFound $false)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function GetStartMenuUserNameFromPath {
|
|
|
|
|
param(
|
|
|
|
|
[string]$StartMenuBinFile
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
$resolvedUserName = [regex]::Match($StartMenuBinFile, '(?:Users\\)([^\\]+)(?:\\AppData)').Groups[1].Value
|
|
|
|
|
if ([string]::IsNullOrWhiteSpace($resolvedUserName)) {
|
|
|
|
|
return 'unknown'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $resolvedUserName
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function RestoreStartMenuFromBackup {
|
|
|
|
|
param(
|
|
|
|
|
[Parameter(Mandatory)]
|
|
|
|
|
[string]$StartMenuBinFile,
|
|
|
|
|
[Parameter(Mandatory = $false)]
|
|
|
|
|
[string]$BackupFilePath
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
$userName = GetStartMenuUserNameFromPath -StartMenuBinFile $StartMenuBinFile
|
|
|
|
|
$backupBinFile = if ([string]::IsNullOrWhiteSpace($BackupFilePath)) {
|
|
|
|
|
$StartMenuBinFile + '.bak'
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
$BackupFilePath
|
|
|
|
|
}
|
|
|
|
|
$currentBinBackup = $StartMenuBinFile + '.restore.bak'
|
|
|
|
|
|
|
|
|
|
if (-not (Test-Path -LiteralPath $backupBinFile)) {
|
|
|
|
|
return [PSCustomObject]@{
|
|
|
|
|
UserName = $userName
|
|
|
|
|
Result = $false
|
|
|
|
|
Message = "No start menu backup file found for user $userName."
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
if (Test-Path -LiteralPath $StartMenuBinFile) {
|
|
|
|
|
Move-Item -Path $StartMenuBinFile -Destination $currentBinBackup -Force
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Copy-Item -Path $backupBinFile -Destination $StartMenuBinFile -Force
|
|
|
|
|
return [PSCustomObject]@{
|
|
|
|
|
UserName = $userName
|
|
|
|
|
Result = $true
|
|
|
|
|
Message = "Restored start menu for user $userName."
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch {
|
|
|
|
|
return [PSCustomObject]@{
|
|
|
|
|
UserName = $userName
|
|
|
|
|
Result = $false
|
|
|
|
|
Message = "Failed to restore start menu for user $userName. $($_.Exception.Message)"
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function RestoreStartMenu {
|
|
|
|
|
param(
|
|
|
|
|
[Parameter(Mandatory = $false)]
|
|
|
|
|
[string]$BackupFilePath
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
$targetUserName = GetUserName
|
|
|
|
|
$startMenuBinFile = GetStartMenuBinPathForUser -UserName $targetUserName
|
|
|
|
|
|
|
|
|
|
Write-Host "Restoring start menu for user $targetUserName from backup..."
|
|
|
|
|
|
|
|
|
|
return RestoreStartMenuFromBackup -StartMenuBinFile $startMenuBinFile -BackupFilePath $BackupFilePath
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function RestoreStartMenuForAllUsers {
|
|
|
|
|
param(
|
|
|
|
|
[Parameter(Mandatory = $false)]
|
|
|
|
|
[string]$BackupFilePath
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
$userPathString = GetUserDirectory -userName "*" -fileName "AppData\Local\Packages\Microsoft.Windows.StartMenuExperienceHost_cw5n1h2txyewy\LocalState"
|
|
|
|
|
$usersStartMenuPaths = Get-ChildItem -Path $userPathString -ErrorAction SilentlyContinue
|
|
|
|
|
$results = @()
|
|
|
|
|
|
|
|
|
|
Write-Host "Restoring start menu for all users from backup..."
|
|
|
|
|
|
|
|
|
|
foreach ($startMenuPath in $usersStartMenuPaths) {
|
|
|
|
|
$startMenuBinFile = Join-Path $startMenuPath.FullName 'start2.bin'
|
|
|
|
|
$results += RestoreStartMenuFromBackup -StartMenuBinFile $startMenuBinFile -BackupFilePath $BackupFilePath
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$defaultStartMenuPath = GetUserDirectory -userName "Default" -fileName "AppData\Local\Packages\Microsoft.Windows.StartMenuExperienceHost_cw5n1h2txyewy\LocalState" -exitIfPathNotFound $false
|
|
|
|
|
|
|
|
|
|
if (Test-Path $defaultStartMenuPath) {
|
|
|
|
|
$defaultStartMenuBinFile = Join-Path $defaultStartMenuPath 'start2.bin'
|
|
|
|
|
if (Test-Path -LiteralPath $defaultStartMenuBinFile) {
|
|
|
|
|
try {
|
|
|
|
|
Remove-Item -LiteralPath $defaultStartMenuBinFile -Force
|
|
|
|
|
$results += [PSCustomObject]@{
|
|
|
|
|
UserName = 'Default'
|
|
|
|
|
Result = $true
|
|
|
|
|
Message = 'Removed start2.bin for the default user profile.'
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch {
|
|
|
|
|
$results += [PSCustomObject]@{
|
|
|
|
|
UserName = 'Default'
|
|
|
|
|
Result = $false
|
|
|
|
|
Message = "Failed to remove start2.bin for the default user profile. $($_.Exception.Message)"
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ($results.Count -eq 0) {
|
|
|
|
|
$results += [PSCustomObject]@{
|
|
|
|
|
UserName = 'unknown'
|
|
|
|
|
Result = $false
|
|
|
|
|
Message = 'No user start menu locations were found.'
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $results
|
2026-03-07 20:28:48 +01:00
|
|
|
}
|