Behind the PowerShell Pipeline logo

Behind the PowerShell Pipeline

Subscribe
Archives
September 17, 2024

Master Your Environment Part 3

Note: I am aware that code samples are not respecting HTML tags and rendering some characters with their HTML codes. Buttondown is working on this issue. I apologize for the annoyance.

Let's wrap up our exploration of [System.Environment]. Even though I would encourage you to use the $ENV: PSDrive, not all environment variables are accessible through it nor are they available on all platforms. If you are creating cross-platform scripts that incorporate environment variables, you may need to use [System.Environment].

Homework

But before we get to the last bit of content on this topic, let's review the homework assignment I gave you. I hope you at least started to devise a solution.

Write a PowerShell function that writes a an object to the pipeline that shows unique environment variables for each target. The output should also include the computer and user names. Feel free to enhance the function as you wish.

The targets are User, Machine, and Process. Here's a function that I came up with:

Function Get-EnvironmentVariableTarget {
    [cmdletbinding()]
    [Alias('gevt')]
    Param()

    Write-Information -MessageData "Running under PowerShell version: $($PSVersionTable.PSVersion)" -Tags meta
    Write-Information -MessageData "Using host: $($host.name)" -Tags meta
    Write-Information -MessageData ".NET version: $([System.Environment]::Version)" -Tags meta
    # nested helper function
    Function HashToOrderedObject {
        # A helper function to convert a hashtable to a PSObject
        # with ordered property names
        Param([Hashtable]$Hash)
        $hash.GetEnumerator() |
        Sort-Object Key |
        foreach -Begin {
            $tmp = [ordered]@{}
        } -Process {
            $tmp.Add($_.key, $_.value)
        } -End { [PSCustomObject]$tmp }
    }

    #Get variables from the different scopes or targets
    $u = [System.Environment]::GetEnvironmentVariables('user')
    $m = [System.Environment]::GetEnvironmentVariables('machine')
    $p = [System.Environment]::GetEnvironmentVariables('process')

    Write-Information -MessageData "User variables: $($u.Count)" -Tags data
    Write-Information -MessageData ($u | Out-String) -Tags data
    Write-Information -MessageData "Machine variables: $($m.Count)" -Tags data
    Write-Information -MessageData ($m | Out-String) -Tags data
    Write-Information -MessageData "Process variables: $($p.Count)" -Tags data
    Write-Information -MessageData ($p | Out-String) -Tags data

    #I need to create a new Hashtable to store the unique process variables
    $p.GetEnumerator() |
    Where-Object { ($m.keys -notContains $_.name) -AND ($u.keys -notContains $_.name) } |
    ForEach-Object -Begin { $Unique = @{} } -Process { $Unique[$_.Name] = $_.Value }

    Write-Information -MessageData "Unique process variables: $($Unique.Count)" -Tags data
    Write-Information -MessageData ($Unique | Out-String) -Tags data

    #create a composite, custom object
    [PSCustomObject]@{
        Computername = [System.Environment]::MachineName
        UserName     = [System.Environment]::UserName
        Host         = $host.Name
        PSVersion    = $PSVersionTable.PSVersion
        User         = HashToOrderedObject -Hash $u
        Machine      = HashToOrderedObject -Hash $m
        Process      = HashToOrderedObject -Hash $Unique
    }
}

The function gets variables from each of the scopes. I then create a hashtable to store the unique process variables that aren't defined in the user or machine targets. The custom object's Process property might be slightly misleading because it isn't the actual Process target but rather the unique variables in the Process target. The output also includes additional information which I thought might be useful. I have also included information data that you can get when you use the -InformationActionVariable parameter.

$r = Get-EnvironmentVariableTarget -InformationVariable iv

Here's the output.

Get-EnvironmentVariableTarget output
figure 1

The individual properties will show the different target variables.

Machine-scoped environment variables
figure 2
Want to read the full issue?
GitHub Bluesky LinkedIn About Jeff
Powered by Buttondown, the easiest way to start and grow your newsletter.