36

Sometimes we need to perform small administrative tasks in SharePoint. A simple PowerShell script is a really good tool for that. For instance, such script can enumerate event handlers of a list:

[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint")
$site = new-object Microsoft.SharePoint.SPSite($args[0])   
$site.RootWeb.Lists["MyList"].EventReceivers > C:\MyListHandlers.txt

It's known that objects like SPSite and SPWeb have to be Dispose()-d after a call, otherwise memory leaks occur. The best would be to call

$site.RootWeb.dispose()
$site.dispose()

at the end of this script. But if this is a Powershell script which will only be run once, and we know that PowerShell cleans up after execution - is it so bad to not call dispose()?

So, my question is - is there some danger if sometimes I run scripts like this; will it affect the overall stability of SharePoint farm (or of the server on which I'm running the script)?

naivists
  • 32,681
  • 5
  • 61
  • 85

5 Answers5

19

This has been edited to include a safe, nonspecific answer.

IN GENERAL: dispose everything, because Dispose is the .NET framework's way to free up external resources (such as file handles, TCP ports, database connections, etc). Resources are not guaranteed to be released unless you call Dispose(). So beware. This is the general, non-SharePoint answer.

SPECIFICALLY WHEN DEALING WITH SharePoint: When you close the PowerShell.exe process, the memory is freed. If you need to dispose objects to keep memory pressure down (important in production environments or if you're looping over all sites/webs), make sure to dispose. If not, you don't need to worry about disposing.

The reason why we're so crazy about disposing in the first place is because most SharePoint code runs in long-running processes (either in an ASP.NET worker process or OWSTimer.exe) and failing to dispose can cause difficult-to-troubleshoot, sudden catastrophes (i.e., web server go boom). These catastrophic performance issues/OutOfMemoryExceptions don't affect me most of the time when working in PowerShell. I run ad-hoc scripts, I waste ~3-50MB of RAM because I fail to dispose my objects, I close the PowerShell window and the memory is freed. Most of the time it's a nonissue.

I've built scripts for working with SharePoint, and most of the time I don't bother disposing.

Here is a script wherein I dispose SPSite and SPWeb objects

Here is a script in which I don't bother to dispose an SPSite object

Peter Seale
  • 4,835
  • 4
  • 37
  • 45
  • 1
    Thanks for the answer. Nice scripts in these links, btw. – naivists Jan 04 '10 at 20:06
  • 2
    thanks! There's a good CodePlex project that has collected dozens of SP-related scripts: http://sharepointpsscripts.codeplex.com – Peter Seale Jan 04 '10 at 20:19
  • 2
    Actually that is not exactly true - when the process ends, yes the memory is freed but neither Dispose nor Finalize is called. It all depends on what the object does in Dispose but in reality, this distinction probably doesn't matter. – Josh Jan 05 '10 at 03:45
  • @Peter, Do you have any references to back this up? – Russell Feb 07 '12 at 20:35
  • I am self-referencing and need not cite any higher authority. But seriously, open task manager and close the PowerShell.exe process via task manager, and see what happens. – Peter Seale Feb 07 '12 at 22:23
4

Ideally, you should call Dispose when possible. Even inside of PowerShell.

The SharePoint libraries include a lot of code that is just a wrapper around COM objects - and to make life more fun, many of those COM objects have their own pools and caches. The .NET call to Dispose really just instructs the COM objects that they can free their own objects (that may have a lifespan outside of the calling process).

Here is some more relevant info: http://blogs.msdn.com/sharepoint/archive/2009/02/11/sharepoint-and-powershell-knowledge.aspx

Goyuix
  • 23,614
  • 14
  • 84
  • 128
4

Just follow this.

Even if it's a simple script that frees memory once executed, you never know whether at some point that gonna be copy/pasted into an inner loop of a bigger script :-)

For correctness, you should always dispose SP objects as specified in the link above.

Ariel
  • 5,752
  • 5
  • 49
  • 59
  • 1
    The point about being copy/pasted into a bigger script is soo-o true. I've seen scripts made by some administrators, a combination of different scripts found across the web which "as a side effect" perform also the thing the admin needed at that moment ;-) – naivists Jan 07 '10 at 16:15
2

If the shell is accessing an external resource that has a lifetime longer than the life of the PowerShell script, then it should call Dispose.

However, if it is a resource allocated by the script, then there is no need to clean up. When the script exits, then all memory allocated for the script will be cleaned up.

Larry Watanabe
  • 10,126
  • 9
  • 43
  • 46
  • 2
    This is not true. Even if it's allocated by the script, it could cause out of memory exceptions down the road. (Why people treat scripts as low-level citizens? ☺) – Ariel Jan 07 '10 at 20:46
2

While closing the process will clean things up, be careful. If you were to do a loop involving all the sites in your farm, a missing dispose can quickly eat up significant amounts of memory which will slow your server to a crawl. Since scripting is most helpful for batch operations, always keep that in mind.

James
  • 218
  • 1
  • 4