How to protect your PowerShell Functions

April 17, 2012

one comment

Creating functions in PowerShell is relatively a simple operation. You declare the function’s name and value, press the Enter key and you’re good to go. It is also very simple to override the function just by re-creating it; that’s all it takes, simple and easy.

What if you need to prevent that from happening? You don’t want to allow someone or something from overriding your functions?

PowerShell gives us the option to do that via a dynamic parameter. Dynamic parameters are cmdlet parameters that are added by a Windows PowerShell provider and are available only when the cmdlet is being used in the provider-enabled drive. The Options dynamic parameter is supported by New-Item and Set-Item when you use them with the Alias,Variable or Function providers.

The Options parameter <System.Management.Automation.ScopedItemOptions> possible values:

  • None – No options. “None” is the default.
  • PrivateThe function is visible only in the current scope (not in child scopes).
  • ReadOnlyThe properties of the function cannot be changed except by using the Force parameter. You can use Remove-Item to delete the function.
  • ConstantThe function cannot be deleted, and its properties cannot be changed. Constant is available only when you are creating a function. You cannot change the option of an existing function to Constant.
  • AllScopeThe function is copied to any new scopes that are created.

Let’s see how we can protect a function, we’ll start by marking it Read only.

# create a function

PS> function test { “I’m a read-only function” }

 

# set it as readonly

PS> Set-Item –Path Function:test –Options ReadOnly

 

# try to update the function definition

PS> function test { “new value” }

 

Cannot write to function test because it is read-only or constant.

At line:8 char:1

+ function test { “new value” }

+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    + CategoryInfo          : WriteError: (test:String) [], SessionStateUnauthorizedAccessException

    + FullyQualifiedErrorId : FunctionNotWritable

 

We get an error when we try to update the function. Let’s try to override it with the Force switch:

PS> Set-Item –Path Function:test -Value { “new value” } -Force
PS>
test

new value

This time we don’t get the error and the function has been updated. If ReadOnly is not enough and doesn’t really protect the function like we want to, then we can set another value. This time let’s try to make it constant.

PS> Set-Item –Path Function:test -Value { “I’m constant” } -Options Constant -Force

Set-Item : Existing function test cannot be made constant. Functions can be made constant only at creation time.

At line:1 char:1

+ Set-Item –Path Function:test -Value { “I’m constant” } -Options Constant -Force

+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    + CategoryInfo          : WriteError: (test:String) [Set-Item], SessionStateUnauthorizedAccessException

    + FullyQualifiedErrorId : FunctionCannotBeMadeConstant,Microsoft.PowerShell.Commands.SetItemCommand

 

PS> 

We get an error that functions can be made constant only at creation time. Let’s create a new function and then try to override it and remove it:PS C:\> # create a constant function

# # create a constant function
PS>
New-Item –Path Function:test2 -Value { “I’m constant” } -Options Constant

Capability Name ModuleName

———- —- ———-

Script    test2

 

# try to update the function

PS> Set-Item –Path Function:test2 -Value { “I’m constant 2” } -Force

 

# try to remove it

PS> Remove-Item Path Function:test2 -Force

 

 

Set-Item : Cannot write to function test2 because it is read-only or constant.

At line:5 char:1

+ Set-Item –Path Function:test2 -Value { “I’m constant 2” } -Force

+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    + CategoryInfo          : WriteError: (test2:String) [Set-Item], SessionStateUnauthorizedAccessException

    + FullyQualifiedErrorId : FunctionNotWritable,Microsoft.PowerShell.Commands.SetItemCommand

 

Remove-Item : A positional parameter cannot be found that accepts argument ‘Function:test2’.

At line:8 char:1

+ Remove-Item Path Function:test2 -Force

+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    + CategoryInfo          : InvalidArgument: (:) [Remove-Item], ParameterBindingException

    + FullyQualifiedErrorId : PositionalParameterNotFound,Microsoft.PowerShell.Commands.RemoveItemCommand

 

PS> 

 

As you can see none of the above changes the function. It is protected and the only option to get rid of it is by closing the shell. 

In addition to Aliases and Functions, we can also protect other objects, like: variables and modules. For variables use the Set-Variable cmdlet, it has its own options parameter. To protect modules from being unloaded we need to set the module’s AccessMode property. Here’s an example using dynamic module.

 

PS> New-Module -Name CantTouchThis -ScriptBlock {

 $ExecutionContext.SessionState.Module.AccessMode = ‘constant’

} | Import-Module

 

Remove-Module -Name CantTouchThis -Force

 

 

Remove-Module : Unable to remove module ‘CantTouchThis’ because it is marked as constant. A module cannot be removed if it is marked constant.

At line:5 char:1

+ Remove-Module -Name CantTouchThis -Force

+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    + CategoryInfo          : PermissionDenied: (CantTouchThis:PSModuleInfo) [Remove-Module], InvalidOperationException

    + FullyQualifiedErrorId : Modules_ModuleIsConstant,Microsoft.PowerShell.Commands.RemoveModuleCommand

 

Remove-Module : No modules were removed. Verify that the specification of modules to remove is correct and those modules exist in the runspace.

At line:5 char:1

+ Remove-Module -Name CantTouchThis -Force

+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    + CategoryInfo          : ResourceUnavailable: (:) [Remove-Module], InvalidOperationException

    + FullyQualifiedErrorId : Modules_NoModulesRemoved,Microsoft.PowerShell.Commands.RemoveModuleCommand

 

PS>

 

I would like to have another way to create constant functions or modules so I logged two suggestions on Microsoft’s Connect website, one for functions and another one for modules, vote them up and maybe we’ll get them in v4 🙂

Add comment
facebook linkedin twitter email

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

one comment

  1. SheaNovember 28, 2012 ב 00:04

    Hello, I enjoy reading all of your article. I like to write a little comment to support you.

    Reply