PowerShell scripts often rely on specific modules, which are collections of cmdlets, functions, and other tools that extend the shell’s capabilities. To effectively manage these dependencies, PowerShell offers three distinct mechanisms: #Requires
, using
, and Import-Module
. While each serves the purpose of making module components available, they operate on different principles and are suited for different scenarios.

What is #Requires?
The #Requires
statement is a script directive that enforces prerequisites before a script runs. It’s processed before any code executes, ensuring the environment meets your requirements. All #Requires
statements are placed at the very top of your script. They will look like the following:
#Requires -Version 7.0
#Requires -Module Az.Accounts
#Requires -Modules @{ ModuleName = 'ActiveDirectory'; ModuleVersion = '1.0.0' }
#Requires -RunAsAdministrator
If the specified requirements aren’t met PowerShell throws an error and halts execution.
#Requires
can check for environmental prerequisites with modules (including specific versions), PowerShell version and administrator privileges. These statements are useful for scripts distributed to others, ensuring a script doesn’t run in an unsupported environment.
What is a using statement?
The using
statement is used to import .NET assembly, namespaces, and types in PowerShell scripts. Its primary purpose is to simplify code by reducing the need for fully qualified names, making it easier to reference types and namespaces, and implicitly load modules. A using
statement is processed before the script runs and must appear at the very beginning of a script file (.PS1) or a module file (.PSM1), before any executable code, functions, or variable declarations. The only exceptions are #Requires
statements and comments, which can precede using statements. They will look like the following:
using namespace System.Net
using module Az.Accounts
using assembly 'C:\path\to\MyCustomAssembly.dll'
When a using
statement fails, it generally results in a terminating or parsing error depending on what is being loaded. The using module
statement imports classes and enumerations from the root module (ModuleToProcess
) of a script module or binary module. This does not apply to nested modules, only the root module.
What is Import-Module?
Import-Module
is a command that loads PowerShell modules into the current session, making their functions, cmdlets, and variables available. It runs during the script’s execution. This means the module is loaded at the point where the command is encountered in your script allowing control over when and which modules are loaded. It will look like the following:
Import-Module Az.Accounts
Import-Module -Name ActiveDirectory
Import-Module -Name .\MyCustomModule.psm1
By default, Import-Module
loads the module into the current scope. This means if you run it inside a function, the module might not be available outside of that function unless you use the Global parameter.
If the module is not found or fails to load, Import-Module
will throw a non-terminating error, which you can handle using a try/catch block.
The command is flexible and can load modules from any path, not just the standard $env:PSModulePath
locations. This is useful for testing modules that are not yet installed in a standard location.
Loading Modules
A frequent source of confusion is the expectation that #Requires -Module
will also import the module. It doesn’t directly! PowerShell has a clever mechanism where it automatically imports a module the first time you try to use a command (cmdlet, function, alias) that belongs to that module. #Requires
only asserts if the module is present, it does not directly load it. This distinction is important when it comes to packaging scripts as executables. When packaging with SAPIEN Script Packager, it is important to explicitly use Import-Module
rather than just a #Requires -Module
statement as our packaging engines will not auto-load the modules.
When using module
is processed, the module will be implicitly loaded. Import-Module
(and indirectly #Requires
) only import the module functions, aliases, and variables, as defined by the module. Classes definitions are not imported. The using module
imports the module and also loads the class definitions.
Lastly, Import-Module
will return an object. The using module
statement is declarative and will import the module, but it is not a command. You are simply telling PowerShell this is what you need. Import-Module
is an imperative command that tells PowerShell how to find the module and returns an object on completion (that object could be null if it fails). The script’s flow of control is dictated by where you place this command. If you put it inside an if block, it will only run if that condition is true.
Summary
By leveraging #Requires
for validation, using
for declarative dependencies, and Import-Module
for fine-grained control, you can create scripts that are not only functional but also adaptable to various environments. Understanding when and how to use each approach helps you write more robust, maintainable, and portable PowerShell scripts. Happy scripting!
Feedback
As always, any feedback is appreciated. If you have a particular type of blog article or product feature request you would like to see, please submit your suggestions on the Wish List and Feature Requests forum or the Feature Requests page.