From 61cec1525b01c4a656bf00633da90d6c0b8f915f Mon Sep 17 00:00:00 2001 From: Justin Grote Date: Thu, 12 Jun 2025 08:18:24 -0700 Subject: [PATCH] Add Note about module assembly initializer and cleanup (#12150) * Add Note about module assembly initializer and cleanup * Add links and fix formatting --------- Co-authored-by: Sean Wheeler --- ...how-to-write-a-powershell-binary-module.md | 88 ++++++++++++------- 1 file changed, 55 insertions(+), 33 deletions(-) diff --git a/reference/docs-conceptual/developer/module/how-to-write-a-powershell-binary-module.md b/reference/docs-conceptual/developer/module/how-to-write-a-powershell-binary-module.md index f5d01b8109cf..56b16928c00f 100644 --- a/reference/docs-conceptual/developer/module/how-to-write-a-powershell-binary-module.md +++ b/reference/docs-conceptual/developer/module/how-to-write-a-powershell-binary-module.md @@ -1,16 +1,16 @@ --- description: How to Write a PowerShell Binary Module -ms.date: 09/13/2016 +ms.date: 06/12/2025 title: How to Write a PowerShell Binary Module --- # How to Write a PowerShell Binary Module -A binary module can be any assembly (.dll) that contains cmdlet classes. By default, all the cmdlets -in the assembly are imported when the binary module is imported. However, you can restrict the -cmdlets that are imported by creating a module manifest whose root module is the assembly. (For -example, the CmdletsToExport key of the manifest can be used to export only those cmdlets that are -needed.) In addition, a binary module can contain additional files, a directory structure, and other -pieces of useful management information that a single cmdlet cannot. +A binary module can be any assembly (`.dll`) that contains cmdlet classes. By default, all the +cmdlets in the assembly are imported when the binary module is imported. However, you can restrict +the cmdlets that are imported by creating a module manifest whose root module is the assembly. (For +example, the **CmdletsToExport** key of the manifest can be used to export only those cmdlets that +are needed.) In addition, a binary module can contain additional files, a directory structure, and +other pieces of useful management information that a single cmdlet cannot. The following procedure describes how to create and install a PowerShell binary module. @@ -19,10 +19,10 @@ The following procedure describes how to create and install a PowerShell binary 1. Create a binary PowerShell solution (such as a cmdlet written in C#), with the capabilities you need, and ensure that it runs properly. - From a code perspective, the core of a binary module is simply a cmdlet assembly. In fact, - PowerShell will treat a single cmdlet assembly as a module, in terms of loading and unloading, - with no additional effort on the part of the developer. For more information about writing a - cmdlet, see [Writing a Windows PowerShell Cmdlet](../cmdlet/writing-a-windows-powershell-cmdlet.md). + From a code perspective, the core of a binary module is a cmdlet assembly. In fact, PowerShell + treats a single cmdlet assembly as a module for loading and unloading, with no additional effort + on the part of the developer. For more information about writing a cmdlet, see + [Writing a Windows PowerShell Cmdlet][01]. 1. If necessary, create the rest of your solution: (additional cmdlets, XML files, and so on) and describe them with a module manifest. @@ -32,9 +32,10 @@ The following procedure describes how to create and install a PowerShell binary files will go into the module. As stated previously however, PowerShell can treat a binary cmdlet like a module with no additional effort. As such, a module manifest is useful mainly for combining multiple files into a single package, or for explicitly controlling publication for a - given assembly. For more information, see [How to Write a PowerShell Module Manifest](how-to-write-a-powershell-module-manifest.md). + given assembly. For more information, see [How to Write a PowerShell Module Manifest][03]. - The following code is an extremely simple C# code block that contains three cmdlets in the same file that can be used as a module. + The following code is a simplified C# example that contains three cmdlets in the same file that + can be used as a module. ```csharp using System.Management.Automation; // Windows PowerShell namespace. @@ -73,37 +74,58 @@ The following procedure describes how to create and install a PowerShell binary 1. Package your solution, and save the package to somewhere in the PowerShell module path. - The `PSModulePath` global environment variable describes the default paths that PowerShell will - use to locate your module. For example, a common path to save a module on a system would be - `%SystemRoot%\Users\\Documents\WindowsPowerShell\Modules\`. If you do not use - the default paths, you will need to explicitly state the location of your module during - installation. Be sure to create a folder to save your module in, as you may need the folder to - store multiple assemblies and files for your solution. + The `$env:PSModulePath` global environment variable describes the default paths that PowerShell + uses to locate your module. For example, a common path to save a module on a system would be + `%SystemRoot%\Users\\Documents\WindowsPowerShell\Modules\`. If you don't use + the default paths, you need to explicitly state the location of your module during installation. + Be sure to create a folder to save your module in, as you may need the folder to store multiple + assemblies and files for your solution. - Note that technically you do not need to install your module anywhere on the `PSModulePath` - - those are simply the default locations that PowerShell will look for your module. However, it is + Technically, you don't need to install your module anywhere on the `$env:PSModulePath` - those + are simply the default locations that PowerShell will look for your module. However, it's considered best practice to do so, unless you have a good reason for storing your module - somewhere else. For more information, see [Installing a PowerShell Module](./installing-a-powershell-module.md) - and [about_PSModulePath](/powershell/module/microsoft.powershell.core/about/about_psmodulepath). + somewhere else. For more information, see [Installing a PowerShell Module][05] and + [about_PSModulePath][02]. -4. Import your module into PowerShell with a call to [Import-Module](/powershell/module/Microsoft.PowerShell.Core/Import-Module). +1. Import your module into PowerShell with a call to [Import-Module][07]. - Calling to [Import-Module](/powershell/module/Microsoft.PowerShell.Core/Import-Module) will load - your module into active memory. If you are using PowerShell 3.0 and later, simply calling the - name of your module in code will also import it; for more information, see [Importing a PowerShell Module](./importing-a-powershell-module.md). + Calling to [Import-Module][07] loads your module into active memory. If you are using PowerShell + 3.0 and later, invoking a command from your module in code also imports it. For more information, + see [Importing a PowerShell Module][04]. -## Importing Snap-in Assemblies as Modules +## Module initialization and cleanup code + +If your module needs to do something upon import or removal such as a discovery task or +initialization, you can implement the [`IModuleAssemblyInitializer`][09] and +[`IModuleAssemblyCleanup`][08] interfaces. + +> [!NOTE] +> This pattern is discouraged unless absolutely necessary. To keep PowerShell performant, you should +> lazily load things at the point your commands are called rather than on import. + +## Importing snap-in assemblies as modules Cmdlets and providers that exist in snap-in assemblies can be loaded as binary modules. When the snap-in assemblies are loaded as binary modules, the cmdlets and providers in the snap-in are -available to the user, but the snap-in class in the assembly is ignored, and the snap-in is not -registered. As a result, the snap-in cmdlets provided by Windows PowerShell cannot detect the +available to the user, but the snap-in class in the assembly is ignored, and the snap-in isn't +registered. As a result, the snap-in cmdlets provided by Windows PowerShell can't detect the snap-in even though the cmdlets and providers are available to the session. -In addition, any formatting or types files that are referenced by the snap-in cannot be imported as +In addition, any formatting or types files that are referenced by the snap-in can't be imported as part of a binary module. To import the formatting and types files you must create a module manifest. -See, [How to Write a PowerShell Module Manifest](how-to-write-a-powershell-module-manifest.md). +See, [How to Write a PowerShell Module Manifest][03]. ## See Also -[Writing a Windows PowerShell Module](./writing-a-windows-powershell-module.md) +- [Writing a Windows PowerShell Module][06] + + +[01]: ../cmdlet/writing-a-windows-powershell-cmdlet.md +[02]: /powershell/module/microsoft.powershell.core/about/about_psmodulepath +[03]: how-to-write-a-powershell-module-manifest.md +[04]: importing-a-powershell-module.md +[05]: installing-a-powershell-module.md +[06]: writing-a-windows-powershell-module.md +[07]: xref:Microsoft.PowerShell.Core.Import-Module +[08]: xref:System.Management.Automation.IModuleAssemblyCleanup +[09]: xref:System.Management.Automation.IModuleAssemblyInitializer