PowerShell and SharePoint Modules

There are a lot of posts about creating modules, for SharePoint, in PowerShell. I decided to write this post so everything I’ve learned is in one place. I’m hoping you learn something from this (as I did).

I have tested the code in this article in SharePoint On-premise  2010, 2013 and 2016.

Modules do have the advantage of, once created and loaded, the functions in your module will be available in every PowerShell session.

Loading the Microsoft.SharePoint.Powershell Snapin

Making sure the Microsoft.SharePoint.PowerShell snapin is always loaded first. This way you are always certain the snapin is available and its not necessary to add it to every script file you create.

Note: this only has to be done once and will be available for all future PowerShell sessions.

Open the PowerShell ISE and run the following, at the command line.  This will create a new profile script (profile.ps1) or open if it already exists.

PS C:> if (!(test-path $profile.AllUsersAllHosts)) {new-item -type file -path $profile.AllUsersAllHosts –force}
powershell_ise $profile.AllUsersAllHosts

Now that the profile.ps1 file is open in the PowerShell ISE, add the following code.  If there is already code in the profile.ps1 file, make sure the following doesn’t already exist and, if not, add it.

$ver = $host | select version
if ($ver.Version.Major -gt 1) {$host.Runspace.ThreadOptions = "ReuseThread"} 
if ((Get-PSSnapin "Microsoft.SharePoint.PowerShell" -ErrorAction SilentlyContinue) -eq $null) 
{
Add-PSSnapin "Microsoft.SharePoint.PowerShell"
}

Here is what the above looks like in my PowerShell session.

profile.ps1 – click on the image to open, full size, in another browser tab.

Make sure to close this PowerShell instance and load a new instance. Test that the Microsoft.SharePoint.PowerShell module has been loaded into your new PowerShell instance, type
Get-SPFarm at the command line and it should now execute without any issues.

Now that we have the Microsoft.SharePoint.PowerShell module loading with every instance of PowerShell, lets move on to creating our first module.

Creating a Script/Module Template

A PowerShell module is fundamentally the same as any other script file with the addition of a few elements.  Let’s start by showing you the fundamental header, body and footer that is in every one of my script files.  In fact, I have this as a template file and use it each time I wish to create a new module.

<#
	.SYNOPSIS
	.DESCRIPTION
	.NOTES
#>
function Verb-YourFunctionName
{
    <#
    .SYNOPSIS

    .DESCRIPTION

    .PARAMETER Web

    .PARAMETER LeadingSpaceCount
        Used to control verbose output. If -1 (default) no verbose output will be rendered. Any value of zero or greater, will generate verbose output to the host. The value of this parameter is used to indent the verbose output. For example, a value of 2 will put two spaces before the output.

    .EXAMPLE
    .EXAMPLE
    #>
    [CmdletBinding()]
    Param(
        [Parameter(Mandatory=$true)][Microsoft.SharePoint.PowerShell.SPWebPipeBind]$Web,
        [Parameter(Mandatory=$false)]
            [System.Int32]$LeadingSpaceCount=-1
    )

    # Setup the leading space for verbose output.
    # If -1 (default) no verbose output will be rendered.  Any value of zero or greater, will generate verbose output to the host.
    # The value of this parameter is used to indent the verbose output.  For example, a value of 2 will put two spaces before the output.
    $ls = ""
    if($LeadingSpaceCount -ge 0){$ls = "".PadRight($LeadingSpaceCount," "); $LeadingSpaceCount++}
    if($LeadingSpaceCount -ge 0)
    {
        Write-Host "$ls- WHAT THIS FUNCTION DOES" -ForegroundColor Yellow
        $ls = "".PadRight($LeadingSpaceCount," ")
        $LeadingSpaceCount++
    }
    try
    {
        [Microsoft.SharePoint.SPWeb]$oWeb = Get-SPWeb $Web
    }
    catch
    {
        Write-Host ([System.String]::Format("$ls- EXCEPTION: [{0}] [{1}]", $sScriptName, $_.Exception.Message)) -ForegroundColor Red
        Write-Host
        throw $_.Exception
    }
    finally
    {
        if($oWeb -ne $null){$oWeb.Dispose()}
    }
    return($SomeReturnVar)
    }

#region Module Members to be Exported
if([System.IO.Path]::GetExtension($MyInvocation.ScriptName) -like ".psm1")
{
    Export-ModuleMember -Function Verb-YourFunctionName -ErrorAction SilentlyContinue
}
#endregion

The header section of the module is simply a set of comments describing the functionality contained within the script/module file.  I tend to breakup my functions into separate files so maintenance is simplified.

The body section of the module is the function or code we are writing.  In the case of my template, the function is named Verb-YourFunctionName.  When being used, the function name will be modified to match the need.

The footer section is where we tell the Add-PSModule code (in the next section) what functions are to be included in our module.

#region Module Members to be Exported
if([System.IO.Path]::GetExtension($MyInvocation.ScriptName) -like ".psm1")
{
    Export-ModuleMember -Function Verb-YourFunctionName -ErrorAction SilentlyContinue
}
#endregion

You will change the Verb-YourFunctionName to the actual name of your function in this module.

Using Add-PSModule to Add Your Module

The last step in this process is to use the Add-PSModule to add the module to your PowerShell session.

Personally I so this in a PowerShell function; one for each different module I wish to create.  For example, I have BMCommon, BMActiveDirectory, BMSharePoint2013, etc. modules.  In most of my client environments, I install these modules so all of my extended functions and variables are available to all instances of PowerShell.

function Add-BMSharePoint2013PSModule
{
    Param(
        [Parameter(Mandatory=$false
            [string]$ModuleInstallPath = "C:\Windows\System32\WindowsPowerShell\v1.0\Modules",
        [Parameter(Mandatory=$false)]
            [int]$LeadingSpaceCount=-1
    )

    $ls = ""
    if($LeadingSpaceCount -ge 0){$ls0 `
        "".PadRight($LeadingSpaceCount," ");
        $LeadingSpaceCount++}

    $sScriptSourcePath = Split-Path -parent `
        $PSCommandPath
    $sModuleName = "BMSharePoint2013"
    $sManifestDescription = "Contains SharePoint 2013 management extended functions."

    $aScriptFiles = "Add-ADUserToSPGroup.ps1",
        "Add-SPAppTile.ps1",
        "Add-SPSitePermissionLevel.ps1"

    $bSuccess = Add-PSModule `
        -ScriptSourcePath $sScriptSourcePath `
        -ModuleName $sModuleName `
        -ScriptFiles $aScriptFiles `
        -ManifestAuthor "Bob Mixon" `
        -ManifestCompanyName "Bob Mixon" `
        -ManifestDescription $sManifestDescription `
        -ModuleInstallPath $ModuleInstallPath `
        -LeadingSpaceCount $LeadingSpaceCount

    return($bSuccess)
}

Add-BMSharePoint2013PSModule -LeadingSpaceCount 0

 

This is all you really need to do!  The high-level steps for accomplishing this are:

  1. Make sure the PowerShell snapin “Microsoft.SharePoint.PowerShell” has been loaded in the PowerShell profile.ps1 file.
  2. Create your new function script file/module; include the Export-ModuleMember at the bottom of the script file/module.
  3. Create and run your module to create and install the module.

Once these steps are complete, you can close your PowerShell instance, open another and your functions will be available.

 

Bob Mixon

My primary goal in life is to support my family, be a friend and enjoy each day as it may be my last. PROFESSIONAL: Senior SharePoint Solution Architect, Senior Information Architect, 5-year Microsoft SharePoint MVP (2006, 2007, 2008, 2009, 2010). You can read my entire profile here.

More Posts - Website

Follow Me:
TwitterLinkedIn

Leave a Reply

Your email address will not be published. Required fields are marked *