Publishing PowerShell script packages
How to use the PowerShellGet module to publish a PowerShell script
Published in Articles on by Michiel van Oosterhout ~ 7 min read
As we've seen in the previous article, PowerShell package providers can discover, install, and manage packages. But the package provider abstraction does not provide a way to publish packages. This is left to the individual package providers to implement. The PowerShellGet package provider exports additional cmdlets to prepare package manifests and publish packages. One type of package it can publish is a script package.
Authoring a script manifest
A PowerShell script package is created from a single PowerShell script (.ps1) file containing code and a manifest. The manifest is required to package the script, and it takes the form of two specially formatted comment blocks with metadata properties:
<#PSScriptInfo
.VERSION 1.0.0
.GUID a2b72a79-5013-4d1e-9c63-1345ac2269a0
.AUTHOR Michiel van Oosterhout
#>
<#
.DESCRIPTION
An example of script file info
#>
The manifest can be validated using Test-ScriptFileInfo, which returns a PSCustomObject with note properties for all the metadata properties. The following metadata properties are supported, but only the ones used in the example above are required.
.AUTHOR.COMPANYNAME.COPYRIGHT.DESCRIPTION.EXTERNALMODULEDEPENDENCIES.EXTERNALSCRIPTDEPENDENCIES.GUID.ICONURI.LICENSEURI.PRIVATEDATA.PROJECTURI.RELEASENOTES.REQUIREDMODULES.REQUIREDSCRIPTS.TAGS.VERSION
Test-ScriptFileInfo adds these additional note properties to the object it returns:
DefinedCommands- All the functions and workflows defined in the script
DefinedFunctions- All the functions defined in the script
DefinedWorkflows- All the workflows defined in the script
Name- The script's file name without the extension
Path- The script's path
ScriptBase- The script's directory
The manifest can be updated in-place using Update-ScriptFileInfo. This is useful when you need to update the .VERSION metadata property in an automated release pipeline.
Creating a PowerShell script package
A PowerShell script package is created and published by invoking Publish-Script. This will validate the manifest, create a NuGet package (.nupkg) file, and upload the package to the package source referred to by the -Repository parameter.
Publish-Script -Path ./Example.ps1 -Repository Example
Executing this this command creates a file named Example.1.0.0.nupkg in the local package source location. On Windows creating and publishing a NuGet package requires NuGet.exe, which can be installed via an interactive prompt when Publish-Script is invoked.
On Windows PowerShell 5.1:
NuGet.exeis required to continuePowerShellGet requires
NuGet.exeto publish an item to the NuGet-based repositories.NuGet.exemust be available in%ProgramData%\Microsoft\Windows\PowerShell\PowerShellGet\or%LOCALAPPDATA%\Microsoft\Windows\PowerShell\PowerShellGet\, or under one of the paths specified inPATHenvironment variable value.NuGet.execan be downloaded from https://nuget.org/nuget.exe. Do you want PowerShellGet to installNuGet.exenow?
(This will install version 2.8 of NuGet.exe to the path specified in the prompt.)
On PowerShell 7.2:
NuGet.exeis required to continueThis version of PowerShellGet requires minimum version '4.1.0' of
NuGet.exeto publish an item to the NuGet-based repositories.NuGet.exemust be available in%ProgramData%\Microsoft\Windows\PowerShell\PowerShellGet\or%LOCALAPPDATA%\Microsoft\Windows\PowerShell\PowerShellGet\, or under one of the paths specified inPATHenvironment variable value.NuGet.execan be downloaded from https://aka.ms/psget-nugetexe. For more information, see https://aka.ms/installing-powershellget. Do you want PowerShellGet to install the latest version ofNuGet.exenow?
(This will install version 6.2 of NuGet.exe to the path specified in the prompt.)
On Linux and macOS creating and publishing a NuGet package requires the dotnet executable, as indicated by this prompt when Publish-Script is invoked:
Publish-Script: For publish operations,
dotnetcommand version 2.0.0 or newer is required to interact with the NuGet-based repositories. Please ensure thatdotnetcommand version 2.0.0 or newer is installed and available under one of the paths specified inPATHenvironment variable value. You can also install thedotnetcommand by following the instructions specified at https://aka.ms/dotnet-install-script.
PowerShell script package metadata
A PowerShell script package is a NuGet package (.nupkg) file, which can be opened on Windows using NuGet Package Explorer or online at https://nuget.info. The script file is located in the root of the package, and most metadata properties in the script's manifest will have been mapped to the corresponding NuGet package metadata. In addition, the following rules apply:
.COMPANYNAMEmaps to Owners;.REQUIREDSCRIPTSmaps to Dependencies;.REQUIREDSCRIPTSis a space- or comma-separated list of string values;.REQUIREDSCRIPTSvalues consist of a name, optionally followed by a colon and a version;.REQUIREDSCRIPTSvalues cannot contain a version with a prerelease label;.REQUIREDSCRIPTSmust be available in the package source;.VERSIONcan contain a prerelease label since PowerShellGet 1.6;.VERSIONprerelease labels are not semver 1.0.0 compatible 2;- the
PSScripttag is added automatically to Tags; - the
PSIncludes_Functiontag is added automatically to Tags if the script declares a function; - the
PSIncludes_Workflowtag is added automatically to Tags if the script declares a workflow; - a
PSCommand_tag is added automatically to Tags for each function and workflow; - a
PSFunction_tag is added automatically to Tags for each function; - a
PSWorkflow_tag is added automatically to Tags for each workflow.
Consuming a PowerShell script package
A PowerShell script package can be installed like any other package. Alternatively the script contained in the script package can be saved to a specific location.
Installing the package
Once published the PowerShell script package can be discovered and installed using standard PowerShell package management commands:
Find-Package -Name Example -ProviderName PowerShellGet
Install-Package -Name Example -ProviderName PowerShellGet
Unfortunately these commands cannot find packages published to a local package source. Fortunately the PowerShellGet package provider exports additional cmdlets specifically to find and install PowerShell script packages, and these cmdlets can be used to find script packages published to a local PowerShellGet repository.
Find-Script -Name Example -Repository example
Install-Script -Name Example -Repository example
Get-InstalledScript -Name Example
PowerShellGet will prompt to add the directory where scripts are installed to the PATH environment variable:
PATHEnvironment Variable ChangeYour system has not been configured with a default script installation path yet, which means you can only run a script by specifying the full path to the script file. This action places the script into the folder
%USERPROFILE%\Documents\WindowsPowerShell\Scripts, and adds that folder to yourPATHenvironment variable. Do you want to add the script installation path%USERPROFILE%\Documents\WindowsPowerShell\Scriptsto thePATHenvironment variable?
You can suppress this prompt with the -NoPathUpdate switch.
(If the script manifest declares any .EXTERNALMODULEDEPENDENCIES or .EXTERNALSCRIPTDEPENDENCIES then a warning will be given if those dependencies are not satisfied.)
Once installed, the script can be used. If the script is a procedural script, it should be executed (e.g. Example.ps1). If the script declares one or more functions, it should be dot sourced (e.g. . Example.ps1) before those function(s) can be invoked. If the directory where scripts are installed has not been added to the PATH environment variable, then its location must be resolved using (Get-InstalledScript -Name Example).InstalledLocation.
Saving the script
As an alternative to installing a PowerShell script package, the script contained in it can simply be saved from the repository to an arbitrary location, and executed or dot sourced from there: Save-Script -Name Example -Repository Example -Path ....
Summary
A PowerShell script is one of the smallest units of distribution available in PowerShell package management, made even more so by the fact that the code and the package manifest are combined in a single file. The package format is based on NuGet with limited support for semantic versioning. Consuming PowerShell scripts distributed this way is further simplified by the option to save the script directly from its package source to a local directory.
-
A local package source can be registered by invoking
Register-PackageSource -Trusted -Provider PowerShellGet -Name Example -Location .... ↩︎ -
The label is validated using
$validCharacters = "^[a-zA-Z0-9]+$". ↩︎