Public/Pop-VarStash.ps1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
<#
.SYNOPSIS
   Pops a variable stash.
.DESCRIPTION
   Pops a variable stash. This command restores all variables from a variable stash and then removes the stash from storage. The stash can optionally be kept using the -Keep parameter.
.EXAMPLE
   Pop-VarStash
 
   Pops the variables from the top of the stash (latest stash, index 0).
.EXAMPLE
   Pop-VarStash -Name MyStash
 
   Pops the variables from the stash with name 'MyStash'.
 
.EXAMPLE
   Pop-VarStash -Index 2
 
   Pops the variables from the stash with index position 2 (lates stash has index 0).
 
.EXAMPLE
    Pop-VarStash -Keep
 
    Pops the variables from the top of the stash (latest stash, index 0). When using parameter -Keep, the stash will not be removed from storage (and the verb pop does not make any sense :) ).
#>

function Pop-VarStash {
    [CmdletBinding(DefaultParameterSetName = 'Keep')]
    param(
        [parameter(ParameterSetName = 'Name',
                   ValueFromPipeline = $true,
                   ValueFromPipelineByPropertyName = $true)]
        [ValidateNotNullOrEmpty()]
        [string]$Name,

        [parameter(ParameterSetName = 'Index',
                   ValueFromPipeline = $true,
                   ValueFromPipelineByPropertyName = $true)]
        [ValidateRange(0, [int]::MaxValue)]
        [int]$Index,

        [parameter(ParameterSetName = 'Name')]
        [parameter(ParameterSetName = 'Index')]
        [parameter(ParameterSetName = 'Keep')]
        [switch]$Keep
    )

    Process {

        switch ($PSCmdlet.ParameterSetName) {
            'Name' { 
                $Stash = Get-VarStash -Name $Name
            }
            'Index' { 
                $Stash = Get-VarStash -Index $Index
            }
            Default {
                $Stash = Get-VarStash -Index 0
            }
        }

        $StashPath = "$env:APPDATA\VariableStash\VariableStash_$($Stash.Name).xml"
        # Check if we have a file to import
        if (Test-Path -Path $StashPath -PathType 'Leaf') {  
            # Import the variables
            $ImportedVariables = Import-Clixml -Path $StashPath

            # Set each variable in parent scope
            foreach ($var in $ImportedVariables) {
                try {
                    $null = Get-Variable -Name $var.Name -Scope 2 -ErrorAction Stop
                    Write-Verbose "Scope 2: Variable '$($var.Name)' will be overwritten."
                }
                catch [System.Management.Automation.PSArgumentOutOfRangeException] {
                    # If we get here, the scope number 2 exceeds the number of active scopes
                    # This can happen if the function is not executing within a module.
                    # (This probably only happens during development)
                    # In that case we use Scope 1 instead
                    try {
                        $null = Get-Variable -Name $var.Name -Scope 1 -ErrorAction Stop
                        Write-Verbose "Scope 1: Variable '$($var.Name)' will be overwritten."
                        Set-Variable -Name $var.Name -Scope 1 -Value $var.Value
                    }
                    catch [System.Management.Automation.PSArgumentOutOfRangeException] {
                        Throw "Unable to get current variables. Have tried both scope 2 and 1. Error: $_"
                    }
                    catch [System.Management.Automation.ItemNotFoundException] {
                        # Scope works. Variable not found in current session
                        Write-Verbose "Scope 1: Variable '$($var.Name)' will be created."
                        Set-Variable -Name $var.Name -Scope 1 -Value $var.Value
                    }
                    catch {
                        Throw "Unable to get current variables in scope 1. Unhandled error. Error: $_"
                    }
                }
                catch {
                    # Scope works. Variable not found in current session
                    Write-Verbose "Scope 2: Variable '$($var.Name)' will be created."
                    Set-Variable -Name $var.Name -Scope 2 -Value $var.Value
                }
            }

            if (-not $Keep.IsPresent) {
                Remove-VarStash -Name $Stash.Name
            }
        }
        else {
            Write-Error -Category ObjectNotFound -Message 'Stash not found.'
        }

    }
}