Per prima cosa, in realtà non si desidera che Dispose venga chiamato qui: quando si chiama Dispose su un'istanza di SPSite, tutti i Web restituiti tramite OpenWeb vengono eliminati perché sono "di proprietà" di tale SPSite!
Uno dei modelli utilizzati dai cmdlet di SharePoint 2010 è una sorta di "rimozione posticipata" che significa che le istanze SPWeb non vengono eliminate finché non viene completata la pipeline in cui sono coinvolte. Questo funziona così:
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()
}
}
Ora ecco come funziona in pratica (questa è una singola riga):
ps> get-spweb "http://localhost/sites/test" | foreach-object {
$_.Title = "New Name"; $_.update()
}
La prima porzione otterrà una singola SPWeb
istanza e passarlo al ForEach-Object
porzione. Solo quando foreach completa (e termina la modifica del titolo del web), il blocco finale corrispondente verrà chiamato in get-spweb
, che dispone del sito e del web. Ciò che è importante è che l'intera pipeline è un singolo blocco di codice che viene eseguito in una singola chiamata.
Questo non sarà lavorare in modo interattivo come questo:
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
Quindi, in questo ultimo esempio che avrebbe dovuto usare una diversa implementazione di get-SPWeb (uno che omette la testata, o evita con un parametro switch) e quindi dovresti smaltire il sito da solo.
Un altro dettaglio importante è che il lavoro interattivo in PowerShell con oggetti sharepoint causerà perdite di memoria. Per impostazione predefinita, powershell viene eseguito in MTA (apartment a più thread) e utilizzerà un pool di thread per eseguire i comandi. Ogni riga inserita utilizzerà un thread diverso. Ogni volta che si accede a un oggetto COM con un thread diverso, si perde una certa quantità di memoria dall'heap non gestito mentre un nuovo heap viene allocato per lo switch di contesto (senza che il vecchio venga liberato). Ciò può essere risolto avviando powershell.exe con l'interruttore -STA. Ciò garantirà che tutti i comandi e le pipeline vengano eseguiti con lo stesso thread, evitando la perdita di memoria. Detto questo, semplicemente chiudendo la console di PowerShell si riacquisterà tutta la memoria, ma gli script di lunga durata potrebbero far morire di fame i server della memoria se non si presta attenzione, eliminando SharePoint (qualsiasi altra cosa non gli piaccia rimanere affamata di working set. Questo è il motivo per cui l'approccio a linea singola funziona così bene nell'esempio precedente: l'oggetto è allocato e disposto nella stessa pipeline, e per estensione, lo stesso thread. Nessuna perdita
Se vieni da mondo .NET - non c'è niente come "usare". Ma immagino di aver visto alcune richieste di funzionalità su ms connect. – stej