Zach Rosenfield recently posted about an obscure memory leak issue when working with PowerShell and the SharePoint object model. You can read his post for details but in summary:
- PowerShell spawns a new thread for each pipeline (essentially any batch of code that runs together).
- SharePoint objects should not be used across multiple threads due to mechanics of the unmanaged heap.
- SharePoint objects used across multiple pipelines result in unmanaged heap leaks until PowerShell closes or you run out of memory.
This PowerShell behavior is easy enough to verify:
PS 1> function Get-ThreadId { [Threading.Thread]::CurrentThread.ManagedThreadId } PS 2> set-alias gt Get-ThreadId PS 3> gt 6 PS 4> gt 4
So we need to ensure that our SharePoint objects are allocated, used and disposed within the same thread. How can we do this? Zach offers two suggestions, but there are actually several options:
Single Line
PS 5> gt; gt; gt 10 10 10 PS 6> gt; ` >> gt; ` >> gt >> 3 3 3
Script
PS 7> @" >> gt >> gt >> "@ > gt.ps1 >> PS 8> .\gt.ps1 8 8
Function
PS 9> function gt2 { >> gt >> gt >> } >> PS 10> gt2 4 4
Inline Script Block
PS 11> &{ >> gt >> gt >> } >> 7 7
My Using Function
PS 12> using Microsoft.SharePoint PS 13> gt; using ($s = [Microsoft.SharePoint.SPSite] 'http://moss') { >> gt >> $s.Url >> gt >> } >> 5 5 http://moss 5
Cmdlet + Wrapper Class
Gary Lapointe has a set of PowerShell cmdlets that use wrapper objects to hide SPSite/SPWeb objects unless you specifically ask for them.
PS 14> $spi = Get-SPSite-gl 'http://moss' PS 15> gt; using ($s = $spi.SPBase) { $s.Url; gt } 8 http://moss 8
The severity of this issue depends on your environment and the kinds of scripts you’re running, but in memory-sensitive and production environments these are definitely some techniques to keep in mind.
February 21, 2009 at 1:10 am
[…] SharePoint+PowerShell Leak Workarounds « Solutionizing .NET […]
August 29, 2009 at 5:02 am
Why not just use “Powershell -STA”? That way it always uses the same thread. WPF and many Com objects require using Powershell this way. I actually haven’t found a compelling reason to use the default MTA mode in Powershell. I’ve found too many little issues with different classes/objects that require the same thread be used throughout the lifetime of the object.
-Stephen
August 31, 2009 at 7:26 am
STA mode is not available in PowerShell v1, but you’re absolutely right that it’s an ideal solution if you have v2.
October 28, 2011 at 7:14 am
[…] Also code called within the same cmd-let/Function and Inline script-blocks are executed in the same thread (see more details on this subject on Keith Dalbys pre-SP2010 blog post here). […]