11

Is it possible to easily list only user-created variables in PowerShell? The get-variable Cmdlet gives me all the system variables as well which isn't what I'd like sometimes.

For example if I open a new session and do

$a=1
$b=2

I'd like some variant of get-variable that only returns a and b since they are the only two variables that have been explicitly created in the session.

4 Answers 4

17

Most of the standard variables can be found in System.Management.Automation.SpecialVariables. If you filter out these and a small list of other known variables, you can create a reusable function to get user-defined variables:

function Get-UDVariable {
  get-variable | where-object {(@(
    "FormatEnumerationLimit",
    "MaximumAliasCount",
    "MaximumDriveCount",
    "MaximumErrorCount",
    "MaximumFunctionCount",
    "MaximumVariableCount",
    "PGHome",
    "PGSE",
    "PGUICulture",
    "PGVersionTable",
    "PROFILE",
    "PSSessionOption"
    ) -notcontains $_.name) -and `
    (([psobject].Assembly.GetType('System.Management.Automation.SpecialVariables').GetFields('NonPublic,Static') | Where-Object FieldType -eq ([string]) | ForEach-Object GetValue $null)) -notcontains $_.name
    }
}

$a = 5
$b = 10
get-udvariable

Name                           Value                                                                                                              
----                           -----                                                                                                              
a                              5     
b                              10

Note: In the ISE there are two additional standard variables: $psISE and $psUnsupportedConsoleApplications

1
  • I thought about this approach, but it seemed just as weird in the console as anything else. Good work! Aug 25, 2013 at 14:31
6

You can consider using description, but that would require different syntax when creating variables:

New-Variable -Name a -Value 1 -Description MyVars
nv b 2 -des MyVars
Get-Variable | where { $_.Description -eq 'MyVars' }

2nd syntax uses aliases/positional parameters to shorten your work.

2

The only way I can personally see to do this, would require an extra step of storing the variables in an array.

One example, just for testing:

PS C:\Users\Athomsfere> $myVars = @($a, $b)
PS C:\Users\Athomsfere> Get-Variable -Name myVars

Name                           Value
----                           -----
myVars                         {some, thing}
0

I used some of @jon Z's great answer and generated a ProxyCommand for Get-Variable.

$MetaData = New-Object System.Management.Automation.CommandMetaData (Get-Command Get-Variable)
[System.Management.Automation.ProxyCommand]::Create($MetaData) | Out-File -FilePath Get-UserVariable.ps1

Then I edited it to use the -Exclude parameter. This way the new Get-UserVariable function works like Get-Variable with piping. The code should work in PowerShell 5.1.

I've also taken the liberty to create a guv alias as well as removing other popular module variables. Sometimes modules will "pollute" the global variable namespace.

function Get-UserVariable {
    [Alias('guv')]
    [CmdletBinding(HelpUri='https://go.microsoft.com/fwlink/?LinkID=2096711')]
    param(
        [Parameter(Position=0, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)]
        [ValidateNotNullOrEmpty()]
        [string[]]
        ${Name},

        [switch]
        ${ValueOnly},

        [string[]]
        ${Include},

        [string[]]
        ${Exclude},

        [ValidateNotNullOrEmpty()]
        [string]
        ${Scope}
    )

    begin
    {
        try {
            $outBuffer = $null
            if ($PSBoundParameters.TryGetValue('OutBuffer', [ref]$outBuffer))
            {
                $PSBoundParameters['OutBuffer'] = 1
            }

            $MiscVar = @(
                'FormatEnumerationLimit'
                'MaximumAliasCount'
                'MaximumDriveCount'
                'MaximumErrorCount'
                'MaximumFunctionCount'
                'MaximumVariableCount'
                'PGHome'
                'PGSE'
                'PGUICulture'
                'PGVersionTable'
                'PROFILE'
                'PSSessionOption'
                'PSGetPath'
                'psEditor'
                <# Oh My Posh Argument Completer Script #>
                '__oh_my_poshCompleterBlock'
                <# gh.exe GitHub CLI Arg Completer #>
                '__ghCompleterBlock'
                <# glow.exe Arg Completer #>
                '__glowCompleterBlock'
                <# VSCode Powershell Editor Services Debug #>
                '__psEditorServices_CallStack'
                <# VMware.PowerCLI variables#>
                'UidUtil'
                <# Remove `global:` for the below two items as the `-Exclude` parameter doesn't work with it #>
                'DefaultVIServer'
                'DefaultVIServers' 
                <# ZLocation Module variables #>            
                'ZLocationPromptScriptBlock'
                <# SqlServer Module variables #>
                'SqlServerConnectionTimeout'
                'SqlServerIncludeSystemObjects'
                'SqlServerMaximumChildItems'
                'SqlServerMaximumTabCompletion'
                <# dbatools/PSFramework - Select-DbaObject #>
                '__PSFramework_SelectParam'
                <# PSKoans Module #>
                'PSKoans_ClearOutputStyle'
                'PSKoans_SetOutputStyle'
                <# Chocolatey Tab Completion Module ( chocolateyProfile.psm1 ) #>
                'ChocolateyTabSettings'
                <# posh-git Module #>
                'GitMissing'
                'GitStatus'
                'GitPromptScriptBlock'
                'GitPromptSettings'
                'GitPromptValues'
                'GitTabSettings'
                'TortoiseGitSettings'
                'VcsPromptStatuses'
                <# gsudo chocolatey tool #>
                'gsudoVerbose'
                'gsudoLoadProfile'
                <# PnP.PowerShell #>
                'WebRequestCounter'
                <# EZOut Module #>
                'EZOut_clearOutputStyle'
                'EZOut_Format-Heatmap'
                'EZOut_Format-Markdown'
                'EZOut_Format-RichText'
                'EZOut_Indent'
                'EZOut_setOutputStyle'
                <# SentinelOneAPI Module #>
                'S1_API_Key'
                'S1_Base_URI'
                'S1_Headers'
                'S1_JSON_Conversion_Depth'
                <# PSWriteHTML #>
                'HTMLIcons'
                <# NTFSSecurity Module #>
                'type_NTFS1' 
                <# Local function variables #>
                'MiscVar'
                'SpecialVarType'
                'SpecialVarFlags'
                'SpecialVar'
                'SpecialVarStr'
                'SpecialVarValue'
                'outBuffer'
                'wrappedCmd'
                'scriptCmd'
                'steppablePipeline'
            )
            $SpecialVarType = 'System.Management.Automation.SpecialVariables'
            $SpecialVarFlags = 'NonPublic,Static' # [System.Reflection.BindingFlags]
            $SpecialVar = [psobject].Assembly.GetType($SpecialVarType).GetFields($SpecialVarFlags)
            $SpecialVarStr = $SpecialVar | Where-Object -Property FieldType -EQ ([string])
            $SpecialVarValue = $SpecialVarStr | ForEach-Object { [WildcardPattern]::Escape( $_.GetValue('') ) }
            $PSBoundParameters['Exclude'] += $MiscVar + $SpecialVarValue + $PSCmdlet.MyInvocation.MyCommand.Parameters.Values.Name

            $wrappedCmd = $ExecutionContext.InvokeCommand.GetCommand('Microsoft.PowerShell.Utility\Get-Variable', [System.Management.Automation.CommandTypes]::Cmdlet)
            $scriptCmd = { & $wrappedCmd @PSBoundParameters }

            $steppablePipeline = $scriptCmd.GetSteppablePipeline($myInvocation.CommandOrigin)
            $steppablePipeline.Begin($PSCmdlet)
        } catch {
            throw
        }
    }

    process
    {
        try {
            $steppablePipeline.Process($_)
        } catch {
            throw
        }
    }

    end
    {
        try {
            $steppablePipeline.End()
        } catch {
            throw
        }
    }

    <# New clean Block Note:
     # Not available in PowerShell Desktop
     # Not currently used in `Get-Variable` as of 4/4/2023
     #>
    # clean
    # {
    #     if ($null -ne $steppablePipeline) {
    #         $steppablePipeline.Clean()
    #     }
    # }

<#
.ForwardHelpTargetName Microsoft.PowerShell.Utility\Get-Variable
.ForwardHelpCategory Cmdlet
#>

}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.