Public/Install-WindowsADK.ps1
|
function Install-WindowsADK { <# .SYNOPSIS Downloads and installs Windows Assessment and Deployment Kit (ADK). .DESCRIPTION The Install-WindowsADK function provides functionality to download and install multiple versions of Windows ADK tool. It supports downloading ADK setup files and installing specific features to a target directory. .PARAMETER Action Specifies the action to perform. Valid values are 'Download', 'Install', or 'Help'. .PARAMETER Version Specifies the Windows ADK version to download or install. If not specified, the function will attempt to detect the OS version and use the appropriate ADK version. .PARAMETER InstallPath Specifies the installation path for Windows ADK. Defaults to 'C:\Tools\ADK'. .PARAMETER Features Specifies which ADK features to install. Defaults to Deployment Tools. .EXAMPLE Install-WindowsADK -Action Download -Version '1709' Downloads Windows ADK version 1709 setup files. .EXAMPLE Install-WindowsADK -Action Install -Version '1607' -InstallPath 'C:\MyTools\ADK' Installs Windows ADK version 1607 to the specified path with default features. .EXAMPLE Install-WindowsADK -Action Install -Version '1809' -Features 'Deployment Tools', 'Windows Performance Toolkit (WPT)' Installs Windows ADK version 1809 with Deployment Tools and Windows Performance Toolkit. .EXAMPLE Install-WindowsADK -Action Install -WhatIf Shows what would be installed without actually performing the installation. .INPUTS None. You cannot pipe objects to Install-WindowsADK. .OUTPUTS [System.Boolean] Returns True if the operation was successful, otherwise False. .NOTES Used Functions: Name ║ Module/Namespace ═════════════════════════════════╬══════════════════════════════ Write-Verbose ║ Microsoft.PowerShell.Utility Write-Error ║ Microsoft.PowerShell.Utility Write-Warning ║ Microsoft.PowerShell.Utility Get-Date ║ Microsoft.PowerShell.Utility Start-Process ║ Microsoft.PowerShell.Management Test-Path ║ Microsoft.PowerShell.Management New-Item ║ Microsoft.PowerShell.Management Invoke-WebRequest ║ Microsoft.PowerShell.Utility Get-FunctionDisplay ║ EguibarIT .NOTES Version: 1.0 DateModified: 27/May/2025 LastModifiedBy: Vicente Rodriguez Eguibar vicente@eguibar.com Eguibar IT http://www.eguibarit.com .LINK https://github.com/vreguibar/EguibarIT/blob/main/Public/Install-WindowsADK.ps1 .COMPONENT Windows Deployment Tools .ROLE Administrator .FUNCTIONALITY Downloads and installs Windows Assessment and Deployment Kit (ADK). #> [CmdletBinding( SupportsShouldProcess = $true, ConfirmImpact = 'High' )] [OutputType([System.Boolean])] param( [Parameter( Mandatory = $true, ValueFromPipeline = $false, ValueFromPipelineByPropertyName = $false, Position = 0, HelpMessage = 'Action to perform: Download, Install, or Help' )] [ValidateSet('Download', 'Install', 'Help')] [String] $Action, [Parameter( Mandatory = $false, ValueFromPipeline = $false, ValueFromPipelineByPropertyName = $false, Position = 1, HelpMessage = 'Windows ADK version to download or install' )] [ValidateSet( '1507', '1511', '1607', '1703', '1709', '1803', '1809', '1903', '1909', '2004', '20H2', '21H1', '21H2', '22H2' )] [String] $Version, [Parameter( Mandatory = $false, ValueFromPipeline = $false, ValueFromPipelineByPropertyName = $false, HelpMessage = 'Installation path for Windows ADK' )] [ValidateNotNullOrEmpty()] [PSDefaultValue( Help = 'Path where Windows ADK will be installed', value = { 'C:\Program Files\ADK' } )] [String] $InstallPath = 'C:\Program Files\ADK', [Parameter( Mandatory = $false, ValueFromPipeline = $false, ValueFromPipelineByPropertyName = $false, HelpMessage = 'ADK features to install' )] [ValidateSet( 'Application Compatibility Toolkit (ACT)', 'Deployment Tools', 'Windows Preinstallation Environment (Windows PE)', 'User State Migration Tool', 'Volume Activation Management Tool (VAMT)', 'Windows Performance Toolkit (WPT)', 'Windows Assessment Toolkit', 'Windows Assessment Services — Client', 'Windows Assessment Services', 'Microsoft SQL Server 2012 Express', '.NET Framework' )] [PSDefaultValue( Help = 'Default is "Deployment Tools"', value = { @('Deployment Tools') } )] [String[]] $Features = @('Deployment Tools') ) Begin { Set-StrictMode -Version Latest # Display function header if variables exist if ($null -ne $Variables -and $null -ne $Variables.Header) { $txt = ($Variables.Header -f (Get-Date).ToString('dd/MMM/yyyy'), $MyInvocation.Mycommand, (Get-FunctionDisplay -Hashtable $PsBoundParameters -Verbose:$False) ) Write-Verbose -Message $txt } #end If ############################## # Variables Definition # ADK version to download URL mapping [hashtable]$AdkUrls = @{} $AdkUrls.Add('1507', 'https://go.microsoft.com/fwlink/p/?LinkId=526740') $AdkUrls.Add('1511', 'https://go.microsoft.com/fwlink/p/?LinkId=526740') $AdkUrls.Add('1607', 'https://go.microsoft.com/fwlink/p/?LinkId=845542') $AdkUrls.Add('1703', 'https://go.microsoft.com/fwlink/p/?LinkId=845542') $AdkUrls.Add('1709', 'https://go.microsoft.com/fwlink/p/?linkid=859206') $AdkUrls.Add('1803', 'https://go.microsoft.com/fwlink/?linkid=873065') $AdkUrls.Add('1809', 'https://go.microsoft.com/fwlink/?linkid=2026036') $AdkUrls.Add('1903', 'https://go.microsoft.com/fwlink/?linkid=2086042') $AdkUrls.Add('1909', 'https://go.microsoft.com/fwlink/?linkid=2120254') $AdkUrls.Add('2004', 'https://go.microsoft.com/fwlink/?linkid=2120254') $AdkUrls.Add('20H2', 'https://go.microsoft.com/fwlink/?linkid=2120254') $AdkUrls.Add('21H1', 'https://go.microsoft.com/fwlink/?linkid=2165884') $AdkUrls.Add('21H2', 'https://go.microsoft.com/fwlink/?linkid=2165884') $AdkUrls.Add('22H2', 'https://go.microsoft.com/fwlink/?linkid=2196127') # Windows version to ADK mapping based on build numbers [hashtable]$WindowsToAdkMapping = @{} $WindowsToAdkMapping.Add('10240', '1507') # Windows 10 1507 $WindowsToAdkMapping.Add('10586', '1511') # Windows 10 1511 $WindowsToAdkMapping.Add('14393', '1607') # Windows 10 1607 / Server 2016 $WindowsToAdkMapping.Add('15063', '1703') # Windows 10 1703 $WindowsToAdkMapping.Add('16299', '1709') # Windows 10 1709 $WindowsToAdkMapping.Add('17134', '1803') # Windows 10 1803 $WindowsToAdkMapping.Add('17763', '1809') # Windows 10 1809 / Server 2019 $WindowsToAdkMapping.Add('18362', '1903') # Windows 10 1903 $WindowsToAdkMapping.Add('18363', '1909') # Windows 10 1909 $WindowsToAdkMapping.Add('19041', '2004') # Windows 10 2004 $WindowsToAdkMapping.Add('19042', '20H2') # Windows 10 20H2 $WindowsToAdkMapping.Add('19043', '21H1') # Windows 10 21H1 $WindowsToAdkMapping.Add('19044', '21H2') # Windows 10 21H2 $WindowsToAdkMapping.Add('19045', '22H2') # Windows 10 22H2 $WindowsToAdkMapping.Add('20348', '21H2') # Server 2022 $WindowsToAdkMapping.Add('22000', '21H2') # Windows 11 21H2 $WindowsToAdkMapping.Add('22621', '22H2') # Windows 11 22H2 $WindowsToAdkMapping.Add('22631', '22H2') # Windows 11 23H2 $WindowsToAdkMapping.Add('26100', '22H2') # Windows 11 24H2 # Features to install [hashtable]$FeaturesToInstall = @{} $FeaturesToInstall.Add('Application Compatibility Toolkit (ACT)', 'OptionId.ApplicationCompatibilityToolkit') $FeaturesToInstall.Add('Deployment Tools', 'OptionId.DeploymentTools') $FeaturesToInstall.Add('Windows Preinstallation Environment (Windows PE)', 'OptionId.WindowsPreinstallationEnvironment') $FeaturesToInstall.Add('User State Migration Tool', 'OptionId.UserStateMigrationTool') $FeaturesToInstall.Add('Volume Activation Management Tool (VAMT)', 'OptionId.VolumeActivationManagementTool') $FeaturesToInstall.Add('Windows Performance Toolkit (WPT)', 'OptionId.WindowsPerformanceToolkit') $FeaturesToInstall.Add('Windows Assessment Toolkit', 'OptionId.WindowsAssessmentToolkit') $FeaturesToInstall.Add('Windows Assessment Services — Client', 'OptionId.WindowsAssessmentServicesClient') $FeaturesToInstall.Add('Windows Assessment Services', 'OptionId.WindowsAssessmentServices') $FeaturesToInstall.Add('Microsoft SQL Server 2012 Express', 'OptionId.SqlExpress2012') $FeaturesToInstall.Add('.NET Framework', 'OptionId.Netfx') # Result variable [boolean]$Result = $false } #end Begin Process { try { # If no version specified, try to detect from OS if (-not $Version) { $OsBuild = [System.Environment]::OSVersion.Version.Build.ToString() Write-Verbose -Message ('Detected OS build: {0}' -f $OsBuild) if ($WindowsToAdkMapping.ContainsKey($OsBuild)) { $Version = $WindowsToAdkMapping[$OsBuild] Write-Verbose -Message ('Mapped OS build {0} to ADK version {1}' -f $OsBuild, $Version) } else { Write-Warning -Message ('Unknown OS build {0}, defaulting to latest ADK version (22H2)' -f $OsBuild) $Version = '22H2' } #end if-else } #end if switch ($Action) { 'Help' { Write-Output 'Install-WindowsADK - Downloads and installs Windows Assessment and Deployment Kit' Write-Output '' Write-Output 'Available ADK versions:' foreach ($Ver in $AdkUrls.Keys | Sort-Object) { Write-Output (' {0} - {1}' -f $Ver, $AdkUrls[$Ver]) } #end foreach Write-Output '' Write-Output 'Available ADK features:' foreach ($FeatureName in $FeaturesToInstall.Keys | Sort-Object) { Write-Output (' {0}' -f $FeatureName) } #end foreach Write-Output '' Write-Output 'Usage examples:' Write-Output ' Install-WindowsADK -Action Download -Version 1809' Write-Output ' Install-WindowsADK -Action Install -Version 1809 -InstallPath "C:\ADK"' Write-Output ' Install-WindowsADK -Action Install -Features "Deployment Tools", "Windows Performance Toolkit (WPT)"' $Result = $true } #end Help 'Download' { if (-not $AdkUrls.ContainsKey($Version)) { throw ('Unsupported ADK version: {0}' -f $Version) } #end if $DownloadUrl = $AdkUrls[$Version] $SetupFileName = 'adksetup.exe' $DownloadPath = Join-Path -Path $env:TEMP -ChildPath $SetupFileName Write-Verbose -Message ('Downloading ADK {0} from {1}' -f $Version, $DownloadUrl) if ($PSCmdlet.ShouldProcess($DownloadUrl, 'Download ADK setup')) { try { $SplatWebRequest = @{ Uri = $DownloadUrl OutFile = $DownloadPath ErrorAction = 'Stop' } Invoke-WebRequest @SplatWebRequest if (Test-Path -Path $DownloadPath) { Write-Verbose -Message ('Successfully downloaded ADK setup to: {0}' -f $DownloadPath) $Result = $true } else { Write-Error -Message 'Download completed but file not found' } #end if-else } catch { Write-Error -Message ('Failed to download ADK: {0}' -f $_.Exception.Message) } #end try-catch } #end if } #end Download 'Install' { if (-not $AdkUrls.ContainsKey($Version)) { throw ('Unsupported ADK version: {0}' -f $Version) } #end if # Ensure installation directory exists if (-not (Test-Path -Path $InstallPath)) { Write-Verbose -Message ('Creating installation directory: {0}' -f $InstallPath) if ($PSCmdlet.ShouldProcess($InstallPath, 'Create installation directory')) { try { New-Item -Path $InstallPath -ItemType Directory -Force -ErrorAction Stop | Out-Null } catch { Write-Error -Message ('Failed to create installation directory: {0}' -f $_.Exception.Message) return $false } #end try-catch } #end if } #end if $DownloadUrl = $AdkUrls[$Version] $SetupFileName = 'adksetup.exe' $SetupPath = Join-Path -Path $env:TEMP -ChildPath $SetupFileName # Download ADK if not already present if (-not (Test-Path -Path $SetupPath)) { Write-Verbose -Message ('Downloading ADK {0} setup' -f $Version) try { $SplatWebRequest = @{ Uri = $DownloadUrl OutFile = $SetupPath ErrorAction = 'Stop' } Invoke-WebRequest @SplatWebRequest } catch { Write-Error -Message ('Failed to download ADK setup: {0}' -f $_.Exception.Message) return $false } #end try-catch } #end if # Install ADK Write-Verbose -Message ('Installing ADK {0} to {1}' -f $Version, $InstallPath) $InstallArgs = @('/quiet', '/installpath', $InstallPath) # Add features to install foreach ($Feature in $Features) { # Map user-friendly names to option IDs if ($FeaturesToInstall.ContainsKey($Feature)) { $OptionId = $FeaturesToInstall[$Feature] Write-Verbose -Message ('Adding feature: {0} ({1})' -f $Feature, $OptionId) } else { # Assume it's already an option ID $OptionId = $Feature Write-Verbose -Message ('Adding feature option ID: {0}' -f $OptionId) } #end if-else $InstallArgs += '/features' $InstallArgs += $OptionId } #end foreach if ($PSCmdlet.ShouldProcess($InstallPath, ('Install Windows ADK {0}' -f $Version))) { try { $SplatProcess = @{ FilePath = $SetupPath ArgumentList = $InstallArgs Wait = $true NoNewWindow = $true PassThru = $true ErrorAction = 'Stop' } $InstallProcess = Start-Process @SplatProcess if ($InstallProcess.ExitCode -eq 0) { Write-Verbose -Message ('Successfully installed Windows ADK {0}' -f $Version) $Result = $true } else { Write-Error -Message ('ADK installation failed with exit code: {0}' -f $InstallProcess.ExitCode) } #end if-else } catch { Write-Error -Message ('Failed to start ADK installation: {0}' -f $_.Exception.Message) } #end try-catch } #end if } #end Install } #end switch } catch { Write-Error -Message ('Error in Install-WindowsADK: {0}' -f $_.Exception.Message) $Result = $false } #end try-catch } #end Process End { # Display function footer if variables exist if ($null -ne $Variables -and $null -ne $Variables.Footer) { $txt = ($Variables.Footer -f $MyInvocation.InvocationName, 'processing Windows ADK installation.' ) Write-Verbose -Message $txt } #end If return $Result } #end End } #end function Install-WindowsADK |