Report dimensioni site collection con Powershell

E’ passato un po’ di tempo dall’ultimo post e mi accingo ad “inaugurare” il nuovo anno esattamente da dove l’avevo lasciato, cioè da Windows PowerShell.

Ne approfitto già che ci sono per ricordarvi che alla prossima SharePoint & Office Conference io e Claudio terremo una sessione su PowerShell 3 e SharePoint 2013, se siete da quelle parti fatevi riconoscere :).

Ma torniamo a noi. Di recente un cliente mi ha chiesto un report giornaliero sulle dimensioni di una serie di site collection (SharePoint 2010). Un possibilità era quella di suggerire al cliente di aprire la site collection con SharePoint Designer tutte le volte che ne aveva voglia e controllare da se. Ottima idea per interrompere subito i rapporti con la maggior parte dei clienti :). Affidarsi alle dimensioni del content database non fornisce sufficienti informazioni sul reale livello di utilizzo del sito in quanto lo stesso database può contenere più site collection. Inoltre penso sia applicabile la stessa considerazione fatta in precedenza.

La strada che ho intrapreso è stata, inutile ribadirlo, quella di utilizzare uno script PowerShell. Concettualmente è molto semplice. Faccio un ciclo su tutte le site collection, memorizzo sia lo spazio utilizzato dalla site collection che dal content database ed invio i risultati via email ad uno o più destinatari . Lo script è pensato per essere eseguito tramite Task Scheduler.

Ecco lo script:

if ((Get-PSSnapin Microsoft.SharePoint.Powershell -ErrorAction SilentlyContinue) -eq $null){
Add-PSSnapin Microsoft.SharePoint.Powershell -ErrorAction SilentlyContinue
}

<## Nelle righe seguenti vado a ricavare l’indirizzo del server SMTP configurato nella Central Administration e imposto qualche variabile di servizio ##>

$nl = [environment]::NewLine
$message = “”
$storage = 0
$ca = Get-SPWebApplication -IncludeCentralAdministration | ?{$_.IsAdministrationWebApplication -eq “True”}
$smtpServer = $ca.OutboundMailServiceInstance.Server.Address

<## A questo punto ciclo su web application e site collection, ordinando i risultati per spazio occupato. Nel ciclo formatto i valori in modo che siano numeri leggibili e creo il messaggio da inviare ##>

Get-SPWebApplication | Get-SPSIte -Limit All | Sort-Object -Descending -Property $_.usage.storage | %{
$db = Get-SPContentDatabase $_.ContentDatabase ;
$dbsize = “{0:N2}” -f ($db.DiskSizeRequired/1GB) ;
$size = “{0:N2}” -f ($_.usage.storage/1GB);
$message += $nl + $nl + $_.Url + “; ” + $size + ” GB; ” + ($_.ContentDatabase -replace “SPContentDatabase Name=”,””) + “; ” + $dbsize + ” GB;”
$storage += $_.usage.storage
}

<## Aggiungo al messaggio la somma dello spazio occupato da tutte le site collection. Alle righe successive imposto il messaggio di posta e lo invio. ##>

$message += $nl + $nl + “Totale storage {0:N2}” -f ($storage/1GB) + ”  GB”

$date = Get-Date
$msg = new-object Net.Mail.MailMessage
$smtp = new-object Net.Mail.SmtpClient($smtpServer)
$msg.From = “me@mioserver.it
$msg.ReplyTo = “me@mioserver.it
$msg.To.Add(“te@tuoserver.com“)
$msg.subject = “Report storage site collections ” + $date.ToShortDateString()
$msg.body = $message
$smtp.Send($msg)

Puoi scaricare lo script dal mio SkyDrive, a tuo rischio e pericolo, si intende 🙂

Se invece questo tipo di informazioni servono una tantum e nel più breve tempo possibile devo convenire con Igor che il comando stsadm -o enumsites -url http://miosito è probabilmente la soluzione più veloce. Anche se io continuo a preferire the Powershell way 🙂

Happy PoSH
– Riccardo

SharePoint & Office Conference 2013


Materiale per SharePointCommunity.it

Live dal mio nuovissimo Lenovo W530 faccio solo una rapida escursione nel mondo esterno per segnalare che nei giorni scorsi è stato pubblicato su SharePointCommunity.it il video della sessione che ho tenuto durante l’evento SharePoint Governance, tenutosi Martedì 30 Ottobre a Milano. In realtà a causa di problemi “tecnici” la sessione è stata registrata in un secondo momento, ma sono sicuro che fa lo stesso 🙂

Da pochi minuti inoltre è stato pubblicato un nuovo articolo su come rinominare una web application in SharePoint. Approfitto per ringraziare Achille della disponibilità 🙂

Qualcuno mi ha segnalato che ha problemi con la riproduzione del video, se così fosse fatecelo sapere che provvederemo a rimediare tempestivamente.

– Riccardo


Vintage Weekend Part II: Ottenere tutti gli utenti del sito con Powershell

Seconda parte della serie Vintage Weekend. Se vi siete persi la prima parte si tratta di esempi di script Powershell pensati per essere utilizzati con SharePoint 2007.

In questo caso il pretesto mi è stato dato da un cliente che aveva bisogno di conoscere tutti gli utenti e gruppi di una site collection. Come nell’esempio precedente trattandosi si SharePoint 2007 è necessario referenziare le librerie che interrogheremo prima di procedere. Successivamente, una volta memorizzato l’oggetto “site collection” effettueremo un ciclo su tutti i gruppi del sito e per ognuno di questi stamperemo a video tutti i nomi utente.

[System.Reflection.Assembly]::LoadWithPartialName(“Microsoft.SharePoint”)
$site = New-Object Microsoft.SharePoint.SPSite(“http://yourservername/sites/yoursitecollection “)
$groups = $site.RootWeb.sitegroups
foreach ($grp in $groups) {
“Group: ” + $grp.name;
foreach ($user in $grp.users) {
”  User: ” + $user.name
}
}
$site.Dispose()

Happy PoSH
– Riccardo


Vintage Weekend: Elencare tutti i documenti di un sito con Powershell su SharePoint 2007

Chiamatelo Vintage, chiamatelo Legacy, chiamatelo un po’ come vi pare ma SharePoint 2007 è ancora là fuori e gode di discreta salute.

Proprio qualche giorno fa mi è stata chiesta un indicazione di massima sul numero totale di elementi presenti in una web application. In un primo momento ho pensato che la pagina “storage manager” potesse aiutarmi, ma così non è stato in quanto questa pagina mostra al massimo i primi 100 “contenitori” più utilizzati.

Ho trovato la risposta, come in molti altri casi in Windows Powershell. Non mi stancherò mai di ripetere infatti che, anche se solo in SharePoint 2010 sono state create delle cmdlet apposite, già dalla versione 2007 è possibile accedere al modello oggetti di SharePoint da script.

Il concetto è molto semplice, selezionare una web application ed effettuare un ciclo su tutte le site collection, tutti i siti, tutti gli elenchi e scrivere URL, titolo e tipologia della lista in un file di testo. Infine ho anche aggiunto il conteggio degli elementi presenti in ciascuna lista.

[void][System.Reflection.Assembly]::LoadWithPartialName(“Microsoft.SharePoint”)
$farm = [Microsoft.SharePoint.Administration.SPFarm]::Local

foreach ($spService in $farm.Services) {
if (!($spService -is [Microsoft.SharePoint.Administration.SPWebService])) {   continue;  }
$webApp = [Microsoft.SharePoint.Administration.SPWebApplication]::Lookup(“http://2007.sharepoint.corp“)

foreach ($site in $webApp.Sites) {
foreach ($web in $site.AllWebs) {
foreach ($list in $web.Lists) {
$values = $web.Url + “,” + $list.Title + “,” + $list.BaseType + “,” + ($list.items).count
add-content -path “D:\Logs\ilmiosito-items.csv” -value $values
}
$web.Dispose();
}
$site.Dispose()
}
}

Una volta eseguito lo script potrete aprire il file CSV in Excel ed utilizzarlo per fare tutte le statistiche che vi servono.

Happy Vintage PoSH
– Riccardo


Verificare lo stato di un servizio con Powershell

Buon ferragosto a tutti! Aspettando la partenza per la “Maremma Antibiotica” (cit. il Maestro M.C. :)) ne approfitto per condividere un semplice script Powershell per verificare lo stato di un servizio (inteso come Windows Service).

Il contesto mi è stato offerto dalle mie VM di test di SharePoint 2013, Server e Foundation, che ad ogni avvio mi si presentano con i servizi di SQL Server stoppati. Premesso che sarebbe stato più corretto ricercare la causa di questo comportamento, mi sono divertito ad imparare qualcosa che non avevo mai provato.

Cominciamo dando un occhiata allo script completo:

gsv | ?{$_.Name -match “SQL”} | foreach-object{
if ($_.Status -ne “Running”){
try {
Start-Service $_.Name -ErrorAction SilentlyContinue
} catch {
write-host “unable to start service”, $_.Name -nonewline
}
}
}

Per prima cosa ho utilizzato la cmdlet Get-Service nella sua forma ridotta (alias) gsv. Ho selezionato solo i servizi nel cui nome è presente la stringa utilizzando il filtro ? {$_.Name -match “SQL”}. Per ciascun elemento (servizio) ne verifico lo stato sfruttando la proprietà Status. Se diverso da “Running” provo ad avviarlo utilizzando la cmdlet Start-Service. Per evitare che lo script si blocchi in caso di errore ho inserito quest’ultimo comando in una “condizione” try – catch, stampando a video il nome del servizio che non ri riesce ad avviare.

Nel caso in cui non dovesse essere possibile selezionare con la stessa query più servizi, possiamo creare un array di servizi (in realtà nomi di servizi e “ciclare” su questi). Vediamo come.

$services = @(“THREADORDER”,”SPOOLER”,”WSEARCH”) ## In questo modo creiamo l’elenco dei servizi da verificare

## nelle successive righe eseguiamo il ciclo sui nomi, otteniamo il servizio corrispondente e proviamo ad avviarlo

foreach ($service in $services){
$svc = gsv $service
if ($svc.Status -ne “Running”){
try {
Start-Service $svc -ErrorAction Stop
} catch {
Write-Host “Unable to start service”, $svc.Name -nonewline
}
}
}

Una volta completato lo script l’ho salvato in un file .ps1 è ho schedulato la sua esecuzione all’avvio del server. Come? Sempre con Powershell ovviamente 🙂

Powershell a parte, avete avuto modo di vedere (e di votare!!!) il video di Green Team nella pagina del concorso SharePoint’s Got Talent? No? Il video è stupendo e ricco di attori sconosciuti ma di gran talento, votare (eh guardare) per credere 😀

Ora vado a terminare le valigie, tra poche ore si parte!!
– Riccardo

 


Aggiornare campi publishing images con Powershell

Di recente ho avuto l’esigenza di aggiornare tutti i valori di un campo di tipo “publishing images“. Anche se non si trattava di un numero esagerato di immagini ho provato a cercare un alternativa, trovo che l’update di questi campi da UI sia infatti molto “noioso”. L’alternativa è ovviamente Powershell :).

Ho scoperto che bastano verametne poche righe per completare l’operazione e, soprattutto, lo stesso script contiene tanti spunti utili in molti altri scenari.

Ma veniamo al dunque. Cominciamo a memorizzare nelle “solite” variabili gli oggetti site collection e web.

$spSite = Get-SPSite http://sharepoint
$spWeb = $spSite.RootWeb

Tocca ora all’elenco che contiene le immagini da aggiornare.

$spList = $spWeb.Lists[“Links”]

A questo punto, facendo un ciclo su tutti gli elementi dell’elenco, memorizziamo nella variabile $image il campo PublishingPageImage. Trattandosi di un tipo di dato “complesso” la nostra variabile avrà diverse proprietà. Una di queste è ImageUrl che contiene le informazioni relative al path dell’immagine.

Nel mio caso l’aggiornamento prevedeva il campio di origine dell’immagine mentre il nome del file doveva rimanere invariato. Di conseguenza ho aggiornato la proprietà ImageUrl sostituendo il vecchio path con quello corretto. Per questa operazione ho utilizzato l’operatore replace.

In un primo momento pensavo che questo, seguito solo dal comando $listitem.Update(), bastasse per aggiornare le mie immagini, ma mi sbagliavo. A questo punto abbiamo aggiornato solo una proprietà dell’oggetto ed è quindi necessario reimpostare correttamente il valore del nostro campo. Il codice di esempio della pagina su MSDN mi è stata molto utile per capire questo passaggio.

foreach($listitem in $spList.Items){
$image = $listitem[“PublishingPageImage”]
$image.ImageUrl = $image.ImageUrl -replace “/SiteAssets/”, “/SiteCollectionImages/”
$listitem[“PublishingPageImage”] = $image;
$listitem.Update()
}

Alla fine dello script rilasciamo l’oggetto “web” e abbiamo finito.

$spWeb.Dispose()

Potete scaricare lo script qui.

Happy Posh
– Riccardo


Modifica e test del server SMTP con Powershell

Chissà perchè nel passaggio 2007 > 2010 Microsoft non abbia ritenuto di mettere a disposizione una cmdlet per la configurazione del server di posta in uscita (SMTP), corrispondente al vecchio comando stsadm -o email. Technet riporta infatti ancora lo stesso comando (http://technet.microsoft.com/en-us/library/cc263462.aspx) e anche nella pagina relativa ai mapping stsadm / Powershell (http://technet.microsoft.com/en-us/library/ff621084.aspx) non si trova corrispondenza.

Questo non signifca però che non si possa fare, bastano poche righe 🙂

Prima di tutto memorizzo i dati da configurare all’interno di quattro variabili.

$smtpServer = ‘mail.sharepoint.corp’
$smtpFrom = ‘admin@sharepoint.corp’
$smtpReplyTo = ‘admin@sharepoint.corp’
$smtpCharset = 65001

In una nuova variabile memorizzo l’oggetto “Web Application” corrispondente alla Central Administration*.

$caWebApp = Get-SPWebApplication -IncludeCentralAdministration | ?{ $_.IsAdministrationWebApplication }

e utilizzo infine il metodo UpdateMailSettings di questo oggetto per configurare il server di posta in uscita.

$caWebApp.UpdateMailSettings($smtpServer, $smtpFrom, $smtpReplyTo, $smtpCharset)

* Dato che la configurazione del server SMTP può essere personalizzata per Web Application basterà selezionare la web application desiderata al posto della Central Administration per modificarne la configurazione.

Una volta apportata la modifica al server di posta è consigliabile effettuare un test per verificare che tutto funzioni a dovere. Anche per questo possiamo usare poche righe di Powershell. Tramite il metodo SendMail dell’oggetto SPUtility (http://msdn.microsoft.com/en-us/library/ms477270.aspx) invieremo un email sfruttando la configurazione SMTP di un sito SharePoint. Più facile a farsi che a dirsi.

$web = Get-SPWeb “http://intranet
$sent = [Microsoft.Sharepoint.Utilities.SpUtility]::SendEmail($web,$false,$false,”riccardo@sharepoint.corp”,”Oggetto del messaggio”,”Corpo del messaggio”)

La variabile $sent assumerà il valore di True o False a seconda che l’invio del messaggio riesca o meno. Semplice no?

– Riccardo