Function to Import the SQLPS PowerShell Module or Snap-in

The SQL Server 2014 basic management tools have been installed on the Windows 8.1 workstation that’s being used in this blog article.

When attempting to import the SQLPS (SQL Server PowerShell) module on your workstation, you’ll be unable to import it and you’ll receive the following error message if the PowerShell script execution policy is set to the default of restricted:

Import-Module -Name SQLPS

import-sqlmodule1a.jpg

Import-Module : File C:\Program Files (x86)\Microsoft SQL Server\120\Tools\PowerShell\Modules\SQLPS\Sqlps.ps1 cannot
be loaded because running scripts is disabled on this system. For more information, see about_Execution_Policies at
http://go.microsoft.com/fwlink/?LinkID=135170.
At line:1 char:1
+ Import-Module -Name SQLPS
+ ~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : SecurityError: (:) [Import-Module], PSSecurityException
+ FullyQualifiedErrorId : UnauthorizedAccess,Microsoft.PowerShell.Commands.ImportModuleCommand

It takes a while for the previous error message to be generated and it’s almost like that’s one of the last steps that’s performed when attempting to import the SQLPS module so I’ll plan to check this early on in my function and warn the user as soon as possible.

I recommend setting the script execution policy to RemoteSigned, but you should read the about_Execution_Policies help topic before changing it.

Set-ExecutionPolicy -ExecutionPolicy RemoteSigned

import-sqlmodule3a.jpg

Once that’s done, you’ll be able to import the module but you’ll receive a warning message about unapproved verbs and the current location is changed. Both are very annoying:

Import-Module -Name SQLPS

import-sqlmodule2a.jpg

WARNING: The names of some imported commands from the module ‘SQLPS’ include unapproved verbs that might make them less
discoverable. To find the commands with unapproved verbs, run the Import-Module command again with the Verbose
parameter. For a list of approved verbs, type Get-Verb.

You could write a block of code to work around this problem and add it to your scripts:

if (-not(Get-Module -Name SQLPS)) {
    if (Get-Module -ListAvailable -Name SQLPS) {
        Push-Location
        Import-Module -Name SQLPS -DisableNameChecking
        Pop-Location
    }
}

I’ve seen other variations of the previous code floating around the Internet, but notice my version uses the best practice of filtering left. No need to grab a list of all the modules on your machine with Get-Module -ListAvailable only to pipe them to Where-Object to filter them down to the SQLPS module. That’s inefficient when compared to filtering left by using Get-Module with the Name and ListAvailable parameters.

The problem with adding the previous block of code to all of your SQL related PowerShell scripts is then you’ll be adding redundant code to potentially thousands of scripts. Even worse is the nightmare of finding and modifying all of them if you ever need to change that block of code for some reason. Good luck with that or keep reading to learn a better way.

I also want it to load the SQL PSSnapin if the machine has the SQL Server 2008 or 2008 R2 management tools installed instead of the SQL Server 2012 or higher module:

if (-not(Get-PSSnapin -Name SqlServerCmdletSnapin100, SqlServerProviderSnapin100 -ErrorAction SilentlyContinue)) {
    if (Get-PSSnapin -Name SqlServerCmdletSnapin100, SqlServerProviderSnapin100 -Registered -ErrorAction SilentlyContinue) {
        Add-PSSnapin -Name SqlServerCmdletSnapin100, SqlServerProviderSnapin100
    }
}

I decided to write a function that would take care of all of that for me and by adding it to a script module, I can simple reference the function from any script that I write:

function Import-MrSqlModule {

<#
.SYNOPSIS
    Imports the SQL Server PowerShell module or snapin.

.DESCRIPTION
    Import-MrSQLModule is a PowerShell function that imports the SQLPS PowerShell
    module (SQL Server 2012 and higher) or adds the SQL PowerShell snapin (SQL
    Server 2008 & 2008R2).

.EXAMPLE
     Import-MrSqlModule

.NOTES
    Author:  Mike F Robbins
    Website: http://mikefrobbins.com
    Twitter: @mikefrobbins
#>

    [CmdletBinding()]
    param ()

    if (-not(Get-Module -Name SQLPS) -and (-not(Get-PSSnapin -Name SqlServerCmdletSnapin100, SqlServerProviderSnapin100 -ErrorAction SilentlyContinue))) {
    Write-Verbose -Message 'SQLPS PowerShell module or snapin not currently loaded'

        if (Get-Module -Name SQLPS -ListAvailable) {
        Write-Verbose -Message 'SQLPS PowerShell module found'

            Push-Location
            Write-Verbose -Message "Storing the current location: '$((Get-Location).Path)'"

            if ((Get-ExecutionPolicy) -ne 'Restricted') {
                Import-Module -Name SQLPS -DisableNameChecking -Verbose:$false
                Write-Verbose -Message 'SQLPS PowerShell module successfully imported'
            }
            else{
                Write-Warning -Message 'The SQLPS PowerShell module cannot be loaded with an execution policy of restricted'
            }

            Pop-Location
            Write-Verbose -Message "Changing current location to previously stored location: '$((Get-Location).Path)'"
        }
        elseif (Get-PSSnapin -Name SqlServerCmdletSnapin100, SqlServerProviderSnapin100 -Registered -ErrorAction SilentlyContinue) {
        Write-Verbose -Message 'SQL PowerShell snapin found'

            Add-PSSnapin -Name SqlServerCmdletSnapin100, SqlServerProviderSnapin100
            Write-Verbose -Message 'SQL PowerShell snapin successfully added'

            [System.Reflection.Assembly]::LoadWithPartialName('Microsoft.SqlServer.Smo') | Out-Null
            Write-Verbose -Message 'SQL Server Management Objects .NET assembly successfully loaded'
        }
        else {
            Write-Warning -Message 'SQLPS PowerShell module or snapin not found'
        }
    }
    else {
        Write-Verbose -Message 'SQL PowerShell module or snapin already loaded'
    }

}

You’re probably thinking “That’s a lot of code just to load the module or snap-in”. Look at the bigger picture! It’s not that much when you consider how much space the help and verbose messages are taking up and since I’m only going to write this once, it’s actually a lot less code than hard coding just a few lines in hundreds or possibly even thousands of scripts. Not to mention when I need to modify this code, I go to one script module and modify it instead of having to locate and modify those few lines in each of those scripts.

If the SQLPS module or SQL snapin doesn’t exist on the machine, you’ll receive a warning:

import-sqlmodule4b.jpg

If the execution policy is restricted, this warning will be displayed almost immediately:

import-sqlmodule5a.jpg

Using the Verbose parameter allows you to see exactly what’s occurring otherwise no output is generated if no errors occur:

import-sqlmodule6a.jpg

Using verbose output is much better than inline comments because the user of the function can see the messages without having to open the function or script module as in this case and read through possibly thousands of lines of code to find your comments.

Running the same function on a machine with PowerShell version 2 and the SQL 2008R2 client tools loads the SQL PSSnapin and it also loads the SMO (SQL Server Management Objects) .NET assembly:

import-sqlmodule7a.jpg

Why? Because I frequently use PowerShell with SMO and I can’t ever remember how to load the necessary assembly since this occurs automatically when using the PowerShell module that’s included with the SQL Server 2012 and higher management tools.

The Import-MrSqlModule shown in this blog article is part of my MrSQL PowerShell module which can be downloaded from GitHub.

µ