mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-02-24 20:20:38 +01:00
292 lines
12 KiB
PowerShell
292 lines
12 KiB
PowerShell
|
|
<#
|
||
|
|
.SYNOPSIS
|
||
|
|
Sets up the development environment for building PowerToys.
|
||
|
|
|
||
|
|
.DESCRIPTION
|
||
|
|
This script automates the setup of prerequisites needed to build PowerToys locally:
|
||
|
|
- Enables Windows long path support (requires elevation)
|
||
|
|
- Enables Windows Developer Mode (requires elevation)
|
||
|
|
- Installs required Visual Studio workloads from .vsconfig
|
||
|
|
- Initializes git submodules
|
||
|
|
|
||
|
|
Run this script once after cloning the repository to prepare your development environment.
|
||
|
|
|
||
|
|
.PARAMETER SkipLongPaths
|
||
|
|
Skip enabling long path support in Windows.
|
||
|
|
|
||
|
|
.PARAMETER SkipDevMode
|
||
|
|
Skip enabling Windows Developer Mode.
|
||
|
|
|
||
|
|
.PARAMETER SkipVSComponents
|
||
|
|
Skip installing Visual Studio components from .vsconfig.
|
||
|
|
|
||
|
|
.PARAMETER SkipSubmodules
|
||
|
|
Skip initializing git submodules.
|
||
|
|
|
||
|
|
.PARAMETER VSInstallPath
|
||
|
|
Path to Visual Studio installation. Default: auto-detected.
|
||
|
|
|
||
|
|
.PARAMETER Help
|
||
|
|
Show this help message.
|
||
|
|
|
||
|
|
.EXAMPLE
|
||
|
|
.\tools\build\setup-dev-environment.ps1
|
||
|
|
Runs the full setup process.
|
||
|
|
|
||
|
|
.EXAMPLE
|
||
|
|
.\tools\build\setup-dev-environment.ps1 -SkipVSComponents
|
||
|
|
Runs setup but skips Visual Studio component installation.
|
||
|
|
|
||
|
|
.EXAMPLE
|
||
|
|
.\tools\build\setup-dev-environment.ps1 -VSInstallPath "C:\Program Files\Microsoft Visual Studio\2022\Enterprise"
|
||
|
|
Runs setup with a custom Visual Studio installation path.
|
||
|
|
|
||
|
|
.NOTES
|
||
|
|
- Some operations require administrator privileges (long paths, VS component installation).
|
||
|
|
- If not running as administrator, the script will prompt for elevation for those steps.
|
||
|
|
- The script is idempotent and safe to run multiple times.
|
||
|
|
#>
|
||
|
|
|
||
|
|
param (
|
||
|
|
[switch]$SkipLongPaths,
|
||
|
|
[switch]$SkipDevMode,
|
||
|
|
[switch]$SkipVSComponents,
|
||
|
|
[switch]$SkipSubmodules,
|
||
|
|
[string]$VSInstallPath = '',
|
||
|
|
[switch]$Help
|
||
|
|
)
|
||
|
|
|
||
|
|
if ($Help) {
|
||
|
|
Get-Help $MyInvocation.MyCommand.Path -Detailed
|
||
|
|
exit 0
|
||
|
|
}
|
||
|
|
|
||
|
|
$ErrorActionPreference = 'Stop'
|
||
|
|
|
||
|
|
# Find repository root
|
||
|
|
$scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Definition
|
||
|
|
$repoRoot = $scriptDir
|
||
|
|
while ($repoRoot -and -not (Test-Path (Join-Path $repoRoot "PowerToys.slnx"))) {
|
||
|
|
$parent = Split-Path -Parent $repoRoot
|
||
|
|
if ($parent -eq $repoRoot) {
|
||
|
|
Write-Error "Could not find PowerToys repository root. Ensure this script is in the PowerToys repository."
|
||
|
|
exit 1
|
||
|
|
}
|
||
|
|
$repoRoot = $parent
|
||
|
|
}
|
||
|
|
|
||
|
|
Write-Host "Repository: $repoRoot"
|
||
|
|
Write-Host ""
|
||
|
|
|
||
|
|
function Test-Administrator {
|
||
|
|
$currentUser = [Security.Principal.WindowsIdentity]::GetCurrent()
|
||
|
|
$principal = New-Object Security.Principal.WindowsPrincipal($currentUser)
|
||
|
|
return $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
|
||
|
|
}
|
||
|
|
|
||
|
|
$isAdmin = Test-Administrator
|
||
|
|
|
||
|
|
# Step 1: Enable Long Paths
|
||
|
|
if (-not $SkipLongPaths) {
|
||
|
|
Write-Host "[1/4] Checking Windows long path support"
|
||
|
|
|
||
|
|
$longPathsEnabled = $false
|
||
|
|
try {
|
||
|
|
$regValue = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem" -Name "LongPathsEnabled" -ErrorAction SilentlyContinue
|
||
|
|
$longPathsEnabled = ($regValue.LongPathsEnabled -eq 1)
|
||
|
|
} catch {
|
||
|
|
$longPathsEnabled = $false
|
||
|
|
}
|
||
|
|
|
||
|
|
if ($longPathsEnabled) {
|
||
|
|
Write-Host " Long paths already enabled" -ForegroundColor Green
|
||
|
|
} elseif ($isAdmin) {
|
||
|
|
Write-Host " Enabling long paths..."
|
||
|
|
try {
|
||
|
|
Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem" -Name "LongPathsEnabled" -Value 1 -Type DWord
|
||
|
|
Write-Host " Long paths enabled" -ForegroundColor Green
|
||
|
|
} catch {
|
||
|
|
Write-Warning " Failed to enable long paths: $_"
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
Write-Warning " Long paths not enabled. Run as Administrator to enable, or run manually:"
|
||
|
|
Write-Host " Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem' -Name 'LongPathsEnabled' -Value 1" -ForegroundColor DarkGray
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
Write-Host "[1/4] Skipping long path check" -ForegroundColor DarkGray
|
||
|
|
}
|
||
|
|
|
||
|
|
Write-Host ""
|
||
|
|
|
||
|
|
# Step 2: Enable Developer Mode
|
||
|
|
if (-not $SkipDevMode) {
|
||
|
|
Write-Host "[2/4] Checking Windows Developer Mode"
|
||
|
|
|
||
|
|
$devModeEnabled = $false
|
||
|
|
try {
|
||
|
|
$regValue = Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\AppModelUnlock" -Name "AllowDevelopmentWithoutDevLicense" -ErrorAction SilentlyContinue
|
||
|
|
$devModeEnabled = ($regValue.AllowDevelopmentWithoutDevLicense -eq 1)
|
||
|
|
} catch {
|
||
|
|
$devModeEnabled = $false
|
||
|
|
}
|
||
|
|
|
||
|
|
if ($devModeEnabled) {
|
||
|
|
Write-Host " Developer Mode already enabled" -ForegroundColor Green
|
||
|
|
} elseif ($isAdmin) {
|
||
|
|
Write-Host " Enabling Developer Mode..."
|
||
|
|
try {
|
||
|
|
$regPath = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\AppModelUnlock"
|
||
|
|
if (-not (Test-Path $regPath)) {
|
||
|
|
New-Item -Path $regPath -Force | Out-Null
|
||
|
|
}
|
||
|
|
Set-ItemProperty -Path $regPath -Name "AllowDevelopmentWithoutDevLicense" -Value 1 -Type DWord
|
||
|
|
Write-Host " Developer Mode enabled" -ForegroundColor Green
|
||
|
|
} catch {
|
||
|
|
Write-Warning " Failed to enable Developer Mode: $_"
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
Write-Warning " Developer Mode not enabled. Run as Administrator to enable, or enable manually:"
|
||
|
|
Write-Host " Settings > System > For developers > Developer Mode" -ForegroundColor DarkGray
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
Write-Host "[2/4] Skipping Developer Mode check" -ForegroundColor DarkGray
|
||
|
|
}
|
||
|
|
|
||
|
|
Write-Host ""
|
||
|
|
|
||
|
|
# Step 3: Install Visual Studio Components
|
||
|
|
if (-not $SkipVSComponents) {
|
||
|
|
Write-Host "[3/4] Checking Visual Studio components"
|
||
|
|
|
||
|
|
$vsConfigPath = Join-Path $repoRoot ".vsconfig"
|
||
|
|
if (-not (Test-Path $vsConfigPath)) {
|
||
|
|
Write-Warning " .vsconfig not found at $vsConfigPath"
|
||
|
|
} else {
|
||
|
|
$vsWhere = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe"
|
||
|
|
|
||
|
|
if (-not $VSInstallPath -and (Test-Path $vsWhere)) {
|
||
|
|
$VSInstallPath = & $vsWhere -latest -property installationPath 2>$null
|
||
|
|
}
|
||
|
|
|
||
|
|
if (-not $VSInstallPath) {
|
||
|
|
$commonPaths = @(
|
||
|
|
"${env:ProgramFiles}\Microsoft Visual Studio\2022\Enterprise",
|
||
|
|
"${env:ProgramFiles}\Microsoft Visual Studio\2022\Professional",
|
||
|
|
"${env:ProgramFiles}\Microsoft Visual Studio\2022\Community"
|
||
|
|
)
|
||
|
|
foreach ($path in $commonPaths) {
|
||
|
|
if (Test-Path $path) {
|
||
|
|
$VSInstallPath = $path
|
||
|
|
break
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (-not $VSInstallPath -or -not (Test-Path $VSInstallPath)) {
|
||
|
|
Write-Warning " Could not find Visual Studio 2022 installation"
|
||
|
|
Write-Warning " Please install Visual Studio 2022 and try again, or import .vsconfig manually"
|
||
|
|
} else {
|
||
|
|
Write-Host " Found: $VSInstallPath" -ForegroundColor DarkGray
|
||
|
|
|
||
|
|
$vsInstaller = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vs_installer.exe"
|
||
|
|
|
||
|
|
if (Test-Path $vsInstaller) {
|
||
|
|
Write-Host ""
|
||
|
|
Write-Host " To install required components:"
|
||
|
|
Write-Host ""
|
||
|
|
Write-Host " Option A - Visual Studio Installer GUI:"
|
||
|
|
Write-Host " 1. Open Visual Studio Installer"
|
||
|
|
Write-Host " 2. Click 'More' > 'Import configuration'"
|
||
|
|
Write-Host " 3. Select: $vsConfigPath"
|
||
|
|
Write-Host ""
|
||
|
|
Write-Host " Option B - Command line (close VS first):"
|
||
|
|
Write-Host " & `"$vsInstaller`" modify --installPath `"$VSInstallPath`" --config `"$vsConfigPath`"" -ForegroundColor DarkGray
|
||
|
|
Write-Host ""
|
||
|
|
|
||
|
|
$choices = @(
|
||
|
|
[System.Management.Automation.Host.ChoiceDescription]::new("&Install", "Run VS Installer now"),
|
||
|
|
[System.Management.Automation.Host.ChoiceDescription]::new("&Skip", "Continue without installing")
|
||
|
|
)
|
||
|
|
|
||
|
|
try {
|
||
|
|
$decision = $Host.UI.PromptForChoice("", "Install VS components now?", $choices, 1)
|
||
|
|
|
||
|
|
if ($decision -eq 0) {
|
||
|
|
# Check if VS Installer is already running (it runs as setup.exe from the Installer folder)
|
||
|
|
$vsInstallerDir = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer"
|
||
|
|
$vsInstallerRunning = Get-Process -Name "setup" -ErrorAction SilentlyContinue |
|
||
|
|
Where-Object { $_.Path -and $_.Path.StartsWith($vsInstallerDir, [System.StringComparison]::OrdinalIgnoreCase) }
|
||
|
|
if ($vsInstallerRunning) {
|
||
|
|
Write-Warning " Visual Studio Installer is already running"
|
||
|
|
Write-Host " Close it and run this script again, or import .vsconfig manually" -ForegroundColor DarkGray
|
||
|
|
} else {
|
||
|
|
Write-Host " Launching Visual Studio Installer..."
|
||
|
|
Write-Host " Close Visual Studio if it's running." -ForegroundColor DarkGray
|
||
|
|
$process = Start-Process -FilePath $vsInstaller -ArgumentList "modify", "--installPath", "`"$VSInstallPath`"", "--config", "`"$vsConfigPath`"" -Wait -PassThru
|
||
|
|
if ($process.ExitCode -eq 0) {
|
||
|
|
Write-Host " VS component installation completed" -ForegroundColor Green
|
||
|
|
} elseif ($process.ExitCode -eq 3010) {
|
||
|
|
Write-Host " VS component installation completed (restart may be required)" -ForegroundColor Green
|
||
|
|
} else {
|
||
|
|
Write-Warning " VS Installer exited with code $($process.ExitCode)"
|
||
|
|
Write-Host " You may need to run the installer manually" -ForegroundColor DarkGray
|
||
|
|
}
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
Write-Host " Skipped VS component installation"
|
||
|
|
}
|
||
|
|
} catch {
|
||
|
|
Write-Host " Non-interactive mode. Run the command above manually if needed." -ForegroundColor DarkGray
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
Write-Warning " Visual Studio Installer not found"
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
Write-Host "[3/4] Skipping VS component check" -ForegroundColor DarkGray
|
||
|
|
}
|
||
|
|
|
||
|
|
Write-Host ""
|
||
|
|
|
||
|
|
# Step 4: Initialize Git Submodules
|
||
|
|
if (-not $SkipSubmodules) {
|
||
|
|
Write-Host "[4/4] Initializing git submodules"
|
||
|
|
|
||
|
|
Push-Location $repoRoot
|
||
|
|
try {
|
||
|
|
$submoduleStatus = git submodule status 2>&1
|
||
|
|
$uninitializedCount = ($submoduleStatus | Where-Object { $_ -match '^\-' }).Count
|
||
|
|
|
||
|
|
if ($uninitializedCount -eq 0 -and $submoduleStatus) {
|
||
|
|
Write-Host " Submodules already initialized" -ForegroundColor Green
|
||
|
|
} else {
|
||
|
|
Write-Host " Running: git submodule update --init --recursive" -ForegroundColor DarkGray
|
||
|
|
git submodule update --init --recursive
|
||
|
|
if ($LASTEXITCODE -eq 0) {
|
||
|
|
Write-Host " Submodules initialized" -ForegroundColor Green
|
||
|
|
} else {
|
||
|
|
Write-Warning " Submodule initialization may have encountered issues (exit code: $LASTEXITCODE)"
|
||
|
|
}
|
||
|
|
}
|
||
|
|
} catch {
|
||
|
|
Write-Warning " Failed to initialize submodules: $_"
|
||
|
|
} finally {
|
||
|
|
Pop-Location
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
Write-Host "[4/4] Skipping submodule initialization" -ForegroundColor DarkGray
|
||
|
|
}
|
||
|
|
|
||
|
|
Write-Host ""
|
||
|
|
Write-Host "Setup complete" -ForegroundColor Green
|
||
|
|
Write-Host ""
|
||
|
|
Write-Host "Next steps:"
|
||
|
|
Write-Host " 1. Open PowerToys.slnx in Visual Studio 2022"
|
||
|
|
Write-Host " 2. If prompted to install additional components, click Install"
|
||
|
|
Write-Host " 3. Build the solution (Ctrl+Shift+B)"
|
||
|
|
Write-Host ""
|
||
|
|
Write-Host "Or build from command line:"
|
||
|
|
Write-Host " .\tools\build\build.ps1" -ForegroundColor DarkGray
|
||
|
|
Write-Host ""
|