Read-Only and Constant Functions

I recently wrote an article on read-only and constant variables. These options help protect variables from being overwritten in different ways. We can do this with functions, as well. I mentioned it in that previous post, but I have a function template that I use to create all my PowerShell tools. In it, are variables and nested functions. In conjunction with that last article, I need to protect the function template's nested functions. It's not likely someone would overwrite a nested function, as the names are more unique than the variables, but I still have to do my part to be thorough. Let's look at an example of creating a function.

Such as when we create and assign variables, we have a preferred, or standard way, and another option. This first example is the standard way, follow by an example of then invoking the newly created function.

Function Test-Function {
    'This is a test function, created in a standard way.'
} # End Function: Test-Function.
PS C:\> Test-Function
This is a test function, created in a standard way.
PS C:\>

That worked well -- it always does. Now, let's build a function in a non-standard way. Before we do that, however, let's discuss the Function drive. If you were to run the Get-PSDrive Cmdlet, it would return your system drive (C:\ in Windows), and likely other drives named using letters. You'd also return some PowerShell specific drives. One of these is the Function drive. It's another way (beside Get-Command) to see which functions are loaded into memory for use.

PS C:\> Get-PSDrive

Name           Used (GB)     Free (GB) Provider      Root                                               CurrentLocation
----           ---------     --------- --------      ----                                               ---------------
Alias                                  Alias
C                 285.62        189.86 FileSystem    C:\
Cert                                   Certificate   \
D                   0.10          1.76 FileSystem    D:\
Env                                    Environment
Function                               Function
HKCU                                   Registry      HKEY_CURRENT_USER
HKLM                                   Registry      HKEY_LOCAL_MACHINE
Variable                               Variable
WSMan                                  WSMan

PS C:\> Get-ChildItem -Path Function:\ | Select-Object -First 9

CommandType     Name                                               Version    Source
-----------     ----                                               -------    ------
Function        A:
Function        Add-SinkProfilePartner                             1.0        SinkProfile
Function        B:
Function        C:
Function        cd..
Function        cd\
Function        Clear-Host
Function        Complete-SinkProfilePartner                        1.0        SinkProfile
Function        Confirm-Logoff

PS C:\>

Okay, now to create our function in a non-standard way. This option uses the New-Item Cmdlet. Notice that we've piped this command to Out-Null. If we hadn't, it would've created some default hey-your-new-command-has-been-created type of output. In writing a scripted solution, it's not likely I would want this output. In the second example, we test that the new function has been created, by trying it.

New-Item -Path Function:\Test-AnotherFunction -Value {
    'This is a test function, created in a NON-standard way.'
} | Out-Null
PS C:\> Test-AnotherFunction
This is a test function, created in a NON-standard way.
PS C:\>

I won't bother demonstrating it all, but functions and variables are identical in relation to read-only and constant options. You can make a function read-only at anytime and delete the function using the Force parameter. You can make a function a constant, but only when the function is being created, which is identical to variables. And also like variables, you cannot remove or delete a constant function, once it's been created. Only ending the PowerShell session in which it was created will remove a constant function.

Let's make our newest, already created function read-only, right after making sure it doesn't have any options that are already applied.

PS C:\> (Get-Item -Path Function:\Test-AnotherFunction).Options
None
PS C:\> Set-Item -Path Function:\Test-AnotherFunction -Options ReadOnly
PS C:\> (Get-Item -Path Function:\Test-AnotherFunction).Options
ReadOnly

If you remember back to the last, variable article, you may see a difference with how we set this to read-only. Set-Item uses OptionS, whereas New/Set-Variable uses Option (singular). I've brought this up on GitHub (https://github.com/PowerShell/PowerShell/issues/10551), but I don't think we'll see any changes soon, if ever. That said, much of PowerShell's success, is based on consistency.

And really, that's it. We can make functions both read-only and constant, too, in order to see they're protected.

≥ Tommy Maynard (Twitter: @thetommymaynard)

About Tommy Maynard

IT Pro. Passionate for #PowerShell, #AWS (certified x2), & all things automation. I'm not done learning. Author in #PSConfBook. Writes at https://powershell.org.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.