Using modules with SharePoint cmdlets...

Oct 28, 2015 at 12:52 PM
Hi,

at first I'd like to thank you for creating a wonderful tool. It's fun working with it!

But there is one thing, not working very well:

Actually I'm developing a script based module (.psm1) with several cmdlets referencing SharePoint objects like Microsoft.SharePoint.SPWeb.

I had to notice that the PowerShell Cmdlet Help Editor wasn't able to resolve parameters based on those SharePoint-Objects and ignores all Cmdlets with parameters of that kind.
So i started to get rid off this problem by adding the needed assemblies to my module.

The script below will get all assemblies which get loaded when the SharePoint PowerShell pssnappin is added, copies them to a destination folder and creates a text file, in which those assemblies are listed. This list can be easily copied to the PSD1-file (into section "RequiredAssemblies") of the module and those assemblies will be loaded, when the module is imported the next time. (Btw. in this way the SPCmdlet Help Editor can now handle Cmdlets with SPObject-based parameters)

Of course you will have to copy the assemblies to your module folder before ;-)

And, of course too, you will have to run the script on a SharePoint server.
# Start this Script inside a blank PowerShell session on a SharePoint-Server, where SharePoint snappin is not loaded
# Path to destination folder to where the dll's are copied to
$dstPath = "c:\SPPowerShellSnappinDLLs" # or maybe your module folder
# Get the currently loaded assemblies
$global:AssembliesBefore = [AppDomain]::CurrentDomain.GetAssemblies()
# Count those assemblies
$cntBef = $global:AssembliesBefore.Count
Write-Host "Assemblies before: $cntBef"
# Load SharePoint PowerShell snappin
Add-PSSnapin Microsoft.SharePoint.PowerShell
# Get all loaded assemblies after adding SharePoint PowerShell snappin
$global:AssembliesAfter = [AppDomain]::CurrentDomain.GetAssemblies()
# Count those assemblies
$cntAft = $global:AssembliesAfter.Count
Write-Host "Assemblies after: $cntAft"
# newArrayList to collect different assemblies
$global:AssembliesDiff = New-Object System.Collections.ArrayList
# iterate and collect new assemlbies
foreach($AssemblyAfter in $global:AssembliesAfter)
{
    $match = $false
    foreach($AssemblyBefore in $global:AssembliesBefore)
    {
        if($AssemblyBefore -eq $AssemblyAfter)
        {
            $match = $true
            break
        }
    }
    if(!$match){
        $global:AssembliesDiff.Add($assemblyAfter)
    }
}
# Count resulting assemblies
$cntDif = $global:AssembliesDiff.Count
Write-Host "Different assemblies: $cntDif"
if(($cntAft - $cntBef) -eq $cntDif)
{
    write-Host "got all"
} else {
    Write-Host "got problem"
}
# iterate resulting assemblies and copy them to destination folder
foreach($assembly in $global:AssembliesDiff)
{
    $file = get-item ($assembly.Location)
    $srcDir = [IO.Path]::GetDirectoryName($file)
    $srcFile = [IO.Path]::GetFileName($file)
    $dstDir = (Resolve-Path $dstPath).ProviderPath
    Start-Process -FilePath robocopy -ArgumentList "`"$srcDir`" `"$dstDir`" `"$srcFile`"" -NoNewWindow -Wait
}
# get assemblies and create a simple text list
# you cann use this text list to copy it to your psd1-file under 'RequiredAssemblies'
$files = Get-ChildItem $dstPath | where{$_.Extension -eq ".dll"}
$fileListTxtFile = $dstPath + "\DLLs.txt"
"DLLs" > $fileListTxtFile
foreach($dllFile in $files)
{
    $filename = $dllFile.BaseName
    $fileEntry = '"' + $filename + '"' + ','
    $fileEntry >> $fileListTxtFile
}
Hope this will help others having the same problem.

BR,
Sam