如何在PowerShell函数中安全地部署SharePoint对象?

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崩溃(其他任何不喜欢缺乏工作集的东西).这就是为什么单行方法在前一个例子中工作得很好的原因:对象被分配并放置在同一个管道中,并且通过扩展,相同的线程.没有泄漏.


Kei*_*ill 7

不,因为你在调用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.