PowerShell and #Requires

Did I run that script as admin?

Have you ever written a Powershell script only to get slapped in the face with a bunch of angry red text and an access denied message? I know at some point I have. The logical course of action is to of course google “how do I make sure I ran a script as admin” you’ll almost always get the following two lines of code.

$currentPrincipal = New-Object Security.Principal.WindowsPrincipal $([Security.Principal.WindowsIdentity]::GetCurrent())
if(!($currentPrincipal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator))){
    write-error -Message "You are not an admin, please elevate and run the script again"
    break
}

That’s four whole lines of codes, and of course, you have to actually RUN that line before it will make a determination, but what if I told you starting in Powershell 4.0 it can be done in one line.

What is about_Requires?

Starting all the way back in Powershell 3.0 a feature was added that was simply known as #requires. #Requires is one of a few Powershell keywords. I’m sure you can guess that it’s purpose to set a requirement which must be met before a script can run. Somehow this particular tool has been forgotten about. What really makes this tool great, is how the #Requires statement can be added anywhere in a script. That means the moment you encounter something that has a pre-requisite you can use this flag and the script won’t run unless the criteria are met. If you want to read more details about it you can read the documentation here below.

https://docs.microsoft.com/en-us/previous-versions/powershell/module/microsoft.powershell.core/about/about_requires?view=powershell-3.0

However, since its initial conception, the toolset has been improved upon many times until it now exists in its proud 7.1 version. You can see all the changes that have been made to it here:

https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_requires?view=powershell-7.x

Enough about what – how do I use it?

If you’ve been following along you might have noticed that every time I type ‘requires’ I’ve been putting a hashtag – or the Powershell comment sign – out in front. This is because its a requirement – ha – for using the #Requires flag. As previously mentioned the best part is how it can be used anywhere in the script, but to know how to use it we should look at the what. Microsofts documentation gives us some decent starting examples.

#Requires -Assembly { <Path to .dll> | <.NET assembly specification> }
#Requires -Version <N>[.<n>]
#Requires -PSSnapin <PSSnapin-Name> [-Version <N>[.<n>]]
#Requires -Modules { <Module-Name> | <Hashtable> }
#Requires -PSEdition <PSEdition-Name>
#Requires -ShellId <ShellId> -PSSnapin <PSSnapin-Name> [-Version <N>[.<n>]]
#Requires -RunAsAdministrator
  • Assembly
    • Allows you to specify that a DLL or .NET component be present in order for the script to run. Great if you are running something really complicated that leverages an API.
  • Version
    • Allows you to specify a specific version of Powershell to be installed. Such as you must have Powershell version 5.1 installed. – Scenarios include where commands are missing from older versions.
  • PSSnapin
    • Allows you to require specific snapins such as exchange or windows ad. (Not really used anymore as we now have modules)
  • Modules
    • Allows you to specify specific modules that you want to be imported for the script to run. While sessions can TRY to import modules, this checks for the modules existence before the script runs. You can import multiple.
  • PSEdition
    • Again not commonly used, but allows you to require the DESKTOP or CORE experience if your powershell script requires components that are only available due to a GUI being present.
  • ShellID
    • This feature and support has been deprecated. It was originally intended for min-shells.
  • RunAsAdministrator
    • This requires that the scripts execution is being run as or by an administrator. Easily the most important one.

Why did people forget about it?

By now I bet you’re wondering why would something so simple become completely forgotten about and be so rarely used. While I can’t say for sure I think the reason is because of terminal based Powershell editors such as ISE and VScode. Unfortunately, if you highlight a block of code and press F8 to run the current selection – the evaluation of the requirements blocks doesn’t occur. The only time the #requires tags are evaluated is if the script has been saved, and is run in its entirety by either pressing F5, or running the script from a Powershell window. While this does somewhat decrease it’s usefulness it’s still fantastic for a finished product.

How about some examples?

Lets do some examples scripts blocks.

The below code sample checks to see if the code is being run as an administrator and if its not it will yell at you.

#Requires -RunAsAdministrator
Get-ChildItem -Path C:\

The below code sample checks to see if the active directory module is available and if so gets a user. I’ve also provided an example in a screenshot of what happens when you require it to look for a module that is not present.

#Requires -Module ActiveDirectory
Get-ADUser -Identity jordan.benzing
#Requires -Module ConfigurationManager

Hopefully you embrace the power and flexibility of the #Requires options to help your scripting grow!

Leave a Reply

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

%d bloggers like this: