Private/Set-NixEnvironmentVariable.ps1
# use all caps for the $ENV: prefix to avoid capitalization issues # this function will strictly be used in linux environments # this function will set an environment variable in the /etc/environment file # this private function will not be called, as the logic is handled in the public function Set-EnvironmentVariable if ($IsLinux) { function Set-EnvironmentVariable { param( [Parameter(Mandatory = $true)] [string]$Name, [Parameter(Mandatory = $true)] [string]$Value ) begin { Write-Debug "[Begin Set-NixEnvironmentVariable]" $environmentFile = "/etc/environment" #region functions # function to test for root function Test-Root { $isRoot = $false $userId = . id -u if ($userId -eq 0) { $isRoot = $true } return $isRoot } # function to parse te environment file function Read-EnvironmentFile { param( [Parameter(Mandatory = $true, ValueFromPipeline = $true)] [string]$EnvironmentFile ) $environmentVariables = [System.Collections.Specialized.OrderedDictionary]::new() $environmentFileContent = Get-Content -Path $EnvironmentFile foreach ($line in $environmentFileContent) { if ($line -match "^(?<name>[A-Z_]+)=(?<value>.*)$") { $environmentVariables.Add($matches.name, $matches.value) # $environmentVariables[$matches.name] = $matches.value } } return $environmentVariables } # function to convert a hashtable to a valid environment file function ConvertTo-EnvironmentFile { [CmdletBinding()] param( [Parameter(Mandatory = $true, ValueFromPipeline = $true)] [System.Collections.Specialized.OrderedDictionary]$EnvironmentVariables ) $stringBuilder = [System.Text.StringBuilder]::new() # iterate over the keys in the order they are listed in the ordered dictionary, and add the resulting environment file content to the string builder foreach ($key in $EnvironmentVariables.Keys) { $null = $stringBuilder.AppendLine("$key=$($EnvironmentVariables[$key])") } return $stringBuilder.ToString() # foreach ($key in $EnvironmentVariables.Keys) { # $environmentFileContent += "$key=$($EnvironmentVariables[$key])" # } # return $environmentFileContent } # function to test if the environment variable already exists function Test-EnvironmentVariableExists { [CmdletBinding()] param( [Parameter(Mandatory = $true, ValueFromPipeline = $true)] [string]$EnvironmentFile, [Parameter(Mandatory = $true)] [string]$Name ) $environmentFileContent = Get-Content -Path $EnvironmentFile foreach ($line in $environmentFileContent) { if ($line -match "^(?<name>[A-Z_]+)=(?<value>.*)$") { if ($matches.name -eq $Name) { Write-Warning "The environment variable $Name already exists in $EnvironmentFile" return $true } } } return $false } # function to add the environment variable to the environment file function Add-EnvironmentVariable { [CmdletBinding()] param( [Parameter(Mandatory = $true, ValueFromPipeline = $true)] [string]$EnvironmentFile, [Parameter(Mandatory = $true)] [string]$Name, [Parameter(Mandatory = $true)] [string]$Value ) $environmentFileContent = Get-Content -Path $EnvironmentFile $environmentFileContent += "`n$Name=$Value" Set-Content -Path $EnvironmentFile -Value $environmentFileContent } # function to update the environment variable in the environment file function Update-EnvironmentVariable { [CmdletBinding()] param( [Parameter(Mandatory = $true, ValueFromPipeline = $true)] [string]$EnvironmentFile, [Parameter(Mandatory = $true)] [string]$Name, [Parameter(Mandatory = $true)] [string]$Value ) $environmentFileContent = Get-Content -Path $EnvironmentFile foreach ($line in $environmentFileContent) { if ($line -match "^(?<name>[A-Z_]+)=(?<value>.*)$") { if ($matches.name -eq $Name) { $line = "$Name=$Value" } } } Set-Content -Path $EnvironmentFile -Value $environmentFileContent } # a function to check the differences between two environment files function Compare-EnvironmentFiles { [CmdletBinding()] param( [Parameter(Mandatory = $true, ValueFromPipeline = $true)] [string]$EnvironmentFile1, [Parameter(Mandatory = $true)] [string]$EnvironmentFile2 ) $environmentFile1Content = Get-Content -Path $EnvironmentFile1 $environmentFile2Content = Get-Content -Path $EnvironmentFile2 $environmentFile1Content | Compare-Object -ReferenceObject $environmentFile2Content } #endregion functions if (!(Test-Root)) { Write-Error "This script must be run as root" break } # create a backup in the user's home directory $backupFile = "$ENV:HOME/environment.bak" try { Copy-Item -Path $environmentFile -Destination $backupFile -Force } catch { Write-Warning "Unable to create backup of $environmentFile" break } # read the environment file into an ordered dictionary $environmentVariables = Read-EnvironmentFile -EnvironmentFile $environmentFile # test if the environment variable already exists $environmentVariableExists = Test-EnvironmentVariableExists -EnvironmentFile $environmentFile -Name $Name } process { Write-Debug "[Process Set-NixEnvironmentVariable]" # if the environment variable already exists, update it if ($environmentVariableExists) { try { Update-EnvironmentVariable -EnvironmentFile $environmentFile -Name $Name -Value $Value } catch { Write-Warning "Unable to update environment variable $Name in $environmentFile" Write-Warning $PSItem.Exception.Message Write-Warning "if the environment variable is not set correctly, you can restore the backup file at $backupFile" break } } else { # if the environment variable does not exist, add it try { Add-EnvironmentVariable -EnvironmentFile $environmentFile -Name $Name -Value $Value } catch { Write-Warning "Unable to add environment variable $Name in $environmentFile" Write-Warning $PSItem.Exception.Message Write-Warning "if the environment variable is not set correctly, you can restore the backup file at $backupFile" break } } } end { Write-Debug "[End Set-NixEnvironmentVariable]" # clean up backup file if the only difference is the new variable $differences = Compare-EnvironmentFiles -EnvironmentFile1 $environmentFile -EnvironmentFile2 $backupFile if ($differences.Count -eq 1) { Remove-Item -Path $backupFile } else { Write-Warning "The environment file $environmentFile has been updated" Write-Warning "if the environment variable is not set correctly, you can restore the backup file at $backupFile" } } } } |