How can I securely host SharePoint objects in PowerShell functions?

What is the correct way to recycle objects created inside a function? I came across this method on a website.

function get-spweb ([String]$webUrl=$(throw 'Parameter -webUrl is missing!')) { $site = get-SPSite $weburl return $site.OpenWeb() $site.Dispose() } 

Is the Dispose method used in this function?

+6
function powershell sharepoint
source share
3 answers

First of all, you don’t actually want Dispose to be called here anyway - when you call Dispose on an SPSite instance, all websites returned through OpenWeb are also deleted because they are “owned” by these SPSite!

One of the models used by the SharePoint 2010 cmdlets is a kind of “deferred deletion”, which means that the instances of SPWeb are not located until the pipeline in which they are involved is complete. This works as follows:

 function Get-SPWeb { param([uri]$Url) begin { # get SPSite that owns the passed Url $site = new-object microsoft.sharepoint.spsite $url # return specific SPWeb instance $site.OpenWeb() } end { # this disposes owning spsite AND the returned web $site.Dispose() } } 

Now here is how it works in practice (this is one line):

 ps> get-spweb "http://localhost/sites/test" | foreach-object { $_.Title = "New Name"; $_.update() } 

The first part will receive a single instance of SPWeb and pass it the ForEach-Object parts. Only when foreach completes (and finishes changing the name of the website) will the corresponding End block be called in get-spweb , which hosts the website and network. The important thing is that the entire pipeline is one block of code that is executed in a single call.

This will not work interactively:

 ps> $w = get-spweb "http://localhost/sites/test" # calls begin AND end ps> $w.title = "new name" ps> $w.update() # boom! web is already disposed 

So in this last example you will have to use a different get-spweb implementation (one that omits the final block or suppresses it using the switch parameter), and then you have to manage the site yourself.

Another important detail: interactive work in powershell with sharepoint objects will lead to a memory leak. By default, powershell runs in MTA (multi-threaded apartment) and will use the thread pool to execute its commands. Each line entered will use a different thread. Each time you access a COM object with a different thread, you will leak some memory from the unmanaged heap, since a new heap is allocated for the context switch (without the old one being freed.) This can be fixed by running powershell.exe with -STA switch. This ensures that all commands and pipelines are executed on the same thread, avoiding memory leaks. However, just closing the powershell console will return all the memory again, but long scripts may starve on your memory servers if you are not careful about flattening SharePoint (anything else you don't like to get hunger from a working set.) Here why the single-line approach works so well in the first example: the object is distributed and placed in one pipeline, and by extension - the same stream. No leakage.

+9
source share

No, it is not, because you first return from a function before calling Dispose. If you have resources to be removed, I would use the try / finally command as follows:

 $site = Get-SPSite $weburl try { # do stuff to $site until done with it } finally { $site.Dispose() } 

The best part is that dispose will be called regardless of how you exit the try block (either successfully, because of an error, or because of the return statement).

+7
source share

the best logical equivalent would be to use "Start-SPAssignment". more details http://technet.microsoft.com/en-us/library/ff607664(v=office.15).aspx

0
source share

All Articles