0

I have the following PowerShell module called module.psm1. This is a simplified example. I am doing actions against SharePoint 2013 so I need the snapin for SharePoint in my module

function Test() {
    if ((Get-PSSnapin "Microsoft.SharePoint.PowerShell" -ErrorAction SilentlyContinue) -eq $null) {
        Write-Verbose "Adding" -Verbose
        Add-PSSnapin "Microsoft.SharePoint.PowerShell" -Verbose
    }
    else {
        Write-Verbose "Already loaed" -Verbose
    }

    if ((Get-PSSnapin "Microsoft.SharePoint.PowerShell" -ErrorAction SilentlyContinue) -ne $null) {
        Write-Verbose "Removing" -Verbose
        #Remove-PSSnapin "Microsoft.SharePoint.PowerShell" -Verbose
    }
    else {
        Write-Verbose "Already removed" -Verbose
    }

    Get-PSSnapin "Microsoft.SharePoint.PowerShell"

    if ((Get-PSSnapin "Microsoft.SharePoint.PowerShell") -eq $null) {
        Write-Verbose "Adding" -Verbose
        Add-PSSnapin "Microsoft.SharePoint.PowerShell" -Verbose
    }
    else { 
        Write-Verbose "Already loaded" -verbose
    }
}

Export-ModuleMember -Function 'Test'

In my moduletest.ps1 I have a call to Test and the same logic

Import-Module "$PSScriptRoot\module.psm1" -Force

Test

if ((Get-PSSnapin "Microsoft.SharePoint.PowerShell" -ErrorAction SilentlyContinue) -eq $null) {
    Write-Verbose "Adding" -Verbose
    Add-PSSnapin "Microsoft.SharePoint.PowerShell" -Verbose
}
else {
    Write-Verbose "Already loaed" -Verbose
}

if ((Get-PSSnapin "Microsoft.SharePoint.PowerShell" -ErrorAction SilentlyContinue) -ne $null) {
    Write-Verbose "Removing" -Verbose
    Remove-PSSnapin "Microsoft.SharePoint.PowerShell" -Verbose
}
else {
    Write-Verbose "Already removed" -Verbose
}

Get-PSSnapin "Microsoft.SharePoint.PowerShell"

if ((Get-PSSnapin "Microsoft.SharePoint.PowerShell") -eq $null) {
    Write-Verbose "Adding" -Verbose
    Add-PSSnapin "Microsoft.SharePoint.PowerShell" -Verbose
}
else { 
    Write-Verbose "Already loaded" -verbose
}

When I run function Test from the module the output is:

VERBOSE: Adding
VERBOSE: Removing
VERBOSE: Performing the operation "Remove-PSSnapin" on target "Microsoft.SharePoint.PowerShell".
VERBOSE: Already loaded

So in the module when I remove the SNapIn somehow its not really gone. When I run the code directly form the ps1 file I get:

VERBOSE: Adding
VERBOSE: Removing
VERBOSE: Performing the operation "Remove-PSSnapin" on target "Microsoft.SharePoint.PowerShell".
VERBOSE: Adding

When in my ps1 file the Remove does actually completely remove the SnapIn. Is this normal behavior? I see same behavior for other SnapIns.

Another question I have is:

When I import the module from the console and when I load the SnapIn from my module and execute a command from the snapin in the console then no cmdlets are recognized. When I load the snapin in the module is that being done in a different scope or context?

Danny
  • 746
  • 2
  • 8
  • 20
  • Are you doing this directly on the SharePoint server or via explicit or implicit remoting? What editor / shell are you using. I have seen times when you load SharePoint or Exchange modules, especially in the ISE, the cmdlet don't show until you hit the Refresh button in the command tab. This has not been an thing when using the consolehost and I've not tried twiht VSCode. – postanote Sep 06 '18 at 21:44
  • I am running this form a regular PowerShell console on the SharePoint server. I see the same behavior when loading other snapins in a module vs directly in ps1 – Danny Sep 07 '18 at 07:25
  • 1
    I'm observing the same issue with SharePoint 2016. Load a module, add the snapin, call a function in the module that removes the snapin, and now it can no longer be added/removed. When adding you get the `An item with the same key has already been added.` breaking exception, when trying to remove the snapin you get `No Windows PowerShell snap-ins matching the pattern 'microsoft.sharepoint.powershell' were found.` There is something about removing the snapin inside the module that bungles it up. – shufler Dec 14 '18 at 18:18

1 Answers1

0

I think how you ran this was you did a call to .\moduletest.ps1, and you are describing the output you received from running the Test function within module.psm1 and then the output you received from the lines of code within moduletest.ps1 itself afterwards. This would've been more helpful in the description of your question, in order to reproduce the issue. I wasn't sure, at first, if you were saying you were running the lines from the files individually in the ISA or running lines in the command window or both, and which ones where.

If you remove a snapin in the context of a script, you obviously need to add it back in the same script if you want to use it again within that script or a session - it does get removed. If you perform some commands at the command line, these would be done in the same context/session as a script called before it is ran in. Ex. if you had the line $myVariable = "Sushi" inside a file called mycode.ps1 and you did .\mycode.ps1 at the command line, and then you did Write-Host $myVariable at the command line right after, it would print Sushi.

When you are running your ps1 script lines, this has the ability to remove a snapin, and apparently it does it quickly. When you are trying to remove a snapin from within a function in a module (as you are in module.psm1), it apparently is still happening, but happening much too slow to be re-added (the re-add fails because it thinks it is still there), because you say when you launch snapin-based commands after the removal/reloading, these fail. I think the module is indeed removing the snapin, but just not reporting to your script it is removed when it checks, in order to be able to re-add it. If you add a delay during the module's Test function between the removal and when it tries to do the re-add of probably 100-200 ms, it will probably succeed at re-adding it just fine:

Start-Sleep -m 200

You generally don't ever even really need to remove the snapin, though - it will remove on its own when the session (window) is closed/script is ended. If you load a snapin that is already loaded, it doesn't matter, either - you should be able to keep loading commands.

vapcguy
  • 7,097
  • 1
  • 56
  • 52