Pokemon Exception Handling

Repeated exposure to sub-optimal code and a 7 year old son obsessed with Pokemon and here’s what you get:

(If you don’t have a 7 year old boy and aren’t familiar with the song you can read and listen to YouTube’s offering in all it’s delicious cheesiness.)

Exception! (Gotta Catch em all)

 (Pokemon theme song)

I wanna code the very best

Like no bug ever was

To catch them is my real test

To suppress them is my cause

I will travel across the land

Searching far and wide

Each exception to just ignore

The message that’s inside

Exception! (gotta catch em all) it’s you and me

I know it’s my destiny,

Exception! Oh you’re my best friend

But our code we must defend

Exception! (gotta catch em all) it’s sad but true

Our catch block will pull us through,

You breach me and I’ll teach you,

Exception! gotta catch’em all

Gotta catch em all

Yeah…

Every challenge along the way

With courage I will face.

I will battle every day

To claim my bug-free space.

“Finally”,

Don’t feel neglected

There’s no better theme.

We can expect the unexpected

A project manager’s dream!

Exception! (gotta catch em all) it’s you and me

I know it’s my destiny,

Exception!  Oh you’re my best friend

But our code we must defend

Exception! (gotta catch em all) it’s sad but true

Our catch block will pull us through,

You breach me and I’ll teach you,

Exception! gotta catch’em all

Gotta catch em all

Gotta catch em all

Gotta catch em all

Gotta catch em all

Yeah…

(Guitar Solo)

Exception! (gotta catch em all) it’s you and me

I know it’s my destiny,

Exception!  Oh you’re my best friend

But our code we must defend

Exception! (gotta catch em all) it’s sad but true

Our catch block will pull us through,

You breach me and I’ll teach you,

Exception! gotta catch’em all

Gotta catch em all

Exception!

Proxy Layer

Proxy Layer

(To the tune Foxy Lady by Jimi Hendrix)

Proxy

Proxy

You know you’re a cute little mediator

Proxy

You know you’re a sweet little interfacer

Proxy

I want a good response

From your sweet service farm, oh

You’ve got to be so light, so light

Ooh, proxy layer

I see you, heh, gettin’ in between

Proxy

You make me wanna do it asynchronously

Proxy

Ah, baby listen now

I’ve made up my mind yeah

I’m tired of wasting all my precious RAM

You’ve got to be so light, so light

Proxy layer

Here I come

I want a good response

From your sweet service farm, oh

You’ve got to be so light, so light

Ooh, proxy layer

Here I come baby

I’ll dependency inject ya

Ow proxy layer

You broker so good

Yeah, proxy

Yeah, give us some

Proxy

SPDisposeCheck using Static Analysis

I’ve created a static analysis ruleset for SPDisposeCheck!

SPDisposeCheck is a valuable tool developed by a small team within Microsoft Premier Support led by Roger Lamb that inspects an assembly to ensure that SharePoint API objects are properly disposed. Failure to properly dispose SharePoint API objects can cause memory leaks. The SPDisposeCheck tool can be downloaded here:

http://download.microsoft.com/download/B/4/D/B4D279A0-E159-40BF-A5E8-F49ABDBE95C7/SPDisposeCheck.msi

The source and compiled versions are available on CodePlex:

http://spdisposecheckstatic.codeplex.com/

Here are the steps to get this up and running on your SharePoint projects:

Copy the SPDisposeCheck SPDisposeCheckRules.dll and the SPDisposeCheck.exe to your local static analysis rules folder.

Example: C:\Program Files\Microsoft Visual Studio 9.0\Team Tools\Static Analysis Tools\FxCop\Rules

Open a SharePoint project and select Project Properties. Select the Code Analysis tab. You should see a new ruleset available called SPDisposeCheck Rules.

If you select Enable Code Analysis on Builds and Treat Warnings as Error for the SPDisposeCheck ruleset, developers should see any SPDispose errors on build for any code added to the solution.  

Run SPDisposeCheck as Build Task and Automated Unit Test

SPDisposeCheck is a valuable tool devloped by a small team within Microsoft Premier Support led by Roger Lamb that inspects an assembly to ensure that SharePoint API objects are properly disposed. Failure to properly dispose SharePoint API objects can cause memory leaks. The SPDisposeCheck tool can be downloaded here:

 http://download.microsoft.com/download/B/4/D/B4D279A0-E159-40BF-A5E8-F49ABDBE95C7/SPDisposeCheck.msi

 Running SPDisposeCheck has always been a manual procedure that a SharePoint architect or team lead has to make sure is run against all new code before a release; or worse run afterward in order to find a leak that is already in production. A preferable approach would be to add this to a unit test that can be part of a restrictive check-in policy in TFS to ensure no code, in which SharePoint API objects are not properly disposed, can be checked in. Here is how that can be accomplished:

 Copy the SharePoint Dispose Check folder as a sub folder of the solution folder as demonstrated below:

 

 
 Find all projects under the solution that reference the Microsoft.SharePoint namespace and select properties on the project file. Select the Build Events tab and enter the commands below into the Post-build events text box for On Successful Build:

 cd $(ProjectDir)

“..\SharePoint Dispose Check\SPDisposeCheck” “$(TargetPath)” > “$(ProjectName)”.SPDisposeCheck.log

findstr /C:”Total Found:” “$(ProjectName)”.SPDisposeCheck.log

 The Post-build events above will run the SPDisposeCheck tool against the compiled assembly outputting to a file that consists of the assembly name appended with .SPDisposeCheck.log. When the project is compiled the developer will see in the output window “Total Found: X” where X is the count of SPDisposeCheck errors in the assembly. See below:

 

 Any value other than “Total Found: 0” means that a SPDisposeCheck error has been spotted. This is a good start, as developers can be instructed to look for this value but not good enough because it’s too easy to ignore. The next step would be to add this to a unit test which can be tied to a TFS restricted check in policy which cannot be ignored. To do this open the class file right click the class and select “Create Unit Tests”

 

 Add a new unit test to the automatically generated unit tests as seen below: The text specified in the File.OpenText section should be replaced with the name of the assembly in question.


///
///A test to ensure SharePoint objects are properly disposed
///
[TestMethod()]
public void SPDisposeCheckTest()
{
     StreamReader streamReader = File.OpenText(@"..\..\..\Intellinet.SharePoint.Utility\Intellinet.SharePoint.Utility.SPDisposeCheck.log");
     String logFile = streamReader.ReadToEnd();
     Assert.IsTrue(logFile.Contains("Total Found: 0"), logFile);
}

This unit test will fail if the file generated by SPDisposeCheck has any value other than “Total Found: 0” and the contents of the file including the links to Roger’s examples of correcting the particular type of dispose defect can be viewed by the developer by clicking the failed unit test.


Since SPDisposeCheck is performing static analysis on the IL a better approach would be to reverse the SPDisposeCheck code and create a Static Analysis rule that would be available as one of the Static Analysis rulesets in TFS. Until that day this can be a very useful approach for SharePoint architects to control code quality and prevent SharePoint API dispose memory leaks.

Mystery Solved! (SPDisposeCheck Missing Memory Leaks?)

Evidently the reason some memory leaks from Roger Lamb’s blog didn’t appear in my SPDisposeCheck test have to do with some offending sample code being optimized out when compiled to release mode. When compiling to debug all the offending samples are identified by SPDisposeCheck. Note the differences identified in Reflector.

 
 

Release Version:

 
 

 
 

Screen clipping taken: 3/20/2009, 2:32 PM

 
 

 
 

 
 

Debug Version:

 
 

 
 

Screen clipping taken: 3/20/2009, 2:33 PM

 
 

 
 

 
 

Thanks Matt Ranlett and Paul Andrew for solving the mystery.

SPDisposeCheck Missing Memory Leaks?

Checking SharePoint memory leaks I came across this blog entry http://blogs.msdn.com/rogerla/archive/2008/02/12/sharepoint-2007-and-wss-3-0-dispose-patterns-by-example.aspx#SPDisposeCheckID_300 describing different types of coding no-nos that can cause memory leaks. As an exercise I created an assembly with all these samples and ran SPDisposeCheck against the assembly and discovered several of the examples were NOT identified by SPDisposeCheck. I wonder If I could be missing something?
 

The following examples were not identified:

 
 

CreatingSPSiteLeak

AllWebsForEachLeak

AllWebsIndexerLeak

SPLimitedWebPartManagerLeak

WebsLeak

PublishingWebCollectionLeak

GetVariationLeak

PersonalSiteLeak

SPSiteCollectionIndexerLeak

SPSiteCollectionForEachLeak

CrossMethodLeak.MethodB

CrossMethodLeak.MethodC

 
 

 
 

SPDispose output text file:

 
 

Note: This tool may report errors which are not actually memory leaks, otherwise known as false positives.

Further investigation should be done to identify and correct real errors.

It is designed to assist developers in making sure their code adheres to best practices for memory allocation when using SharePoint APIs.

Please see the following for more information:

http://blogs.msdn.com/rogerla/

http://msdn2.microsoft.com/en-us/library/aa973248.aspx

http://msdn2.microsoft.com/en-us/library/bb687949.aspx

———————————————————-

 
 

 
 

ID: SPDisposeCheckID_110

Module: SPDisposeTest.dll

Method: SPDisposeTest.Class1.OpenWebLeak

Statement: local0 := new Microsoft.SharePoint.SPSite(Microsoft.SharePoint.SPContext.get_Current().{Microsoft.SharePoint.SPContext}get_Web().{Microsoft.SharePoint.SPWeb}get_Url()).{Microsoft.SharePoint.SPSite}OpenWeb()

Notes: Constructor called for Microsoft.SharePoint.SPSite but not assigned. This type should be assigned and subsequently disposed

More Information: http://blogs.msdn.com/rogerla/archive/2008/02/12/sharepoint-2007-and-wss-3-0-dispose-patterns-by-example.aspx#SPDisposeCheckID_110

———————————————————-

 
 

 
 

ID: SPDisposeCheckID_150

Module: SPDisposeTest.dll

Method: SPDisposeTest.Class1.AllWebsAddLeak

Statement: OP_POP local0.{Microsoft.SharePoint.SPSite}get_AllWebs().{Microsoft.SharePoint.SPWebCollection}Add(“site-relative URL”)

Notes: Call to SPWebCollection.Add without capturing return value which should be disposed or closed

More Information: http://blogs.msdn.com/rogerla/archive/2008/02/12/sharepoint-2007-and-wss-3-0-dispose-patterns-by-example.aspx#SPDisposeCheckID_150

———————————————————-

 
 

 
 

ID: SPDisposeCheckID_150

Module: SPDisposeTest.dll

Method: SPDisposeTest.Class1.WebsAddLeak(System.String)

Statement: OP_POP local1.{Microsoft.SharePoint.SPWeb}get_Webs().{Microsoft.SharePoint.SPWebCollection}Add(strWebUrl)

Notes: Call to SPWebCollection.Add without capturing return value which should be disposed or closed

More Information: http://blogs.msdn.com/rogerla/archive/2008/02/12/sharepoint-2007-and-wss-3-0-dispose-patterns-by-example.aspx#SPDisposeCheckID_150

———————————————————-

 
 

 
 

ID: SPDisposeCheckID_150

Module: SPDisposeTest.dll

Method: SPDisposeTest.Class1.SPWebCollectionAddLeak(System.String)

Statement: OP_POP local2.{Microsoft.SharePoint.SPWebCollection}Add(strWebUrl)

Notes: Call to SPWebCollection.Add without capturing return value which should be disposed or closed

More Information: http://blogs.msdn.com/rogerla/archive/2008/02/12/sharepoint-2007-and-wss-3-0-dispose-patterns-by-example.aspx#SPDisposeCheckID_150

———————————————————-

 
 

 
 

ID: SPDisposeCheckID_110

Module: SPDisposeTest.dll

Method: SPDisposeTest.Class1.SPSiteCollectionAddLeak

Statement: local0 := new Microsoft.SharePoint.SPSite(“http://moss”).{Microsoft.SharePoint.SPSite}get_WebApplication()

Notes: Constructor called for Microsoft.SharePoint.SPSite but not assigned. This type should be assigned and subsequently disposed

More Information: http://blogs.msdn.com/rogerla/archive/2008/02/12/sharepoint-2007-and-wss-3-0-dispose-patterns-by-example.aspx#SPDisposeCheckID_110

———————————————————-

 
 

 
 

ID: SPDisposeCheckID_240

Module: SPDisposeTest.dll

Method: SPDisposeTest.Class1.SPSiteCollectionAddLeak

Statement: OP_POP local1.{Microsoft.SharePoint.Administration.SPSiteCollection}Add(“sites/myNewSiteCollection”, “DOMAIN\\User”, “roger.lamb@litwareinc.com”)

Notes: Call to SPSiteCollection.Add without capturing return value which should be disposed or closed

More Information: http://blogs.msdn.com/rogerla/archive/2008/02/12/sharepoint-2007-and-wss-3-0-dispose-patterns-by-example.aspx#SPDisposeCheckID_240

———————————————————-

 
 

 
 

ID: SPDisposeCheckID_110

Module: SPDisposeTest.dll

Method: SPDisposeTest.Class1.SPSiteCollectionAddNoLeak

Statement: local0 := new Microsoft.SharePoint.SPSite(“http://moss”).{Microsoft.SharePoint.SPSite}get_WebApplication()

Notes: Constructor called for Microsoft.SharePoint.SPSite but not assigned. This type should be assigned and subsequently disposed

More Information: http://blogs.msdn.com/rogerla/archive/2008/02/12/sharepoint-2007-and-wss-3-0-dispose-patterns-by-example.aspx#SPDisposeCheckID_110

———————————————————-

 
 

 
 

ID: SPDisposeCheckID_110

Module: SPDisposeTest.dll

Method: SPDisposeTest.Class1+CrossMethodLeak.MethodA

Statement: this._siteCollection := new Microsoft.SharePoint.SPSite(“http://moss”)

Notes:          Disposable type not disposed: Microsoft.SharePoint.SPSite

***This may be a false positive depending on how the type was created or if it is disposed outside the current scope

More Information: http://blogs.msdn.com/rogerla/archive/2008/02/12/sharepoint-2007-and-wss-3-0-dispose-patterns-by-example.aspx#SPDisposeCheckID_110

———————————————————-

 
 

 
 

ID: SPDisposeCheckID_120

Module: SPDisposeTest.dll

Method: SPDisposeTest.Class1+CrossMethodLeak.MethodA

Statement: this._web := this._siteCollection.{Microsoft.SharePoint.SPSite}OpenWeb()

Notes:          Disposable type not disposed: Microsoft.SharePoint.SPWeb

***This may be a false positive depending on how the type was created or if it is disposed outside the current scope

More Information: http://blogs.msdn.com/rogerla/archive/2008/02/12/sharepoint-2007-and-wss-3-0-dispose-patterns-by-example.aspx#SPDisposeCheckID_120

———————————————————-

 
 

Total Found: 9

 
 

———————————————————-

 
 

Modules Checked: 1

———————————————————-

spdisposetest.dll

———————————————————-

 
 

Modules Ignored: 0

———————————————————-

———————————————————-

 
 

Methods Ignored: 0

———————————————————-

 
 

 
 

 
 

The source code for my test assembly:

 
 

using System;

using System.Collections.Generic;

using System.Text;

using Microsoft.SharePoint;

using Microsoft.Office.Server;

using Microsoft.Office.Server.UserProfiles;

using Microsoft.SharePoint.Utilities;

using Microsoft.SharePoint.Publishing;

using Microsoft.SharePoint.Portal.WebControls;

using Microsoft.SharePoint.WebControls;

using Microsoft.SharePoint.WebPartPages;

using Microsoft.SharePoint.Administration;

using System.Web.UI;

using System.Web.UI.WebControls;

using System.Web.UI.WebControls.WebParts;

using System.Web;

 
 

 
 

namespace SPDisposeTest

{

public
class
Class1

{

void CreatingSPSiteLeak()

{

SPSite siteCollection = new SPSite(http://moss);

// siteCollection leaked

}

 
 

void CreatingSPSiteExplicitDisposeNoLeak()

{

SPSite siteCollection = null;

try

{

siteCollection = new SPSite(http://moss);

}

finally

{

if (siteCollection != null)

siteCollection.Dispose();

}

}

 
 

void CreatingSPSiteWithAutomaticDisposeNoLeak()

{

using (SPSite siteCollection = new SPSite(http://moss))

{

} // SPSite object siteCollection.Dispose() automatically called

}

 
 

void OpenWebLeak()

{

using (SPWeb web = new SPSite(SPContext.Current.Web.Url).OpenWeb())

{

// SPSite leaked !

} // SPWeb object web.Dispose() automatically called

}

 
 

void OpenWebNoLeak()

{

using (SPSite siteCollection = new SPSite(http://moss))

{

using (SPWeb web = siteCollection.OpenWeb())

{

} // SPWeb object web.Dispose() automatically called

} // SPSite object siteCollection.Dispose() automatically called

}

 
 

void AllWebsForEachLeak()

{

using (SPSite siteCollection = new SPSite(http://moss))

{

using (SPWeb outerWeb = siteCollection.OpenWeb())

{

foreach (SPWeb innerWeb in siteCollection.AllWebs)

{

// explicit dispose here to avoid OOM’s with large # of webs

}

} // SPWeb object outerWeb.Dispose() automatically called

} // SPSite object siteCollection.Dispose() automatically called

}

 
 

void AllWebsForEachNoLeakOrMemoryOOM()

{

using (SPSite siteCollection = new SPSite(http://moss))

{

using (SPWeb outerWeb = siteCollection.OpenWeb())

{

foreach (SPWeb innerWeb in siteCollection.AllWebs)

{

try

{

// …

}

finally

{

if (innerWeb != null)

innerWeb.Dispose();

}

}

} // SPWeb object outerWeb.Dispose() automatically called

} // SPSite object siteCollection.Dispose() automatically called

}

 
 

void AllWebsIndexerLeak()

{

using (SPSite siteCollection = new SPSite(http://moss))

{

SPWeb web = siteCollection.AllWebs[0];

// SPWeb web leaked

} // SPSite object siteCollection.Dispose() automatically called

}

 
 

void AllWebsIndexerNoLeak()

{

using (SPSite siteCollection = new SPSite(http://moss))

{

using (SPWeb web = siteCollection.AllWebs[0])

{

} // SPWeb object web.Dispose() automatically called

} // SPSite object siteCollection.Dispose() automatically called

}

 
 

void AllWebsAddLeak()

{

using (SPSite siteCollection = new SPSite(http://moss))

{

SPWeb web = siteCollection.AllWebs.Add(“site-relative URL”);

// SPWeb web Leaked

} // SPSite object siteCollection.Dispose() automatically called

}

 
 

void AllWebsAddNoLeak()

{

using (SPSite siteCollection = new SPSite(http://moss))

{

using (SPWeb web = siteCollection.AllWebs.Add(“site-relative URL”))

{

} // SPWeb object web.Dispose() automatically called

} // SPSite object siteCollection.Dispose() automatically called

}

 
 

void SPLimitedWebPartManagerLeak()

{

using (SPSite siteCollection = new SPSite(http://moss))

{

using (SPWeb web = siteCollection.OpenWeb())

{

SPFile page = web.GetFile(“Source_Folder_Name/Source_Page”);

SPLimitedWebPartManager webPartManager = page.GetLimitedWebPartManager(PersonalizationScope.Shared);

// SPWeb object webPartManager.Web leaked

} // SPWeb object web.Dispose() automatically called

} // SPSite object siteCollection.Dispose() automatically called

}

 
 

void SPLimitedWebPartManagerNoLeak()

{

using (SPSite siteCollection = new SPSite(http://moss))

{

using (SPWeb web = siteCollection.OpenWeb())

{

SPFile page = web.GetFile(“Source_Folder_Name/Source_Page”);

using (SPLimitedWebPartManager webPartManager = page.GetLimitedWebPartManager(PersonalizationScope.Shared))

{

try

{

// …

}

finally

{

webPartManager.Web.Dispose();

}

}

} // SPWeb object web.Dispose() automatically called

} // SPSite object siteCollection.Dispose() automatically called

}

 
 

void WebsLeak()

{

using (SPSite siteCollection = new SPSite(http://moss))

{

using (SPWeb outerWeb = siteCollection.OpenWeb())

{

foreach (SPWeb innerWeb in outerWeb.Webs)

{

// SPWeb innerWeb leak

}

} // SPWeb object outerWeb.Dispose() automatically called

} // SPSite object siteCollection.Dispose() automatically called

}

 
 

void WebsNoLeak()

{

using (SPSite siteCollection = new SPSite(http://moss))

{

using (SPWeb outerWeb = siteCollection.OpenWeb())

{

foreach (SPWeb innerWeb in outerWeb.Webs)

{

try
//should be 1st statement after foreach

{

// …

}

finally

{

if (innerWeb != null)

innerWeb.Dispose();

}

}

} // SPWeb object outerWeb.Dispose() automatically called

} // SPSite object siteCollection.Dispose() automatically called

}

 
 

void WebsAddLeak(string strWebUrl)

{

using (SPSite siteCollection = new SPSite(http://moss))

{

using (SPWeb web = siteCollection.OpenWeb())

{

SPWeb addedWeb = web.Webs.Add(strWebUrl); // will leak

 
 

} // SPWeb object web.Dispose() automatically called

} // SPSite object siteCollection.Dispose() automatically called

}

 
 

void WebsAddNoLeak(string strWebUrl)

{

using (SPSite siteCollection = new SPSite(http://moss))

{

using (SPWeb web = siteCollection.OpenWeb())

{

using (SPWeb addedWeb = web.Webs.Add(strWebUrl))

{

//..

}

 
 

} // SPWeb object web.Dispose() automatically called

} // SPSite object siteCollection.Dispose() automatically called

}

 
 

void SPWebCollectionAddLeak(string strWebUrl)

{

using (SPSite siteCollection = new SPSite(http://moss))

{

using (SPWeb outerWeb = siteCollection.OpenWeb())

{

SPWebCollection webCollection = siteCollection.AllWebs; // no AllWebs leak just getting reference

SPWeb innerWeb = webCollection.Add(strWebUrl); // must dispose of innerWeb

// innerWeb Leak

} // SPWeb object outerWeb.Dispose() automatically called

} // SPSite object siteCollection.Dispose() automatically called

}

 
 

void SPWebCollectionAddNoLeak(string strWebUrl)

{

using (SPSite siteCollection = new SPSite(http://moss))

{

using (SPWeb outerWeb = siteCollection.OpenWeb())

{

SPWebCollection webCollection = siteCollection.AllWebs; // no AllWebs leak just getting reference

using (SPWeb innerWeb = webCollection.Add(strWebUrl))

{

//…

}

} // SPWeb object outerWeb.Dispose() automatically called

} // SPSite object siteCollection.Dispose() automatically called

}

 
 

void SPControlBADPractice()

{

HttpContext Context = null;

SPSite siteCollection = SPControl.GetContextSite(Context);

siteCollection.Dispose(); // DO NOT DO THIS

SPWeb web = SPControl.GetContextWeb(Context);

web.Dispose(); // DO NOT DO THIS

}

 
 

void SPControlBestPractice()

{

HttpContext Context = null;

SPSite siteCollection = SPControl.GetContextSite(Context);

SPWeb web = SPControl.GetContextWeb(Context);

// Do NOT call Dispose()

}

 
 

void SPContextBADPractice()

{

SPSite siteCollection = SPContext.Current.Site;

siteCollection.Dispose(); // DO NOT DO THIS

SPWeb web = SPContext.Current.Web;

web.Dispose(); // DO NOT DO THIS

}

 
 

void SPContextBestPractice()

{

SPSite siteCollection = SPContext.Current.Site;

SPWeb web = SPContext.Current.Web;

// Do NOT call Dispose()

}

 
 

void PublishingWebCollectionLeak()

{

using (SPSite siteCollection = new SPSite(http://moss))

{

using (SPWeb web = siteCollection.OpenWeb())

{

// passing in web you own, no dispose needed on outerPubWeb

PublishingWeb outerPubWeb = PublishingWeb.GetPublishingWeb(web);

 
 

PublishingWebCollection pubWebCollection = outerPubWeb.GetPublishingWebs();

foreach (PublishingWeb innerPubWeb in pubWebCollection)

{

// innerPubWeb leak

}

// PublishingWeb will leak for each innerPubWeb referenced

} // SPWeb object web.Dispose() automatically called

} // SPSite object siteCollection.Dispose() automatically called

}

 
 

void PublishingWebCollectionNoLeak()

{

using (SPSite siteCollection = new SPSite(http://moss))

{

using (SPWeb web = siteCollection.OpenWeb())

{

// passing in web you own, no dispose needed on outerPubWeb

PublishingWeb outerPubWeb = PublishingWeb.GetPublishingWeb(web);

PublishingWebCollection pubWebCollection = outerPubWeb.GetPublishingWebs();

foreach (PublishingWeb innerPubWeb in pubWebCollection)

{

try

{

// …

}

finally

{

if (innerPubWeb != null)

innerPubWeb.Close();

}

}

// outerPubWeb.Close(); not needed and if called will log warning in ULS log

} // SPWeb object web.Dispose() automatically called

} // SPSite object siteCollection.Dispose() automatically called

}

 
 

void GetPublishingWebNoLeak()

{

using (SPSite siteCollection = new SPSite(http://moss))

{

using (SPWeb web = siteCollection.OpenWeb())

{

// passing in web you own, no dispose needed on singlePubWeb

PublishingWeb singlePubWeb = PublishingWeb.GetPublishingWeb(web);

} // SPWeb object web.Dispose() automatically called

} // SPSite object siteCollection.Dispose() automatically called

}

 
 

void GetVariationLeak()

{

using (SPSite siteCollection = new SPSite(http://moss))

{

using (SPWeb web = siteCollection.OpenWeb())

{

PublishingWeb publishingWeb = PublishingWeb.GetPublishingWeb(web); // Passing in web so no Close() needed

VariationLabel variationLabel = Variations.Current.UserAccessibleLabels[0];

PublishingWeb variationPublishingWeb = publishingWeb.GetVariation(variationLabel); // must be Closed()

// …

} // SPWeb object web.Dispose() automatically called

} // SPSite object siteCollection.Dispose() automatically called

}

 
 

void GetVariationNoLeak()

{

using (SPSite siteCollection = new SPSite(http://moss))

{

using (SPWeb web = siteCollection.OpenWeb())

{

PublishingWeb variationPublishingWeb = null;

try

{

PublishingWeb publishingWeb = PublishingWeb.GetPublishingWeb(web); // Passing in web so no Close() needed

VariationLabel variationLabel = Variations.Current.UserAccessibleLabels[0];

variationPublishingWeb = publishingWeb.GetVariation(variationLabel); // must be Closed()

// …

}

finally

{

if (variationPublishingWeb != null)

variationPublishingWeb.Close();

}

} // SPWeb object outerWeb.Dispose() automatically called

} // SPSite object siteCollection.Dispose() automatically called

}

 
 

void PersonalSiteLeak()

{

// open a site collection

using (SPSite siteCollection = new SPSite(http://moss))

{

UserProfileManager profileManager = new UserProfileManager(ServerContext.GetContext(siteCollection));

UserProfile profile = profileManager.GetUserProfile(“domain\\username”);

SPSite personalSite = profile.PersonalSite; // will leak

}

}

 
 

void PersonalSiteNoLeak()

{

// open a site collection

using (SPSite siteCollection = new SPSite(http://moss))

{

UserProfileManager profileManager = new UserProfileManager(ServerContext.GetContext(siteCollection));

UserProfile profile = profileManager.GetUserProfile(“domain\\username”);

using (SPSite personalSite = profile.PersonalSite)

{

// …

}

}

}

 
 

void SPSiteCollectionIndexerLeak()

{

using (SPSite siteCollectionOuter = new SPSite(http://moss))

{

SPWebApplication webApp = siteCollectionOuter.WebApplication;

SPSiteCollection siteCollections = webApp.Sites;

 
 

SPSite siteCollectionInner = siteCollections[0];

// SPSite siteCollectionInner leak

} // SPSite object siteCollectionOuter.Dispose() automatically called

}

 
 

void SPSiteCollectionIndexerNoLeak()

{

using (SPSite siteCollectionOuter = new SPSite(http://moss))

{

SPSite siteCollectionInner = null;

try

{

SPWebApplication webApp = siteCollectionOuter.WebApplication;

SPSiteCollection siteCollections = webApp.Sites;

 
 

siteCollectionInner = siteCollections[0];

}

finally

{

if (siteCollectionInner != null)

siteCollectionInner.Dispose();

}

} // SPSite object siteCollectionOuter.Dispose() automatically called

}

 
 

void SPSiteCollectionForEachLeak()

{

using (SPSite siteCollectionOuter = new SPSite(http://moss))

{

SPWebApplication webApp = siteCollectionOuter.WebApplication;

SPSiteCollection siteCollections = webApp.Sites;

 
 

foreach (SPSite siteCollectionInner in siteCollections)

{

// SPSite siteCollectionInner leak

}

} // SPSite object siteCollectionOuter.Dispose() automatically called

}

 
 

void SPSiteCollectionForEachNoLeak()

{

using (SPSite siteCollectionOuter = new SPSite(http://moss))

{

SPWebApplication webApp = siteCollectionOuter.WebApplication;

SPSiteCollection siteCollections = webApp.Sites;

 
 

foreach (SPSite siteCollectionInner in siteCollections)

{

try

{

// …

}

finally

{

if (siteCollectionInner != null)

siteCollectionInner.Dispose();

}

}

} // SPSite object siteCollectionOuter.Dispose() automatically called

}

 
 

void SPSiteCollectionAddLeak()

{

SPWebApplication webApp = new SPSite(http://moss”).WebApplication;

SPSiteCollection siteCollections = webApp.Sites;

SPSite siteCollection = siteCollections.Add(“sites/myNewSiteCollection”, “DOMAIN\\User”, “roger.lamb@litwareinc.com”);

// SPSite siteCollection leak

}

 
 

void SPSiteCollectionAddNoLeak()

{

SPWebApplication webApp = new SPSite(http://moss”).WebApplication;

SPSiteCollection siteCollections = webApp.Sites;

using (SPSite siteCollection = siteCollections.Add(“sites/myNewSiteCollection”, “DOMAIN\\User”, “roger.lamb@litwareinc.com”))

{

} // SPSite object siteCollection.Dispose() automatically called

}

 
 

public
class
CrossMethodLeak

{

private SPSite _siteCollection = null;

private SPWeb _web = null;

 
 

public
void MethodA()

{

_siteCollection = new SPSite(http://moss);

_web = _siteCollection.OpenWeb();

}

 
 

public
void MethodB()

{

if (_web != null)

{

string title = _web.Title;

}

}

 
 

public
void MethodC()

{

if (_web != null)

{

string name = _web.Name;

}

}

}

}

}

 
 

 UPDATE:  Mystery Solved! – https://stephenvick.wordpress.com/2009/03/20/mystery-solved-spdisposecheck-missing-memory-leaks/

Error “Value does not fall within the expected range” when calling GetCustomListTemplates method when creating a custom list from a ListTemplate.

When deploying an .stp file within a feature and trying to use this file within a feature receiver FeatureActivated method the list template will not return in the GetCustomListTemplates method unless two properties are specified for the .stp within the elements.xml. These properties are LanguageDisplay and Version. Shown below.  

 
 

Screen clipping taken: 2/18/2009, 12:14 PM

What magical property these properties hold that allow the list template to be seen in the GetCustomListTemplate method I do know. But once I deleted the old .stp file from the gallery, re-deployed and activated the feature all was well.

Follow

Get every new post delivered to your Inbox.