Carbon.Environment.psm1
|
# Copyright WebMD Health Services # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License #Requires -Version 5.1 Set-StrictMode -Version 'Latest' # Functions should use $script:moduleDirPath as the relative root from which to find things. A published module has its # function appended to this file, while a module in development has its functions in the Functions directory. $script:moduleDirPath = $PSScriptRoot if (-not (Test-Path -Path 'variable:IsWindows')) { $script:IsWindows = $true $script:IsLinux = $script:IsMacOS = $false } # Store each of your module's functions in its own file in the Functions directory. On the build server, your module's # functions will be appended to this file, so only dot-source files that exist on the file system. This allows # developers to work on a module without having to build it first. Grab all the functions that are in their own files. $functionsPath = Join-Path -Path $script:moduleDirPath -ChildPath 'Functions\*.ps1' if( (Test-Path -Path $functionsPath) ) { foreach( $functionPath in (Get-Item $functionsPath) ) { . $functionPath.FullName } } function Assert-Scope { [CmdletBinding()] param( [Parameter(ValueFromPipeline)] [Object] $Scope, [String] $Message ) begin { Set-StrictMode -Version 'Latest' Use-CallerPreference -Cmdlet $PSCmdlet -Session $ExecutionContext.SessionState $writeError = $false $receivedCount = 0 $seenScopes = [Collections.Generic.Hashset[EnvironmentVariableTarget]]::New() } process { if ($null -eq $Scope) { return } if ($Scope -isnot [EnvironmentVariableTarget]) { $msg = "Failed to validate scope ""${Scope}"" because it is a [$($Scope.GetType().FullName)] object, but " + 'we expected [EnvironmentVariableTarget].' Write-Error -Message $msg -ErrorAction Stop return } $receivedCount += 1 # PowerShell and .NET do not support user-level and computer-level environment variables on Linux and macOS. if (-not $IsWindows -and $Scope -ne [EnvironmentVariableTarget]::Process) { $writeError = $true return } if ($seenScopes.Contains($Scope)) { return } $Scope | Write-Output [void]$seenScopes.Add($Scope) } end { # Operate on process-level environment variables by default, if the user specifies no scope. if ($receivedCount -eq 0) { return [EnvironmentVariableTarget]::Process } if ($writeError) { if (-not $Message) { $Message = 'PowerShell and .NET only support user-level and computer-level environment variables on ' + 'Windows.' } Write-Error -Message $Message -ErrorAction $ErrorActionPreference } } } function Remove-CEnvironmentVariable { <# .SYNOPSIS Removes an environment variable. .DESCRIPTION The `Remove-CEnvironmentVariable` function deletes environment variables. Pass the names of the environment variables to delete to the `Name` parameter (or pipe the names into the function). If an environment variable does not exist at that scope, the function writes an error. Otherwise, the environment variable is deleted. By default, operates on the current process's environment variables. PowerShell and .NET do not support user-level and computer-level environment variables. On Windows, use the `Scope` parameter to remove user-level and/or machine-level environment variables. Multiple scopes are accepted. Changes to environment variables are not reflected in running processes, including the current PowerShell session. If you want the removal of the user-level or machine-level environment variable to be reflected in the current process, include `Process` in the list of scopes passed to the `Scope` parameter. To remove a user-level environment variable for a specific user on Windows, pass that user's credentials to the `-Credential` parameter. A PowerShell process is run as that user to remove the environment variable. On Windows, environment variable names are case-insensitive. On Linux and macOS, environment variable names are case-sensitive. .LINK Remove-CEnvironmentVariable .LINK Set-CEnvironmentVariable .LINK Test-CEnvironmentVariable .EXAMPLE Remove-CEnvironmentVariable -Name 'MyEnvironmentVariable' Demonstrates how to remove an environment variable from the current process. In this example, the `MyEnvironmentVariable` is removed. If it doesn't exist, an error is written. .EXAMPLE Remove-CEnvironmentVariable -Name 'SomeComputerVariable' -Scope Machine Demonstrates how to remove a computer-level environment variable. In this example, the `SomeComputerVariable` environment variable is removed from the computer's environment variables. If that computer-level variable doesn't exist, an error is written. .EXAMPLE Remove-CEnvironmentVariable -Name 'SomeUsersVariable' -Scope User Demonstrates how to remove a user-level environment variable for the current user. In this example, the `SomeUsersVariable` environment variable is removed from the current user's environment variables. If it doesn't exist at the user scope, an error is written. .EXAMPLE Remove-CEnvironmentVariable -Name 'SomeUsersVariable' -Scope Process,User Demonstrates how to have the change to a user-level or machine-level environment variable reflected in the current process by including `Process` in the list of scopes passed to `Scope`. .EXAMPLE Remove-CEnvironmentVariable -Name 'SomeUsersVariable' -Credential $user Demonstrates how to remove a user-level environment variable for a specific user. In this example, the `SomeUsersVariable` environment variable is removed from the `$user` user's environment variables. If that user doesn't have a `SomeUsersVariable` environment variable, an error is written. .EXAMPLE 'Var1','Var2' | Remove-CEnvironmentVariable Demonstrates that you can pipe the environment variables to delete to `Remove-CEnvironmentVariable`. #> [CmdletBinding(SupportsShouldProcess, DefaultParameterSetName='ForCurrentUser')] param( # The environment variable to remove. Case-insensitive on Windows, case-sensitive on Linux and macOS. [Parameter(Mandatory, ValueFromPipeline)] [String[]] $Name, # The scopes at which to remove the environment variable. Default is the current process. [Parameter(ParameterSetName='ForCurrentUser')] [EnvironmentVariableTarget[]] $Scope, # Remove an environment variable for a specific user. [Parameter(Mandatory, ParameterSetName='ForSpecificUser')] [pscredential] $Credential ) begin { Set-StrictMode -Version 'Latest' Use-CallerPreference -Cmdlet $PSCmdlet -Session $ExecutionContext.SessionState $userEnvVars = [Collections.Generic.List[string]]::new() $Scope = $Scope | Assert-Scope } process { if ($Credential) { $userEnvVars.AddRange( $Name ) return } foreach ($_name in $Name) { foreach ($_scope in $Scope) { $target = "$($_scope.ToString().ToLowerInvariant())-level environment variable ""${_name}""" if (-not (Test-CEnvironmentVariable -Name $_name -Scope $_scope)) { $msg = "Failed to delete ${target} because it does not exist." Write-Error -Message $msg -ErrorAction $ErrorActionPreference continue } if (-not $PSCmdlet.ShouldProcess($target, "remove")) { continue } Write-Information "Removing ${target}." [Environment]::SetEnvironmentVariable($_name, [NullString]::Value, $_scope) } } } end { if (-not $Credential -or -not $userEnvVars.Count) { return } if (-not $IsWindows) { $msg = 'PowerShell and .NET only support user-level environment variables on Windows.' Write-Error -Message $msg -ErrorAction $ErrorActionPreference return } $parameters = $PSBoundParameters [void]$parameters.Remove('Credential') [void]$parameters.Remove('Name') Start-Job -ScriptBlock { Import-Module -Name (Join-Path -Path $using:moduleDirPath -ChildPath 'Carbon.Environment.psm1') $VerbosePreference = $using:VerbosePreference $ErrorActionPreference = $using:ErrorActionPreference $DebugPreference = $using:DebugPreference $WhatIfPreference = $using:WhatIfPreference $InformationPreference = $using:InformationPreference Remove-CEnvironmentVariable -Name $using:userEnvVars @using:parameters -Scope User } -Credential $Credential | Receive-Job -Wait -AutoRemoveJob } } function Set-CEnvironmentVariable { <# .SYNOPSIS Creates or sets an environment variable. .DESCRIPTION The `Set-CEnvironmentVariable` function creates or sets an environment variable. Pass the name of the environment variable to the `Name` parameter and the value to the `Value` parameter. An environment variable with that name and value is set for the current process. Use the `Scope` parameter to set user-level and/or machine-level variables. Uses `[Environment]::SetEnvironmentVariable` to create the variable if it doesn't exist, or update its value if the variable exists and its value is different from the value being set. By default, creates and sets the current process's environment variables. PowerShell and .NET do not support user-level and computer-level environment variables. On Windows, use the `Scope` parameter to remove user-level and/or machine-level environment variables. Multiple scopes are accepted. Changes to environment variables are not reflected in running processes, including the current PowerShell session. If you want a new or changed user-level or machine-level environment variable to be reflected in the current process, include `Process` in the list of scopes passed to the `Scope` parameter. To create or set an environment variable for a specific user on Windows, pass that user's credentials to the `-Credential` parameter. This will run a PowerShell process that creates or sets the environment variable. Writes an information message for each environment variable created or updated. The message includes the value being set. Use the `Sensitive` switch to omit the value from the information message. On Windows, environment variable names are case-insensitive. On Linux and macOS, environment variable names are case-sensitive. In PowerShell 7.4 and earlier, setting `Value` to an empty string deletes the variable. In newer versions of PowerShell, the variable is set to an empty value. .LINK Remove-CEnvironmentVariable .LINK Test-CEnvironmentVariable .EXAMPLE Set-CEnvironmentVariable -Name 'MyEnvironmentVariable' -Value 'Value1' Demonstrates how to create or set an environemnt variable for the current process. In this example, the current process's `MyEnvironmentVariable` variable is created or set with a value of `Value1`. .EXAMPLE Set-CEnvironmentVariable -Name 'MyEnvironmentVariable' -Value 'Value1' -Scope Machine Demonstrates how to create a computer-level environment variable by including `Machine` in the list of scopes passed to the `Scope` parameter. The current process's environment variables will not have the new or updated environment variable. .EXAMPLE Set-CEnvironmentVariable -Name 'MyEnvironmentVariable' -Value 'Value1' -Scope User Demonstrates how to create a user environment variable by including `User` in the list of scopes passed to the `Scope` parameter. The current process's environment variables will not have the new or updated environment variable. .EXAMPLE Set-CEnvironmentVariable -Name 'MyEnvironmentVariable' -Value 'Value1' -Scope Process,User Demonstrates how to have a change to a user or machine-level environment variable reflected in the current process by including `Process` in the list of scopes passed to the `Scope` parameter. .EXAMPLE Set-CEnvironmentVariable -Name 'SomeUsersEnvironmentVariable' -Value 'SomeValue' -Credential $userCreds Demonstrates how to set an environment variable for a specific user by passing that user's credentials to the `Credential` parameter. .EXAMPLE Set-CEnvironmentVariable -Name 'MySensitiveEnvironmentVariable' -Value 'SecretValue' -Sensitive Demonstrates how to omit the environment variable's value from the information message output by this function. #> [CmdletBinding(SupportsShouldProcess)] param( # The name of environment variable to add/set. Case-insensitive on Windows. Case-sensitive on Linux and macOS. [Parameter(Mandatory)] [String] $Name, # The environment variable's value. In PowerShell 7.4 and earlier, setting this to an empty string deletes the # variable. In newer versions, the variable is created with an empty value. [Parameter(Mandatory)] [AllowEmptyString()] [String] $Value, # The scopes at which to set the variable. Default is the current process. Changes to user-level and # computer-level variables are not reflected in the current process's environment variables unless `Process` is # in this list. [Parameter(ParameterSetName='ForCurrentUser')] [EnvironmentVariableTarget[]] $Scope, [Parameter(Mandatory,ParameterSetName='ForSpecificUser')] # Set an environment variable for a specific user. [pscredential] $Credential, # Don't output the variable's value in information messages. [switch] $Sensitive ) Set-StrictMode -Version 'Latest' Use-CallerPreference -Cmdlet $PSCmdlet -Session $ExecutionContext.SessionState if( $PSCmdlet.ParameterSetName -eq 'ForSpecificUser' ) { if (-not $IsWindows) { $msg = 'PowerShell and .NET only support user-level environment variables on Windows.' Write-Error -Message $msg -ErrorAction $ErrorActionPreference return } $parameters = $PSBoundParameters [void]$parameters.Remove('Credential') $job = Start-Job -ScriptBlock { Import-Module -Name (Join-Path -path $using:moduleDirPath -ChildPath 'Carbon.Environment.psm1' -Resolve) $VerbosePreference = $using:VerbosePreference $ErrorActionPreference = $using:ErrorActionPreference $DebugPreference = $using:DebugPreference $WhatIfPreference = $using:WhatIfPreference $InformationPreference = $using:InformationPreference Set-CEnvironmentVariable @using:parameters -Scope User } -Credential $Credential $job | Wait-Job | Receive-Job $job | Remove-Job -Force -ErrorAction Ignore return } $Scope = $Scope | Assert-Scope foreach ($_scope in $Scope) { # Only set the variable if its value has changed. if ($Value -eq [Environment]::GetEnvironmentVariable($Name, $_scope)) { continue } $target = "$($_scope.ToString().ToLowerInvariant())-level environment variable ""${Name}""" if (-not $PSCmdlet.ShouldProcess($target, "set")) { continue } $valueMsg = " to ""${Value}""" if ($Sensitive) { $valueMsg = '' } Write-Information "Setting ${target}${valueMsg}." [Environment]::SetEnvironmentVariable($Name, $Value, $_scope) } } function Test-CEnvironmentVariable { <# .SYNOPSIS Tests if an environment variable exists. .DESCRIPTION The `Test-CEnvironmentVariable` function tests if an environment variable exists. Pass the name of the variable to the `Name` parameter (or pipe in multiple names). If a variable with that name exists in the current process, returns `$true`. Otherwise, returns `$false`. By default, checks in the current process's environment variables. PowerShell and .NET do not support user-level and computer-level environment variables. On Windows, use the `Scope` parameter to check if user-level or computer-level environment variables exist. To check if a specific user has an environment variable on Windows, pass that user's credentials to the `Credential` parameter. On Windows, environment variable names are case-insenstive. On Linux and macOS, they are case-sensitive. .EXAMPLE Test-CEnvironmentVariable -Name 'PATH' Demonstrates how to check that an environment variable exists. In this case, will return `$true` if the `PATH` environment variable exists at any scope. .EXAMPLE Test-CEnvironmentVariable -Name 'MY_VAR' -Scope User Demonstrates how to check that an environment variable exists at a specific scope. In this case, will return `$true` if the user has a `MY_VAR` environment variable. .EXAMPLE 'PATH' | Test-CEnvironmentVariable Demonstrates that you can pipe environment variable names to `Test-CEnvironmentVariable`. #> [CmdletBinding(DefaultParameterSetName='CurrentUser')] param( # The name of the environment variable to check. Case-insensitive on Windows. Cse-sensitive on Linux and MacOS. [Parameter(Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName)] [String] $Name, # The specific scope to check. By default, checks the current process. [Parameter(ParameterSetName='CurrentUser')] [EnvironmentVariableTarget] $Scope, [Parameter(Mandatory, ParameterSetName='ForUser')] [pscredential] $Credential ) begin { Set-StrictMode -Version 'Latest' Use-CallerPreference -Cmdlet $PSCmdlet -Session $ExecutionContext.SessionState $userEnvVars = [Collections.Generic.List[String]]::New() $validScope = $Scope | Assert-Scope } process { if ($Credential) { $userEnvVars.Add($Name) return } if ($null -eq $validScope) { return } return ($null -ne [Environment]::GetEnvironmentVariable($Name, $validScope)) } end { if (-not $Credential -or -not $userEnvVars.Count) { return } if (-not $IsWindows) { $msg = 'PowerShell and .NET only support user-level environment variables on Windows.' Write-Error -Message $msg -ErrorAction $ErrorActionPreference return } $parameters = $PSBoundParameters [void]$parameters.Remove('Credential') [void]$parameters.Remove('Name') Start-Job -ScriptBlock { Import-Module -Name (Join-Path -path $using:moduleDirPath -ChildPath 'Carbon.Environment.psm1' -Resolve) $VerbosePreference = $using:VerbosePreference $ErrorActionPreference = $using:ErrorActionPreference $DebugPreference = $using:DebugPreference $WhatIfPreference = $using:WhatIfPreference $InformationPreference = $using:InformationPreference $using:userEnvVars | Test-CEnvironmentVariable @using:parameters -Scope User } -Credential $Credential | Receive-Job -Wait -AutoRemoveJob | Write-Output } } function Uninstall-CEnvironmentVariable { <# .SYNOPSIS Removes an environment variable if it exists. .DESCRIPTION The `Uninstall-CEnvironmentVariable` function deletes environment variables, but only if they exist. Pass the names of the environment variables to delete to the `Name` parameter (or pipe in the names). Each environment variable that exists is deleted. No errors are written if an environment variable doesn't exist. By default, removes the current process's environment variables. PowerShell and .NET do not support user-level and computer-level environment variables. On Windows, use the `Scope` parameter to remove user-level and/or machine-level environment variables. Multiple scopes are accepted. Changes to environment variables are not reflected in running processes, including the current PowerShell session. If you want the removal of user-level and/or machine-level environment variable to be reflected in the current process, include `Process` in the list of scopes passed to the `Scope` parameter. To remove a specific user's user-level environment variable on Windows, pass that user's credentials to the `-Credential` parameter. On Windows, environment variable names are case-insensitive. On Linux and macOS, environment variable names are case-sensitive. .LINK Remove-CEnvironmentVariable .LINK Set-CEnvironmentVariable .LINK Test-CEnvironmentVariable .EXAMPLE Uninstall-CEnvironmentVariable -Name 'MyEnvironmentVariable' Demonstrates how to remove an environment variable from the current process if it exists. In this case, will remove the `MyEnvironmentVariable` environment variable, if it exists. .EXAMPLE Uninstall-CEnvironmentVariable -Name 'MyUserVariable' -Scope User Demonstrates how to remove a user-level environment by including `User` in the list of scopes. .EXAMPLE Uninstall-CEnvironmentVariable -Name 'MyComputerVariable' -Scope Machine Demonstrates how to remove a computer-level environment by including `Machine` in the list of scopes. .EXAMPLE Uninstall-CEnvironmentVariable -Name 'MyComputerVariable' -Scope User,Machine Demonstrates that you can pass multiple scopes to the `Scope` parameter. .EXAMPLE Uninstall-CEnvironmentVariable -Name 'MyComputerVariable' -Scope Process,Machine Demonstrates how to have the removal of a computer-level environment reflected in the current process by including `Process` in the list of scopes. .EXAMPLE 'Var1','Var2' | Uninstall-CEnvironmentVariable Demonstrates that you can pipe names to `Uninstall-CEnvironmentVariable`. .EXAMPLE Uninstall-CEnvironmentVariable Name 'Var1','Var2' Demonstrates that you can pass an array of names to the `Name` parameter. .EXAMPLE Uninstall-CEnvironmentVariable -Name 'SomeUsersVariable' -Credential $credential Demonstrates that you can remove another user's user-level environment variable by passing its credentials to the `Credential` parameter. This runs a separate PowerShell process as that user to remove the variable. #> [CmdletBinding(SupportsShouldProcess, DefaultParameterSetName='ForCurrentUser')] param( # The environment variable to remove. Case-insensitive on Windows, case-sensitive on Linux and macOS. [Parameter(Mandatory, ValueFromPipeline)] [String[]] $Name, # The scopes at which to remove the environment variable. Defaults to the current process. [Parameter(ParameterSetName='ForCurrentUser')] [EnvironmentVariableTarget[]] $Scope, # Remove an environment variable for a specific user. [Parameter(Mandatory, ParameterSetName='ForSpecificUser')] [pscredential] $Credential ) begin { Set-StrictMode -Version 'Latest' Use-CallerPreference -Cmdlet $PSCmdlet -Session $ExecutionContext.SessionState $userEnvVarsToDelete = [Collections.Generic.List[String]]::New() $Scope = $Scope | Assert-Scope } process { if ($PSCmdlet.ParameterSetName -eq 'ForSpecificUser') { $userEnvVarsToDelete.AddRange($Name) return } foreach ($_name in $Name) { foreach ($_scope in $Scope) { if (-not (Test-CEnvironmentVariable -Name $_name -Scope $_scope)) { continue } $target = "$($_scope.ToString().ToLowerInvariant())-level environment variable ""${_name}""" if (-not $PSCmdlet.ShouldProcess($target, 'remove')) { continue } Write-Information "Removing ${target}." [Environment]::SetEnvironmentVariable($_name, [NullString]::Value, $_scope) } } } end { if (-not $userEnvVarsToDelete.Count) { return } if (-not $IsWindows) { $msg = 'PowerShell and .NET only support user-level environment variables on Windows.' Write-Error -Message $msg -ErrorAction $ErrorActionPreference return } $uninstallArgs = $PSBoundParameters [void]$uninstallArgs.Remove('Credential') [void]$uninstallArgs.Remove('Name') Start-Job -ScriptBlock { Import-Module -Name (Join-Path -Path $using:moduleDirPath -ChildPath 'Carbon.Environment.psm1') $VerbosePreference = $using:VerbosePreference $ErrorActionPreference = $using:ErrorActionPreference $DebugPreference = $using:DebugPreference $WhatIfPreference = $using:WhatIfPreference $InformationPreference = $using:InformationPreference Uninstall-CEnvironmentVariable -Name $using:userEnvVarsToDelete -Scope User @using:uninstallArgs } -Credential $Credential | Receive-Job -Wait -AutoRemoveJob } } function Use-CallerPreference { <# .SYNOPSIS Sets the PowerShell preference variables in a module's function based on the callers preferences. .DESCRIPTION Script module functions do not automatically inherit their caller's variables, including preferences set by common parameters. This means if you call a script with switches like `-Verbose` or `-WhatIf`, those that parameter don't get passed into any function that belongs to a module. When used in a module function, `Use-CallerPreference` will grab the value of these common parameters used by the function's caller: * ErrorAction * Debug * Confirm * InformationAction * Verbose * WarningAction * WhatIf This function should be used in a module's function to grab the caller's preference variables so the caller doesn't have to explicitly pass common parameters to the module function. This function is adapted from the [`Get-CallerPreference` function written by David Wyatt](https://gallery.technet.microsoft.com/scriptcenter/Inherit-Preference-82343b9d). There is currently a [bug in PowerShell](https://connect.microsoft.com/PowerShell/Feedback/Details/763621) that causes an error when `ErrorAction` is implicitly set to `Ignore`. If you use this function, you'll need to add explicit `-ErrorAction $ErrorActionPreference` to every `Write-Error` call. Please vote up this issue so it can get fixed. .LINK about_Preference_Variables .LINK about_CommonParameters .LINK https://gallery.technet.microsoft.com/scriptcenter/Inherit-Preference-82343b9d .LINK http://powershell.org/wp/2014/01/13/getting-your-script-module-functions-to-inherit-preference-variables-from-the-caller/ .EXAMPLE Use-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState Demonstrates how to set the caller's common parameter preference variables in a module function. #> [CmdletBinding()] param ( [Parameter(Mandatory)] #[Management.Automation.PSScriptCmdlet] # The module function's `$PSCmdlet` object. Requires the function be decorated with the `[CmdletBinding()]` # attribute. $Cmdlet, [Parameter(Mandatory)] # The module function's `$ExecutionContext.SessionState` object. Requires the function be decorated with the # `[CmdletBinding()]` attribute. # # Used to set variables in its callers' scope, even if that caller is in a different script module. [Management.Automation.SessionState]$SessionState ) Set-StrictMode -Version 'Latest' # List of preference variables taken from the about_Preference_Variables and their common parameter name (taken # from about_CommonParameters). $commonPreferences = @{ 'ErrorActionPreference' = 'ErrorAction'; 'DebugPreference' = 'Debug'; 'ConfirmPreference' = 'Confirm'; 'InformationPreference' = 'InformationAction'; 'VerbosePreference' = 'Verbose'; 'WarningPreference' = 'WarningAction'; 'WhatIfPreference' = 'WhatIf'; } foreach( $prefName in $commonPreferences.Keys ) { $parameterName = $commonPreferences[$prefName] # Don't do anything if the parameter was passed in. if( $Cmdlet.MyInvocation.BoundParameters.ContainsKey($parameterName) ) { continue } $variable = $Cmdlet.SessionState.PSVariable.Get($prefName) # Don't do anything if caller didn't use a common parameter. if( -not $variable ) { continue } if( $SessionState -eq $ExecutionContext.SessionState ) { Set-Variable -Scope 1 -Name $variable.Name -Value $variable.Value -Force -Confirm:$false -WhatIf:$false } else { $SessionState.PSVariable.Set($variable.Name, $variable.Value) } } } |