处理函数内创建的对象的正确方法是什么? 我在网站上遇到过这种方法。
function get-spweb ([String]$webUrl=$(throw 'Parameter -webUrl is missing!'))
{
$site = get-SPSite $weburl
return $site.OpenWeb()
$site.Dispose()
}
是否在此函数中调用Dispose方法?
答案 0 :(得分:10)
首先,你实际上并不想要在这里调用Dispose - 当你在SPSite实例上调用Dispose时,通过它的OpenWeb返回的所有网页也会因为它们被SPSite“拥有”而被处理掉!
SharePoint 2010的cmdlet使用的其中一个模型是一种“延迟处置”,这意味着SPWeb实例在它们所涉及的管道完成之前不会被丢弃。这样的工作方式如下:
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()
}
}
现在,这是实践中的工作原理(这是一行):
ps> get-spweb "http://localhost/sites/test" | foreach-object {
$_.Title = "New Name"; $_.update()
}
第一部分将获得单个SPWeb
实例并将其传递给ForEach-Object
部分。只有当foreach完成(并完成更改Web标题)时,才会在get-spweb
中调用相应的End块,这将放置站点和Web。重要的是整个管道是一个代码块,可以在一次调用中执行。
此不会以交互方式工作:
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
因此,在后一个示例中,您必须使用不同的get-spweb实现(一个省略了结束块,或者使用switch参数来抑制它),然后您必须自己处理该站点。
另一个重要的细节是,在PowerShell中使用sharepoint对象进行交互式工作会导致内存泄漏。默认情况下,powershell在MTA(多线程单元)中运行,并将使用一个线程池来执行你的命令。输入的每一行将使用不同的线程。每次使用不同的线程访问COM对象时,都会从非托管堆中泄漏一些内存,因为为上下文切换分配了一个新堆(没有释放旧的。)这可以通过启动powershell.exe来缓解-STA开关。这将确保所有命令和管道都使用相同的线程执行,从而避免内存泄漏。也就是说,只需关闭powershell控制台就可以重新获得所有内存,但是如果不小心,长时间运行的脚本可能会使内存服务器匮乏,从而导致SharePoint崩溃(其他任何不喜欢缺乏工作集的东西)。这就是为什么单行方法在前一个例子中工作得很好的原因:对象被分配并放置在同一个管道中,并且通过扩展,相同的线程。没有泄漏。
答案 1 :(得分:7)
不是没有,因为在调用Dispose之前先退出函数。如果您有必须处理的资源,那么我将使用如下的try / finally语句:
$site = Get-SPSite $weburl
try {
# do stuff to $site until done with it
}
finally {
$site.Dispose()
}
最后的好处是无论你如何退出try块(无论是因为错误还是因为返回语句而成功)都会调用dispose。
答案 2 :(得分:0)
最好的逻辑等值是使用“Start-SPAssignment”。 详见http://technet.microsoft.com/en-us/library/ff607664(v=office.15).aspx