SPWeb, SPSite, and SPSiteAdministration
objects can sometimes take up large amounts of memory, so using any of
these objects in PowerShell requires proper memory management.
Normally, instances of these objects obtained through cmdlets such as Get-SPWeb are disposed of automatically at the end of the pipeline, but this does not happen to instances stored in variables.
The Start-SPAssignment and Stop-SPAssignment
cmdlets were introduced to spare script authors the need to dispose of
each such object individually. Instead, you can associate multiple
objects with an assignment store, and then dispose of them all
correctly and efficiently with one command.
Dispose Method
If you want to do a straightforward task, such as
change the description of a site, use the cmdlets available, which
dispose of the objects at the end of the pipeline. Here is an example:
PS > $url = "http://SPServer01"
PS > Get-SPWeb -Identity $url | Set-SPWeb -Description "Hello"
If you want to change properties that are not available through the Set-SPWeb cmdlet, such as enabling or disabling the tree view on a single site, the simplest way is to store an instance of an SPWeb object in a variable, change the TreeViewEnabled property, use the Update() method, and finally use the Dispose() method when the change is committed to dispose of the object. Here is an example of this approach:
PS > $spWeb = Get-SPWeb -Identity $url
PS > $spWeb.TreeViewEnabled = $True
PS > $spWeb.Update()
PS > $spWeb.Dispose()
The Start-SPAssignment and Stop-SPAssignment Cmdlets
In the previous example, we disposed of the object using the Dispose() method. As mentioned earlier, it is also possible to dispose of objects using the Start-SPAssignment and Stop-SPAssignment cmdlets.
There are basically three levels of assignments:
No assignment Applies when an object of the type SPWeb, SPSite, or SPSiteAdministration is not assigned to a variable and is disposed of automatically.
Simple assignment All objects are assigned to the global assignment store.
Advanced assignment Objects are assigned to named stores and disposed of when the specific store is disposed.
In the following example, we store an object of the type SPWeb in a variable and dispose of it using a simple assignment.
PS > Start-SPAssignment -Global
PS > $spWeb = Get-SPWeb -Identity $url
PS > $spWeb.TreeViewEnabled = $True
PS > $spWeb.Update()
PS > Stop-SPAssignment -Global
When iterating through multiple sites in a site
collection, the simple assignment lets you associate multiple objects
with an assignment store, and then dispose of them all correctly and
efficiently with a single command, as shown in this example:
PS > Start-SPAssignment -Global
PS > $spSite = Get-SPSite -Identity $url
PS > $spSite | Get-SPWeb -limit All ForEach-Object {
>> $spWeb = $_
>> $spWeb.TreeViewEnabled = $True
>> spWeb.Update()
>> }
PS > Stop-SPAssignment -Global
Here, we first use the Start-SPAssignment cmdlet with the Global switch parameter. Then we iterate through multiple sites in a site collection and change the TreeViewEnabled property on each site. When the last site is processed, we dispose of the objects using the Stop-SPAssignment cmdlet.
The
previous example might seem like a good way to update multiple sites
and handle the disposal with a few simple cmdlets. But suppose that the
site collection contains a thousand sites. An instance object for each
site would then be stored in the global assignment store, and would not
be disposed of until the final site was updated. This is obviously not
a good approach for large site collections.
A better way when iterating through large site
collections is to use the advanced assignment when storing objects
returned from cmdlets in variables and using the Dispose() method to dispose of objects stored in variables created in a loop, as demonstrated in this example:
PS > $spAssignment = Start-SPAssignment
PS > $spSite = Get-SPSite -Identity $url -AssignmentCollection $spAssignment
PS > $spSite | Get-SPWeb -limit All | ForEach-Object {
>> $spWeb = $_
>> $spWeb.TreeViewEnabled = $True
>> spWeb.Update()
>> $spWeb.Dispose()
>> }
PS > Stop-SPAssignment $spAssignment
Here, we assign the instance object returned from the Get-SPSite cmdlet to an advanced assignment store. Then we iterate through each site in the site collection using the ForEach-Object
cmdlet. In the script block, we store the current object in a variable
and change a property. When we are finished with the object, we call
the Dispose() method to immediately dispose of the object before handling the next object passed to the ForEach-Object cmdlet. Finally, when the ForEach-Object cmdlet has processed all objects in the pipeline, we use Stop-SPAssignment to dispose of the object assigned to the $spAssignment variable.