2010-09-24 43 views
6

处理函数内创建的对象的正确方法是什么? 我在网站上遇到过这种方法。如何在PowerShell功能中安全地处理SharePoint对象?

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

Dispose方法是否曾在此函数中调用过?

+0

如果你来自.NET世界 - 没有什么像'using'。但我想我在ms connect上看到了一些功能请求。 – stej 2010-09-25 08:42:16

回答

9

首先,您实际上并不希望在此调用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完成(并且完成网页标题的更改)后,才会在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 

因此,在后一个例子你就必须使用不同的实现得到-的SPWeb(一个省略了端块,或者抑制它带有一个开关参数),然后你必须自己处理网站。

另一个重要的细节是,使用sharepoint对象在PowerShell中交互工作会导致内存泄漏。默认情况下,powershell在MTA(多线程单元)中运行,并将使用线程池来执行您的命令。输入的每一行都将使用不同的线程。每次使用不同的线程访问COM对象时,都会为非托管堆泄漏一些内存,因为为上下文切换分配了一个新堆(没有释放旧的堆)。这可以通过启动powershell.exe来缓解-STA开关。这将确保所有命令和管道都使用相同的线程执行,从而避免内存泄漏。也就是说,简单地关闭PowerShell控制台将会重新获得所有的内存,但如果你不小心,长时间运行的脚本可能会让你的内存服务器挨饿,从而导致SharePoint(其他任何不想让工作集缺乏的东西)。 )这就是为什么单线方法在前一个例子中工作得非常好的原因:对象被分配并放置在同一个管道中,并通过扩展来处理相同的线程。没有泄漏。

+0

这是如何适合'Start-SPAssignment-Global' – 2012-03-29 04:15:36

+0

@Lavinski在启动/停止分配的情况下,那么实例不会在流水线运行结束时处理。当你叫停时,他们会被处置掉。 – x0n 2014-01-22 20:14:31

7

不,它不是因为您在调用Dispose之前先退出函数。如果您有必须配置资源,那么我会使用try/finally语句,像这样:

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

约终于做的好处是,你怎么退出try块(或者处置将调用不管成功,因为错误或因为返回声明)。