PowerShell 101: Creating a Module Manifest

Published:20 June 2025 - 5 min. read

Maybe you’ve put together some great functions but struggle to make them cohesive, intuitive, or shareable. Without a way to define your module’s identity and functionality, managing or scaling as your scripts evolve into robust tools can be a headache. Not unless you have a module manifest in place.

Think of a module manifest as the backbone of your PowerShell module. In this guide, you’ll learn what a manifest is and how to create one that simplifies management and enhances usability.

Prerequisites

To follow along with this tutorial, ensure you have:

  • PowerShell 5.1 or PowerShell 7+ installed
  • Administrative access to create files in the PowerShell modules directory
  • A basic PowerShell module (.psm1 file) ready to enhance with a manifest

What is a PowerShell Module Manifest?

A module manifest is a PowerShell data file (.psd1) that contains metadata about your module. It’s essentially a hashtable that tells PowerShell:

  • Which functions to expose
  • What PowerShell versions are compatible
  • Who created the module and when
  • What dependencies the module requires
  • How the module should behave when imported

Without a manifest, PowerShell modules still work but lack professional polish and control. The manifest transforms a collection of scripts into a manageable, versioned package.

Creating and Naming a Manifest

A manifest file must follow specific naming conventions. Name the manifest file after your module with a .psd1 extension. For example, if your module is named ComputerInventory, the manifest file should be ComputerInventory.psd1.

Using New-ModuleManifest

While you can create a manifest manually, the New-ModuleManifest cmdlet simplifies the process. Here’s a complete example:

New-ModuleManifest -Path 'C:\Program Files\PowerShell\Modules\ComputerInventory\ComputerInventory.psd1' `
    -RootModule 'ComputerInventory.psm1' `
    -ModuleVersion '1.0.0' `
    -Guid (New-Guid).Guid `
    -Author 'Your Name' `
    -CompanyName 'Your Organization' `
    -Description 'A module for collecting computer hardware inventory information' `
    -PowerShellVersion '5.1' `
    -FunctionsToExport 'Get-MemoryInfo','Get-ProcessorInfo','Get-StorageInfo' `
    -CompatiblePSEditions 'Core','Desktop'

Understanding the Parameters

Path – Where to create the manifest file. The path shown uses PowerShell’s default module location, but you can create a manifest anywhere. Common locations include:

  • C:\Program Files\PowerShell\Modules\ – System-wide modules (requires admin rights)
  • $HOME\Documents\PowerShell\Modules\ – User-specific modules
  • Any project folder during development

To see all module paths PowerShell searches:

$env:PSModulePath -split ';'

RootModule – The main .psm1 file containing your module’s code. This parameter tells PowerShell which file to load when someone imports your module. The path is relative to the manifest location.

Required vs Optional Parameters

Only the -Path parameter is mandatory. New-ModuleManifest creates a template manifest with default values if you omit other parameters. However, these parameters are highly recommended:

ParameterRequiredPurposeDefault if Omitted
PathYesWhere to save the manifestN/A
RootModuleNoMain module file to loadModule won’t load any code
ModuleVersionNoVersion tracking‘0.0.1’
GuidNoUnique module identifierAuto-generated
AuthorNoModule creatorCurrent user name
FunctionsToExportNoWhich functions to expose‘*’ (all functions)

Key Parameter Explanations:

  • Guid: A unique identifier that distinguishes your module from others. (New-Guid).Guid generates a fresh GUID each time. Keep the same GUID across versions of your module.
  • FunctionsToExport: Controls which functions are available to users. Specify exact function names to hide helper functions and only expose your public API.
  • CompatiblePSEditions: Declares which PowerShell editions your module supports:
    • ‘Desktop’ = Windows PowerShell 5.1
    • ‘Core’ = PowerShell 7+
    • Both = Works on either edition
  • PowerShellVersion: The minimum PowerShell version required. Set this based on the cmdlets and features your module uses.

Exploring Key Attributes in the Manifest

Manifests include various attributes that control module behavior. Here are the most important ones:

Essential Attributes

AttributeDefinitionExample
RootModuleSpecifies the primary module file (.psm1)'ComputerInventory.psm1'
ModuleVersionIndicates the module version for tracking changes'1.0.0'
GUIDA unique identifier for the module'a4d1f2c3-8b7e-4a5d-9c6f-1e2a3b4c5d6e'
AuthorThe module creator’s name'Jane Smith'
DescriptionBrief explanation of the module’s purpose'Collects hardware inventory'

Compatibility Attributes

AttributeDefinitionWhen to Use
PowerShellVersionMinimum PowerShell version requiredSet to ‘5.1’ for broad compatibility
CompatiblePSEditionsWhich PowerShell editions are supportedUse ‘Core’ for PS 7+, ‘Desktop’ for Windows PowerShell
CLRVersionRequired .NET Framework versionOnly needed for Windows PowerShell modules
ProcessorArchitectureRequired processor architectureUse when module has architecture-specific dependencies

Export Control Attributes

The FunctionsToExport attribute deserves special attention. By default, PowerShell exports all functions from a module. This can expose helper functions you intended to keep private.

# Export only public functions
FunctionsToExport = @('Get-MemoryInfo', 'Get-ProcessorInfo', 'Get-StorageInfo')

# This keeps ConvertTo-GB as an internal helper function

Why Keep Functions Private?

There are several reasons to hide certain functions from module users:

  1. Simplified User Experience – Users see only the main functions they need. If your module has 3 main functions but 15 helper functions, exposing everything creates confusion about what to use.
  2. Implementation Flexibility – Private functions can be changed, renamed, or removed without breaking code that depends on your module. Public functions become part of your module’s contract with users.
  3. Preventing Misuse – Helper functions might require specific input formats or assume certain conditions. Direct use could cause errors or unexpected behavior.
  4. Cleaner IntelliSense – When users type your module name followed by a dash, they see only the relevant commands, not internal utilities.

For example, if ConvertTo-GB is a simple calculation helper used by multiple functions, users don’t need direct access to it. They should use the main functions that call it internally.

To see what functions are actually exported:

Get-Command -Module ComputerInventory

Dependency Management

Manifests can also manage module dependencies:

# Modules that must be imported before this module
RequiredModules = @('ActiveDirectory', 'Az.Compute')

# Assemblies that must be loaded
RequiredAssemblies = @('System.Web.dll')

# Scripts to run when module imports
ScriptsToProcess = @('Initialize-Module.ps1')

Testing the Manifest

A manifest with syntax errors or missing references will cause module import failures. Always validate your manifest using Test-ModuleManifest:

Test-ModuleManifest -Path 'C:\Program Files\PowerShell\Modules\ComputerInventory\ComputerInventory.psd1'

This cmdlet checks for:

  • Syntax errors in the manifest file
  • Missing files referenced in the manifest
  • Inconsistent version information
  • Invalid attribute values

If successful, it returns a PSModuleInfo object. If there are errors, it provides detailed error messages.

Common Validation Issues

Here are frequent problems Test-ModuleManifest catches:

  1. Missing RootModule: The .psm1 file doesn’t exist at the specified path
  2. Invalid GUID format: The GUID isn’t in the correct format
  3. Syntax errors: Missing commas, unclosed quotes, or brackets
  4. Version conflicts: CompatiblePSEditions specified without PowerShellVersion

Verifying the Module

After creating and testing your manifest, verify the module loads correctly:

# Import the module
Import-Module ComputerInventory -Force

# Check module details
Get-Module -Name ComputerInventory | Format-List

# Verify exported functions
Get-Command -Module ComputerInventory

The output should show:

  • The correct module version
  • Expected exported commands
  • Proper module type (Script or Binary)
  • The module’s installation path

Advanced Manifest Features

Private Data Section

The PrivateData section stores additional metadata, particularly for PowerShell Gallery publishing:

PrivateData = @{
    PSData = @{
        Tags = @('Inventory', 'Hardware', 'Windows', 'CrossPlatform')
        LicenseUri = 'https://github.com/yourname/ComputerInventory/blob/main/LICENSE'
        ProjectUri = '<https://github.com/yourname/ComputerInventory>'
        IconUri = 'https://raw.githubusercontent.com/yourname/ComputerInventory/main/icon.png'
        ReleaseNotes = 'Initial release with basic hardware inventory functions'
    }
}

Module Initialization

Use ScriptsToProcess to run initialization code before the module loads:

ScriptsToProcess = @('Init-ComputerInventory.ps1')

This script might:

  • Set module-scoped variables
  • Validate prerequisites
  • Configure logging
  • Load configuration files

Nested Modules

For complex modules, you can organize code into nested modules:

NestedModules = @(
    'Private\HelperFunctions.psm1',
    'Public\CoreFunctions.psm1'
)

Summary

You’ve learned how to create professional PowerShell modules using manifests. A well-crafted manifest transforms a collection of functions into a polished, version-controlled module that’s easy to share and maintain.

Key takeaways:

  • Always create a manifest for modules you plan to share
  • Use New-ModuleManifest to ensure proper structure
  • Test manifests with Test-ModuleManifest before distribution

Start by adding a manifest to your existing modules. As you gain experience, explore advanced features like nested modules and initialization scripts to build increasingly sophisticated PowerShell tools.

Hate ads? Want to support the writer? Get many of our tutorials packaged as an ATA Guidebook.

Explore ATA Guidebooks

Looks like you're offline!