dist/Export-WindowsUpdateTools.ps1
|
<#
.SYNOPSIS Package the WindowsUpdateTools module into a distributable ZIP. .DESCRIPTION Reads the module manifest to determine version and creates a ZIP archive of the module directory suitable for copying to another computer. The ZIP contains the full module folder structure (Public/Private files and the .psd1 manifest). .PARAMETER ModuleRoot Path to the WindowsUpdateTools module folder. Defaults to the parent directory of this script. .PARAMETER OutputDirectory Where to place the generated ZIP. Defaults to the current 'dist' directory. .PARAMETER Force Overwrite existing archive if present. .EXAMPLE .\Export-WindowsUpdateTools.ps1 .EXAMPLE .\Export-WindowsUpdateTools.ps1 -Force #> [CmdletBinding()] param( [string]$ModuleRoot = (Split-Path -Parent (Split-Path -Parent $MyInvocation.MyCommand.Path)), [string]$OutputDirectory = (Split-Path -Parent $MyInvocation.MyCommand.Path), [switch]$Force ) if (-not (Test-Path $ModuleRoot)) { throw "Module root not found: $ModuleRoot" } Write-Host "Packaging WindowsUpdateTools module..." -ForegroundColor Cyan Write-Host "Module source: $ModuleRoot" -ForegroundColor Gray $psd1 = Join-Path $ModuleRoot 'WindowsUpdateTools.psd1' if (-not (Test-Path $psd1)) { throw "Module manifest not found at: $psd1" } # Read version from manifest try { $manifestData = Import-PowerShellDataFile -Path $psd1 -ErrorAction Stop $version = $manifestData.ModuleVersion } catch { # Fallback: parse manually if Import-PowerShellDataFile fails $content = Get-Content -Path $psd1 -Raw if ($content -match "ModuleVersion\s*=\s*'([^']+)'") { $version = $matches[1] } else { $version = '0.0.0' Write-Warning "Could not determine module version from manifest" } } if (-not $OutputDirectory) { $OutputDirectory = Split-Path -Parent $MyInvocation.MyCommand.Path } if (-not (Test-Path $OutputDirectory)) { New-Item -Path $OutputDirectory -ItemType Directory -Force | Out-Null } $moduleName = (Split-Path $ModuleRoot -Leaf) $zipPath = Join-Path $OutputDirectory "${moduleName}-$version.zip" Write-Host "Version: $version" -ForegroundColor Gray Write-Host "Output: $zipPath" -ForegroundColor Gray if ((Test-Path $zipPath) -and -not $Force) { Write-Host "Archive already exists: $zipPath" -ForegroundColor Yellow return $zipPath } # Create temporary staging folder to ensure ZIP contains top-level module folder $temp = Join-Path ([System.IO.Path]::GetTempPath()) ([System.Guid]::NewGuid().ToString()) New-Item -Path $temp -ItemType Directory -Force | Out-Null $staging = Join-Path $temp $moduleName # Ensure staging subfolder exists before copying; Copy-Item will fail if destination is a file New-Item -Path $staging -ItemType Directory -Force | Out-Null # Use -Container to preserve the folder structure and guard against copying into an existing file # Exclude the 'dist' folder to avoid including old exports try { Get-ChildItem -Path $ModuleRoot -Force | Where-Object { $_.Name -ne 'dist' } | ForEach-Object { Copy-Item -Path $_.FullName -Destination $staging -Recurse -Force -ErrorAction Stop } } catch { # If copy fails, attempt a more granular copy to avoid container/leaf conflicts Get-ChildItem -Path $ModuleRoot -Force | Where-Object { $_.Name -ne 'dist' } | ForEach-Object { $src = $_.FullName $dest = Join-Path $staging $_.Name if ($_.PSIsContainer) { Copy-Item -Path $src -Destination $dest -Recurse -Force -ErrorAction SilentlyContinue } else { Copy-Item -Path $src -Destination $dest -Force -ErrorAction SilentlyContinue } } } try { if (Test-Path $zipPath) { Remove-Item -Path $zipPath -Force } Compress-Archive -Path $staging -DestinationPath $zipPath -Force Write-Host "Created archive: $zipPath" -ForegroundColor Green return $zipPath } finally { Remove-Item -Path $temp -Recurse -Force -ErrorAction SilentlyContinue } |