Prism is a PowerShell module manager inspired by NuGet. Run prism install
in a source code repository and Prism will
save modules privately into a "PSModules" directory in that repository. Prism let's you:
- Package and deploy modules side-by-side with the app or tool that uses them without needing to install modules globally ahead of time.
- Not worry about what modules are or aren't installed. Scripts can import and use modules from the "PSModules" directory in the script's source code repository.
- Avoid comitting modules to the source code repository. Team members and build processes run
prism install
to get modules installed.
- Windows PowerShell 5.1 and .NET 4.6.1+
- PowerShell 6+ on Windows, Linux, or macOS
- PackageManagement 1.3.2 to 1.4.8.1 and PowerShellGet 2.1.5 to 2.2.5.
We recommend installing Prism globally from the PowerShell Gallery into the current user's scope:
Install-Module -Name 'Prism' -Scope CurrentUser -Repository 'PSGallery' -Force
If you only have the "PSGallery" repository (run Get-PSRepository
to get a list), you can omit the -Repository
parameter. If "PSGallery" repository is trusted (run Set-PSRepository
to configure a repository's installation
policy), you cam omit the -Force
parameter.
In your source code repository, create a "prism.json" file in the root of your repository. It should have a PSModules
property that is an array of modules that should be installed.
{
"PSModules": [
{
"Name": "Whiskey",
"Version": "0.*"
},
{
"Name": "Yodel",
"Version": "1.*"
}
]
}
Then, open a PowerShell prompt in the same directory as the "prism.json" file and run
prism install
When Prism is done running, there should be a PSModules directory in the current directory that contains all the private modules listed in the prism.json file. There will also be a prism.lock.json file, which should also get checked into source control along with the prism.json file.
To add Prism to your build process, you'll need to install its dependencies, install Prism, then run it. Prism has an
init.ps1 script that can do all this for you. Each release of Prism has an init.ps1 script whose URL you can find on the
GitHub releases page.. Once you have the URL, you can add
this snippet to your build (replacing VERSION
with the version of init.ps1 you want to use):
Invoke-WebRequest 'https://github.com/webmd-health-services/Prism/releases/download/VERSION/init.ps1' | Invoke-Expression
prism install
If you always want to use the latest version of the init.ps1 script instead of pinning to a specific version, use this URL.
Make sure you've run prism install
at least once, and check the file it creates, prism.lock.json
, into your
repository. If you don't, the prism install
command on the server will always generate the lock file, which makes
builds take longer.
Each module object in the prism.json file must have a Name
property, which is the name of the module to install. Each
object can also have a Version
property, which is the version to install. Wildcards are supported, so you can pin to
the latest major, minor, or patch versions of a module. The default is to install the latest version of a module. To
allow pinning to prerelease versions, add an AllowPrerelease
property whose value is true
.
The Version
property is optional. If omitted, Prism will install the latest version. Use wildcards to pin to specific
minor, patch, or prerelease versions of a module. Prism assumes modules use Semantic Versioning.
For example, if a module has versions 5.2.0-rc1
, 5.1.1
, 5.1.0
, 5.1.0-rc1
, 5.1.0-beta1
, 5.0.0
, 5.0.0-rc1
,
4.10.1
, 4.10.0
, and 4.9.0
:
5.*
would pin the module to the latest release of version 5,5.1.1
(prerelease versions are ignored).4.10.*
would pin the module to the latest prerelease of version4.10
,4.10.1
(prerelease versions are ignored).5.*-rc*
would pin the module to the latest release or prerelease of version 5,5.2.0-rc1
. In order to use prerelease versions, the version must contain a-
prerelease prefix.
Modules are pinned/locked to a specific version of a module the first time prism install
is run. The command generates
a prism.lock.json
file, with the specific versions of each module to install. Once a lock file is created, prism install
will only install the module versions listed in the lock file. To update the versions in the lock file to
newer versions or to reflect changes made to the prism.json
file, run prism update
.
Modules will always be saved in the same directory as the "prism.json" file, in a directory named "PSModules". If
installing nested modules for a module (i.e. the install directory contains a .psd1 or .psm1 file), modules are saved to
a "Modules" directory. You can customize this directory name with the PSModulesDirectoryName
option in your
prism.json
file:
{
"PSModules": [],
"PSModulesDirectoryName": "SomeOtherDirName"
}
To install modules in the same directory as the "prism.json" file, use .
as the "PSModulesDirectoryName" value.
To put the PSModules directory in a different directory, put a "prism.json" file in that directory. Use the "prism"
command's -Recurse
switch to run prism against every prism.json file under the current directory.
By default, PowerShell supports installing multiple versions of a module side-by-side by installing a module into a
directory named after the module's version number. Because Windows has a 260 character limit on paths, Prism instead
flattens modules on installation by removing this versioned directory. You can prevent Prism from flattening the
installation location by setting the FlattenModules
configuration setting to false
:
{
"FlattenModules": false
}
To use a private module installed by Prism, use Import-Module
and pass the path to the module instead of a module
name. Use Join-Path
and join the $PSScriptRoot
automatic variable—the path to the current script's directory—with
the relative path to the module in the PSModules directory.
# If a script is in the same directory as the "PSModules" directory.
Import-Module -Name (Join-Path -Path $PSScriptRoot -ChildPath 'PSModules\Whiskey' -Resolve)
# If the script is in a sub-directory.
Import-Module -Name (Join-Path -Path $PSScriptRoot -ChildPath '..\PSModules\Whiskey' -Resolve)
To import and use a private, nested module installed by Prism, use Import-Module
and pass the path to the module
instead of a module name. Use Join-Path
and join the path to your module's directory with the relative path to the
module.
$script:moduleDirPath = $PSScriptRoot
Import-Module -Name (Join-Path -Path $script:moduleDirPath -ChildPath 'Whiskey' -Resolve)
DO always use the Import-Module
cmdlet's Alias
, Cmdlet
, and Function
parameters to explicitly list what
commands your script is importing and using. It makes upgrading easier when you know what commands you're using.
DO NOT depend on PowerShell's automatic module loading. That functionality won't see the private modules Prism installs.
DO ship your module's dependencies as nested modules. Use Prism to manage these as it structures dependencies to avoid long directory paths. Import dependencies from that private location. A module can have its own version of a module loaded privately.
DO NOT use the NestedModules
module manifest property. Use an explicit Import-Module
in your root module to
import dependencies saved inside your module.
DO NOT use the TypesToProcess
module manifest property, i.e. don't specify extended type data in a .ps1xml file.
PowerShell writes errors and refuses to import a module if its type file has previously been loaded. Instead, in your
root module, check if members are present on types, and add them using the Update-TypeData
cmdlet if they are not
present.
TRY NOT to use or load private assemblies (i.e. .dll files). Only one version of an assembly can be loaded at a time, and once an assembly is loaded, PowerShell silently doesn't load other versions later. Users may get cryptic errors about missing properties and objects. If you must use an assembly, add code in your root module to detect if the correct version of your assembly is loaded, and write a terminating error if it isn't, asking the user to restart PowerShell.
Prism requires that PackageManagement and PowerShellGet are installed and available globally. See the "System Requiremens" for the versions of each that should be installed.
For each module and version in the lock file, prism install
calls the Save-Module
cmdlet to install that specific
version. It passes the name of all installed repositories to the Save-Module
cmdlet's -Repository
parameter. The
Save-Module
command loops through each repository, and installs the first module it finds.
The prism install
command first uses Get-Module
to see if the correct version of the module is installed in the
private PSModules directory. If it is, the module is not re-installed. If it isn't, the module is installed using the
Save-Module
command.
It calls Find-Module
once to get the latest version of all the modules in the "prism.json" file. For each module with
a specific version that doesn't match the latest version, Prism will call Find-Module
again to get all versions of
that module. (If the module's version from the "prism.json" file contains the prerelease suffix, -
, or the build
suffix, +
, or the AllowPrerelease
proeprty exists and is set to true
, prerelease versions will be included.) Prism
selects the first version returned by Find-Module
that matches the version wildcard from the "prism.json" file. It
writes these versions to a lock file, which is used by the prism install
command to install the modules.
If you get an error that "The term 'prism' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.", make sure Prism is actually installed. Run this command:
Get-Module -Name Prism -ListAvailable
If the above command returns the module, it most likely means that your $PSModuleAutoloadingPreference
variable is not
set to ALL
. To fix this, you can:
- Set
$PSModuleAutoloadingPreference
toALL
. - If
$PSModuleAutoloadingPreference
is set toMODULEQUALIFIED
, runPrism\prism install
instead. - If
$PSModuleAutoloadingPreference
is set toNONE
, import Prism first,Import-Module Prism
then runprism install
.
For bug reports and feature requests, submit an issue. If you want to contribute a feature, enter an issue first and work with the team through the issue to discuss and get approval before beginning.
See the CHANGELOG. Also, the changelog and this readme are both included with the Prism module.