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