PackageModel/Support/ExecutionEngine/Eigenverft.Manifested.Sandbox.PackageModel.ExecutionEngine.PathRegistration.ps1
|
<#
Eigenverft.Manifested.Sandbox.PackageModel.ExecutionEngine.PathRegistration #> function Get-EnvironmentVariableValue { <# .SYNOPSIS Reads an environment variable for one target scope. .DESCRIPTION Returns the current environment variable value for the requested Process, User, or Machine target. #> [CmdletBinding()] param( [Parameter(Mandatory = $true)] [string]$Name, [Parameter(Mandatory = $true)] [ValidateSet('Process', 'User', 'Machine')] [string]$Target ) return [Environment]::GetEnvironmentVariable($Name, $Target) } function Set-EnvironmentVariableValue { <# .SYNOPSIS Writes an environment variable for one target scope. .DESCRIPTION Persists the requested environment variable value to the Process, User, or Machine target scope. #> [CmdletBinding()] param( [Parameter(Mandatory = $true)] [string]$Name, [AllowNull()] [string]$Value, [Parameter(Mandatory = $true)] [ValidateSet('Process', 'User', 'Machine')] [string]$Target ) [Environment]::SetEnvironmentVariable($Name, $Value, $Target) } function Get-NormalizedPathEntry { [CmdletBinding()] param( [AllowNull()] [string]$PathEntry ) if ([string]::IsNullOrWhiteSpace($PathEntry)) { return $null } $expandedEntry = [Environment]::ExpandEnvironmentVariables($PathEntry.Trim()) -replace '/', '\' if ([string]::IsNullOrWhiteSpace($expandedEntry)) { return $null } if ([System.IO.Path]::IsPathRooted($expandedEntry)) { try { return [System.IO.Path]::GetFullPath($expandedEntry).TrimEnd('\') } catch { return $expandedEntry.TrimEnd('\') } } return $expandedEntry.TrimEnd('\') } function Resolve-PathRegistrationDirectory { <# .SYNOPSIS Resolves the directory that should be added to PATH. .DESCRIPTION Turns a raw source path into the concrete directory entry that should be registered in PATH. Existing files resolve to their parent directory. #> [CmdletBinding()] param( [Parameter(Mandatory = $true)] [string]$SourcePath, [string]$SourceKind ) $resolvedSourcePath = [System.IO.Path]::GetFullPath($SourcePath) if ($SourceKind -in @('commandEntryPoint', 'appEntryPoint', 'shim')) { return [System.IO.Path]::GetFullPath((Split-Path -Parent $resolvedSourcePath)) } if (Test-Path -LiteralPath $resolvedSourcePath -PathType Leaf) { return [System.IO.Path]::GetFullPath((Split-Path -Parent $resolvedSourcePath)) } return [System.IO.Path]::GetFullPath($resolvedSourcePath) } function Add-PathEntry { [CmdletBinding()] param( [AllowNull()] [string]$CurrentValue, [Parameter(Mandatory = $true)] [string]$DirectoryPath ) $normalizedTargetDirectory = Get-NormalizedPathEntry -PathEntry $DirectoryPath $existingEntries = @() foreach ($entry in @(([string]$CurrentValue) -split ';')) { if ([string]::IsNullOrWhiteSpace($entry)) { continue } $existingEntries += $entry.Trim() } foreach ($entry in @($existingEntries)) { $normalizedEntry = Get-NormalizedPathEntry -PathEntry $entry if ([string]::Equals($normalizedEntry, $normalizedTargetDirectory, [System.StringComparison]::OrdinalIgnoreCase)) { return [pscustomobject]@{ Value = ($existingEntries -join ';') Changed = $false } } } $updatedEntries = @($existingEntries) + @($DirectoryPath) return [pscustomobject]@{ Value = ($updatedEntries -join ';') Changed = $true } } function Remove-PathEntries { [CmdletBinding()] param( [AllowNull()] [string]$CurrentValue, [string[]]$DirectoryPaths ) $normalizedDirectoriesToRemove = @( foreach ($directoryPath in @($DirectoryPaths)) { $normalizedDirectoryPath = Get-NormalizedPathEntry -PathEntry $directoryPath if (-not [string]::IsNullOrWhiteSpace($normalizedDirectoryPath)) { $normalizedDirectoryPath } } ) if (@($normalizedDirectoriesToRemove).Count -eq 0) { return [pscustomobject]@{ Value = [string]$CurrentValue Changed = $false RemovedEntries = @() } } $filteredEntries = New-Object System.Collections.Generic.List[string] $removedEntries = New-Object System.Collections.Generic.List[string] foreach ($entry in @(([string]$CurrentValue) -split ';')) { if ([string]::IsNullOrWhiteSpace($entry)) { continue } $trimmedEntry = $entry.Trim() $normalizedEntry = Get-NormalizedPathEntry -PathEntry $trimmedEntry if ($normalizedEntry -and $normalizedEntry -in $normalizedDirectoriesToRemove) { $removedEntries.Add($trimmedEntry) | Out-Null continue } $filteredEntries.Add($trimmedEntry) | Out-Null } return [pscustomobject]@{ Value = (@($filteredEntries.ToArray()) -join ';') Changed = ($removedEntries.Count -gt 0) RemovedEntries = @($removedEntries.ToArray()) } } function Register-PathEnvironment { <# .SYNOPSIS Registers a directory in PATH for the requested scopes. .DESCRIPTION Updates Process and User PATH for user mode, or Process and Machine PATH for machine mode. Removes any requested cleanup directories before ensuring the active directory is present. #> [CmdletBinding()] param( [Parameter(Mandatory = $true)] [ValidateSet('user', 'machine')] [string]$Mode, [Parameter(Mandatory = $true)] [string]$RegisteredPath, [string[]]$CleanupDirectories ) if ([string]::IsNullOrWhiteSpace($RegisteredPath)) { throw 'PATH registration requires a registered directory path.' } if (-not (Test-Path -LiteralPath $RegisteredPath)) { throw "PATH registration directory '$RegisteredPath' was not found." } $normalizedRegisteredPath = Resolve-PathRegistrationDirectory -SourcePath $RegisteredPath $cleanupDirectoriesToApply = @($CleanupDirectories) $targets = @('Process') if ($Mode -eq 'user') { $targets += 'User' } elseif ($Mode -eq 'machine') { $targets += 'Machine' } $updatedTargets = New-Object System.Collections.Generic.List[string] $cleanedTargets = New-Object System.Collections.Generic.List[string] foreach ($target in @($targets)) { $currentValue = Get-EnvironmentVariableValue -Name 'Path' -Target $target $cleanupResult = Remove-PathEntries -CurrentValue $currentValue -DirectoryPaths $cleanupDirectoriesToApply $updateResult = Add-PathEntry -CurrentValue $cleanupResult.Value -DirectoryPath $normalizedRegisteredPath if ($cleanupResult.Changed -or $updateResult.Changed) { Set-EnvironmentVariableValue -Name 'Path' -Value $updateResult.Value -Target $target $updatedTargets.Add($target) | Out-Null } if ($cleanupResult.Changed) { $cleanedTargets.Add($target) | Out-Null } } return [pscustomobject]@{ Status = if ($updatedTargets.Count -gt 0) { 'Registered' } else { 'AlreadyRegistered' } Mode = $Mode RegisteredPath = $normalizedRegisteredPath CleanupDirectories = @($cleanupDirectoriesToApply) CleanedTargets = @($cleanedTargets.ToArray()) UpdatedTargets = @($updatedTargets.ToArray()) } } |