Hidden … sort of: The Hidden Keyword in PowerShell Classes

March 18th, 2015 by June Blender
Last updated on April 8th, 2016

 
Applies to: PowerShell 5.0.14279.1000
 

The Hidden keyword hides properties and methods (and other members, like events) in a PowerShell class. When a member is hidden, you can still view and change it, but the Get-Member cmdlet doesn’t display it without the Force parameter and the hidden members are not available to auto-completion features, such as PrimalSense and IntelliSense.

You can apply the Hidden keyword to any member (property, method, event, etc), including static members. It is not case sensitive and it can appear anywhere in the member signature before the member name. As a best practice, I suggest placing it first to simplify troubleshooting.

I’ve spent quite a bit of time playing with classes in the Windows PowerShell 5.0. The ability to create and script with your own classes, and to create subclasses of those classes, is extremely powerful. I consider it to be the final frontier in the dev-ops continuum, so I’m determined to make sure that everyone understands it, even people who have no development background.

One of the little quirks of scripted classes in Windows PowerShell is that all properties of instances of the class are public, visible, and read-write. When you add properties to a class, Windows PowerShell automatically creates special methods called accessors that let users of the class get and set (view and change) the property values.

For example, I’ll create a little Tree class with a Species property. At this point, I haven’t created any methods, not even constructors.

class Tree
{
    [String] $Species
}

When I create an instance of the Tree class…

$myTree = [Tree]::new()

… Windows PowerShell adds get_Species and set_Species accessor methods so you can view and change the Species property value. These methods are hidden, but you can see them when you use the Force parameter of Get-Member.

PS C:\> $myTree | Get-Member -Name "*Species*"

   TypeName: Tree

Name    MemberType Definition               
----    ---------- ----------               
Species Property   string Species {get;set;}



PS C:\> $myTree | Get-Member -Name "*Species*" -Force

   TypeName: Tree

Name        MemberType Definition               
----        ---------- ----------               
get_Species Method     string get_Species()     
set_Species Method     void set_Species(string )
Species     Property   string Species {get;set;}

In fact, every variable that you create in a class outside of a method becomes a property of that class with accessor methods to view and change it.

For example, I’ve added a Height property and a Grow method to the Tree class, and a grow_times variable to hold the number of times that I’ve called the Grow method on my tree. But Windows PowerShell considers the grow_times variable to be a property, and adds get/set methods for it to the class.

class Tree
{
    # Properties
    [String] $Species
    [double] $Height
 
    # Methods
    [int] Grow ([int]$inches)
    {
        $this.Height += $inches
        $this.grow_times++
        return $this.Height
    }
 
    # Variables -- these are properties, too.
    [int] $grow_times = 0
}

When I create an instance of the Tree class, grow_times is a property with get and set accessor methods, just like Species and Height.

PS C:\> $myTree | Get-Member

TypeName: Tree

Name        MemberType Definition
----        ---------- ----------
Equals      Method     bool Equals(System.Object obj)
GetHashCode Method     int GetHashCode()
GetType     Method     type GetType()
Grow        Method     int Grow(int inches)
ToString    Method     string ToString()
grow_times  Property   int grow_times {get;set;}
Height      Property   int Height {get;set;}
Species     Property   string Species {get;set;}

 

And, when I type $myTree and a dot, IntelliSense suggest the grow_times property, along with the other properties of the tree.

image

I can’t make my variable completely private to the class – there is no Private keyword — but there is a Hidden keyword that hides members from auto-complete features and from Get-Member without –Force.

In this example, I add the Hidden keyword to the grow_times property. I can place “Hidden” anywhere in the statement before the name, that is, it can go before or after “[int]” or an attribute, but I think it’s best to place it first, especially for troubleshooting.

class Tree
{
    # Properties
    [String] $Species
    [double] $Height
 
    # Methods
    [int] Grow ([int]$inches)
    {
        $this.Height += $inches
        $this.grow_times++
        return $this.Height
    }
 
    # Hidden properties
    hidden [int] $grow_times = 0
}

 

Now, when I create a tree object and run Get-Member, the grow_times property is not displayed.

image

The property is visible to Get-Member only with –Force.

PS C:\> $myTree | Get-Member -MemberType Property

TypeName: Tree

Name    MemberType Definition
----    ---------- ----------
Height  Property   int Height {get;set;}
Species Property   string Species {get;set;}


PS C:\> $myTree | Get-Member -MemberType Property -Force

TypeName: Tree

Name       MemberType Definition
----       ---------- ----------
grow_times Property   int grow_times {get;set;}
Height     Property   int Height {get;set;}
Species    Property   string Species {get;set;}

 

Users of the class can get and set the grow_times property, but only if they know about it. It is not advertised to them. (You cannot override or redefine the property accessors.)

PS C:\> $myTree.grow_times
0

PS C:\ps-test> $myTree.grow_times++

PS C:\ps-test> $myTree.grow_times
1

 

And, even though it is hidden, grow_times is available to all members of the class, including the Grow() method that increments it.

PS C:\> $myTree.Height = 10

PS C:\> $myTree.grow_times
0

PS C:\> $myTree.Grow(2)
12

PS C:\> $myTree.grow_times
1

Windows PowerShell classes give you a whole new level of power. And, the Hidden keyword is a handy tool for making classes work the way you designed them.

Update 4/08/2016: Bruce Payette, the PowerShell team language developer, explained that we don’t have a Private keyword because PowerShell uses PowerShell for debugging. If you were able to create a property that was invisible to PowerShell, you couldn’t debug it.

June Blender is a technology evangelist at SAPIEN Technologies, Inc. You can reach her at juneb@sapien.com or follow her on Twitter at @juneb_get_help.

——————————

More SAPIEN blog posts about the Windows PowerShell 5.0 classes:

Beyond custom objects- Create a .NET class
Enumerated Types in Windows PowerShell 5.0
Find variables with class
Creating Objects in Windows PowerShell
Why Do We Need Constructors?
Inheritance in PowerShell Classes

 

 
[Google+]   [Facebook]   [LinkedIn]   [StumbleUpon]   [Digg]   [Reddit]   [Google Bookmark]  

Tags: , ,