Support/Package/Execution/Eigenverft.Manifested.Sandbox.Package.PowerShellModule.ps1
|
<#
Eigenverft.Manifested.Sandbox.Package.PowerShellModule #> $script:PackagePowerShellModuleExecutionRoot = $PSScriptRoot function Get-PackageWindowsPowerShellPath { [CmdletBinding()] param() $systemRoot = if ([string]::IsNullOrWhiteSpace($env:SystemRoot)) { [Environment]::GetFolderPath('Windows') } else { [string]$env:SystemRoot } $powerShellPath = [System.IO.Path]::GetFullPath((Join-Path $systemRoot 'System32\WindowsPowerShell\v1.0\powershell.exe')) if (-not (Test-Path -LiteralPath $powerShellPath -PathType Leaf)) { throw "Windows PowerShell 5.1 executable '$powerShellPath' was not found." } return $powerShellPath } function Get-PackagePowerShellModuleHelperScriptPath { [CmdletBinding()] param() $helperPath = [System.IO.Path]::GetFullPath((Join-Path $script:PackagePowerShellModuleExecutionRoot 'Invoke-PackagePowerShellModuleInstall.ps1')) if (-not (Test-Path -LiteralPath $helperPath -PathType Leaf)) { throw "PowerShell module installer helper '$helperPath' was not found." } return $helperPath } function Get-PackagePowerShellModuleInstallOperation { [CmdletBinding()] param( [Parameter(Mandatory = $true)] [psobject]$PackageResult ) $install = Get-PackageAssignedInstallOperation -Release $PackageResult.Package if (-not $install -or -not [string]::Equals([string]$install.kind, 'powershellModuleInstaller', [System.StringComparison]::OrdinalIgnoreCase)) { throw "Package '$($PackageResult.DefinitionId)' is not configured with packageOperations.assigned.install.kind powershellModuleInstaller." } foreach ($requiredProperty in @('moduleName', 'requiredVersion')) { if (-not $install.PSObject.Properties[$requiredProperty] -or [string]::IsNullOrWhiteSpace([string]$install.$requiredProperty)) { throw "Package '$($PackageResult.DefinitionId)' powershellModuleInstaller requires packageOperations.assigned.install.$requiredProperty." } } return $install } function New-PackagePowerShellModuleRequest { [CmdletBinding()] param( [Parameter(Mandatory = $true)] [ValidateSet('Check', 'Install')] [string]$Operation, [Parameter(Mandatory = $true)] [psobject]$PackageResult, [Parameter(Mandatory = $true)] [psobject]$Install, [Parameter(Mandatory = $true)] [string]$StageDirectory, [Parameter(Mandatory = $true)] [string]$NugetDirectory, [Parameter(Mandatory = $true)] [string]$ProviderDirectory ) $scope = if ($Install.PSObject.Properties['scope'] -and -not [string]::IsNullOrWhiteSpace([string]$Install.scope)) { [string]$Install.scope } else { 'CurrentUser' } $allowClobber = if ($Install.PSObject.Properties['allowClobber']) { [bool]$Install.allowClobber } else { $false } $skipPublisherCheck = if ($Install.PSObject.Properties['skipPublisherCheck']) { [bool]$Install.skipPublisherCheck } else { $false } $repositoryName = 'EVFLocal_{0}' -f ([Guid]::NewGuid().ToString('N').Substring(0, 12)) return [pscustomobject]@{ operation = $Operation definitionId = [string]$PackageResult.DefinitionId packageId = [string]$PackageResult.PackageId moduleName = [string]$Install.moduleName requiredVersion = [string]$Install.requiredVersion scope = $scope allowClobber = $allowClobber skipPublisherCheck = $skipPublisherCheck requireNuGetProvider = if ($Install.PSObject.Properties['requireNuGetProvider']) { [bool]$Install.requireNuGetProvider } else { $false } repositoryName = $repositoryName stageDirectory = [System.IO.Path]::GetFullPath($StageDirectory) nugetDirectory = [System.IO.Path]::GetFullPath($NugetDirectory) providerDirectory = [System.IO.Path]::GetFullPath($ProviderDirectory) } } function Invoke-PackagePowerShellModuleHelper { [CmdletBinding()] param( [Parameter(Mandatory = $true)] [psobject]$PackageResult, [AllowNull()] [psobject]$Install, [ValidateSet('Check', 'Install')] [string]$Operation = 'Install' ) if (-not $Install) { $Install = Get-PackagePowerShellModuleInstallOperation -PackageResult $PackageResult } foreach ($requiredProperty in @('moduleName', 'requiredVersion')) { if (-not $Install.PSObject.Properties[$requiredProperty] -or [string]::IsNullOrWhiteSpace([string]$Install.$requiredProperty)) { throw "Package '$($PackageResult.DefinitionId)' PowerShell module helper requires $requiredProperty." } } if ([string]::IsNullOrWhiteSpace([string]$PackageResult.PackageInstallStageDirectory)) { throw "Package '$($PackageResult.DefinitionId)' powershellModuleInstaller requires a package install stage directory." } $stageDirectory = [System.IO.Path]::GetFullPath([string]$PackageResult.PackageInstallStageDirectory) if ($Operation -eq 'Install') { if ([string]::IsNullOrWhiteSpace([string]$PackageResult.PackageFilePath) -or -not (Test-Path -LiteralPath $PackageResult.PackageFilePath -PathType Leaf)) { throw "Package '$($PackageResult.DefinitionId)' powershellModuleInstaller requires a staged .nupkg package file." } Remove-PathIfExists -Path $stageDirectory | Out-Null } $null = New-Item -ItemType Directory -Path $stageDirectory -Force $nugetDirectory = [System.IO.Path]::GetFullPath((Join-Path $stageDirectory 'Nuget')) $providerDirectory = [System.IO.Path]::GetFullPath((Join-Path $stageDirectory 'Provider')) $null = New-Item -ItemType Directory -Path $nugetDirectory -Force $null = New-Item -ItemType Directory -Path $providerDirectory -Force if ($Operation -eq 'Install') { $targetPackageFile = [System.IO.Path]::GetFullPath((Join-Path $nugetDirectory (Split-Path -Leaf ([string]$PackageResult.PackageFilePath)))) $null = Copy-FileToPath -SourcePath ([string]$PackageResult.PackageFilePath) -TargetPath $targetPackageFile -Overwrite } $requestPath = [System.IO.Path]::GetFullPath((Join-Path $stageDirectory 'powershell-module-install-request.json')) $resultPath = [System.IO.Path]::GetFullPath((Join-Path $stageDirectory 'powershell-module-install-result.json')) if (Test-Path -LiteralPath $resultPath -PathType Leaf) { Remove-Item -LiteralPath $resultPath -Force } $request = New-PackagePowerShellModuleRequest -Operation $Operation -PackageResult $PackageResult -Install $Install -StageDirectory $stageDirectory -NugetDirectory $nugetDirectory -ProviderDirectory $providerDirectory $request | ConvertTo-Json -Depth 10 | Set-Content -LiteralPath $requestPath -Encoding UTF8 $timeoutSec = if ($Install.PSObject.Properties['timeoutSec'] -and [int]$Install.timeoutSec -gt 0) { [int]$Install.timeoutSec } else { 600 } $powerShellPath = Get-PackageWindowsPowerShellPath $helperScriptPath = Get-PackagePowerShellModuleHelperScriptPath $commandArguments = @( '-NoLogo' '-NoProfile' '-NonInteractive' '-ExecutionPolicy' 'Bypass' '-File' $helperScriptPath '-RequestPath' $requestPath '-ResultPath' $resultPath ) Write-PackageExecutionMessage -Message ("[STATE] PowerShell module helper operation='{0}', module='{1}', version='{2}'." -f $Operation, [string]$Install.moduleName, [string]$Install.requiredVersion) Write-PackageExecutionMessage -Message ("[PATH] PowerShell module helper: {0}" -f $helperScriptPath) Write-PackageExecutionMessage -Message ("[PATH] PowerShell module local repository: {0}" -f $nugetDirectory) # Install: keep Hidden to avoid flashing consoles. Check: use Normal — Start-Process -WindowStyle Hidden # has been observed to yield exit code 0xFFFD0000 (-196608) on some hosts (e.g. WDAG) before the script runs. $helperWindowStyle = if ($Operation -eq 'Check') { 'Normal' } else { 'Hidden' } $installerResult = Invoke-PackageInstallerCommand ` -PackageResult $PackageResult ` -CommandPath $powerShellPath ` -CommandArguments @($commandArguments) ` -WorkingDirectory $stageDirectory ` -TimeoutSec $timeoutSec ` -SuccessExitCodes @(0) ` -RestartExitCodes @() ` -TargetKind 'powershellModule' ` -InstallerKind 'powershellModuleInstaller' ` -UiMode 'silent' ` -LogPath $null ` -ElevationMode 'none' ` -WindowStyle $helperWindowStyle if (-not (Test-Path -LiteralPath $resultPath -PathType Leaf)) { throw "PowerShell module helper did not write result JSON '$resultPath'." } $helperResult = Get-Content -LiteralPath $resultPath -Raw | ConvertFrom-Json if ($helperResult.PSObject.Properties['success'] -and -not [bool]$helperResult.success) { $message = if ($helperResult.PSObject.Properties['errorMessage']) { [string]$helperResult.errorMessage } else { 'unknown helper failure' } throw "PowerShell module helper failed: $message" } return [pscustomobject]@{ HelperResult = $helperResult Installer = $installerResult RequestPath = $requestPath ResultPath = $resultPath NugetDirectory = $nugetDirectory ProviderDirectory = $providerDirectory } } function Test-PackagePowerShellModulePresence { <# .SYNOPSIS Checks for an exact PowerShell module version through the same PS5.1 helper used by the installer. #> [CmdletBinding()] param( [Parameter(Mandatory = $true)] [psobject]$PackageResult, [Parameter(Mandatory = $true)] [string]$Name, [Parameter(Mandatory = $true)] [string]$RequiredVersion, [string]$Scope = 'CurrentUser', [bool]$RequireNuGetProvider = $false ) $install = [pscustomobject]@{ kind = 'powershellModuleInstaller' moduleName = $Name requiredVersion = $RequiredVersion scope = if ([string]::IsNullOrWhiteSpace($Scope)) { 'CurrentUser' } else { $Scope } allowClobber = $false skipPublisherCheck = $false timeoutSec = 600 requireNuGetProvider = $RequireNuGetProvider } $result = Invoke-PackagePowerShellModuleHelper -PackageResult $PackageResult -Install $install -Operation Check return $result.HelperResult } function Install-PackagePowerShellModule { <# .SYNOPSIS Installs an exact PowerShell module version from the staged .nupkg through a local PSRepository. #> [CmdletBinding()] param( [Parameter(Mandatory = $true)] [psobject]$PackageResult ) $install = Get-PackagePowerShellModuleInstallOperation -PackageResult $PackageResult $result = Invoke-PackagePowerShellModuleHelper -PackageResult $PackageResult -Operation Install $helperResult = $result.HelperResult return [pscustomobject]@{ Status = 'Applied' InstallKind = 'powershellModuleInstaller' TargetKind = 'powershellModule' InstallDirectory = $null ReusedExisting = $false ModuleName = [string]$install.moduleName RequiredVersion = [string]$install.requiredVersion InstalledVersion = if ($helperResult.PSObject.Properties['installedVersion']) { [string]$helperResult.installedVersion } else { $null } ModuleBase = if ($helperResult.PSObject.Properties['moduleBase']) { [string]$helperResult.moduleBase } else { $null } Scope = if ($helperResult.PSObject.Properties['scope']) { [string]$helperResult.scope } else { $null } PackageFilePath = $PackageResult.PackageFilePath NugetDirectory = $result.NugetDirectory ProviderDirectory = $result.ProviderDirectory RequestPath = $result.RequestPath ResultPath = $result.ResultPath Installer = $result.Installer } } |