91

I have a group of PowerShell scripts that sometimes get run together, sometimes one at a time. Each of the scripts requires that a certain snap-in be loaded.

Right now each script is calling Add-PSSnapin XYZ at the beginning.

Now if I run multiple scripts back-to-back the subsequent scripts throw:

Cannot add Windows PowerShell snap-in XYZ because it is alerady added. Verify the name of the snap-in and try again.

How can I have each script check to see if the snap-in is already loaded before calling Add-PSSnapin?

joshuapoehls
  • 32,695
  • 11
  • 50
  • 61

5 Answers5

135

You should be able to do it with something like this, where you query for the Snapin but tell PowerShell not to error out if it cannot find it:

if ( (Get-PSSnapin -Name MySnapin -ErrorAction SilentlyContinue) -eq $null )
{
    Add-PsSnapin MySnapin
}
Scott Saad
  • 17,962
  • 11
  • 63
  • 84
  • Ah-hah! This is exactly what I needed, thank you! I had tried something similar to this in my experimenting but I didn't know about the -ErrorAction SilentlyContinue. – joshuapoehls Sep 25 '09 at 16:41
  • 2
    The SilentlyContinue is because Get-PSSnapin doesn't quietly return null when if doesn't find the snap in by default. It errors out. – Rich Apr 26 '11 at 15:58
  • 1
    For the lazy: [This article](http://mcpmag.com/articles/2009/05/19/snapins-on-standby.aspx) provides a full code example how to also check if a snap-in is registered before loading it. – herzbube Nov 27 '12 at 10:26
21

Scott already gave you the answer. You can also load it anyway and ignore the error if it's already loaded:

Add-PSSnapin -Name <snapin> -ErrorAction SilentlyContinue
Shay Levy
  • 121,444
  • 32
  • 184
  • 206
  • 6
    That would also silently continue if the snap in did not load for other reasons like not being installed. Which could lead to difficult to diagnose problems for people using your script. – Graham Ambrose Jan 12 '11 at 15:52
  • Right, in that case we can check first if the snap-in is registered. – Shay Levy Jan 13 '11 at 08:21
3

I tried @ScottSaad's code sample but it didn't work for me. I haven't found out exactly why but the check was unreliable, sometimes succeeding and sometimes not. I found that using a Where-Object filtering on the Name property worked better:

if ((Get-PSSnapin | ? { $_.Name -eq $SnapinName }) -eq $null) {
    Add-PSSnapin $SnapinName 
}

Code courtesy of this.

Andy McCluggage
  • 37,618
  • 18
  • 59
  • 69
3

Surpisingly, nobody mentioned the native way for scripts to specify dependencies: the #REQUIRES -PSSnapin Microsoft.PowerShell... comment/preprocessor directive. Just the same you could require elevation with -RunAsAdministrator, modules with -Modules Module1,Module2, and a specific Runspace version.

Read more by typing Get-Help about_requires

Alexey
  • 414
  • 3
  • 10
  • This solution seems to me to be the "right" way to do this. – Grax32 Mar 26 '15 at 13:22
  • 1
    The problem I had with this is that Powershell returns an error if the required snapin is not loaded and I'd assume what everyone would want is for the snapin to be loaded if it's not. – Dwayne Driskill Jun 02 '16 at 14:37
  • 1
    Modules are newer, and it's modules that are loaded automatically as needed, not PSSnapins, you're right. But at least nothing will be broken or littered by running the part of the script that works without the snapin. – Alexey Jun 23 '16 at 11:33
  • As the snap-in is not pre-loaded when running in plain PowerShell, the script will always fail with this pre-check :/ – Dennis Jan 23 '23 at 09:39
1

Scott Saads works but this seems somewhat quicker to me. I have not measured it but it seems to load just a little bit faster as it never produces an errormessage.

$snapinAdded = Get-PSSnapin | Select-String $snapinName
if (!$snapinAdded)
{
    Add-PSSnapin $snapinName
}
Alexey
  • 414
  • 3
  • 10