At my current client, we are setting up a MOSS 2007 web application that provides collaboration sites for their communities of practice. We have an initial site hierarchy of 155 sites across 20 site collections. How do you set that all up? Although we set up the 20 site collections manually (most got their own content databases, but that’s not the reason we did them manually. With only 20 items, in the time it would have taken to set up a script, it could also just be done, and it was good training for a new SharePoint support person.
For the sites however, we wanted to have each site based on the Publishing site template, have a set of preconfigured lists, use a branding feature we had installed, and have a welcome page that used a particular layout and had a particular set of web parts. Because it was a publishing site, we couldn’t save it as a template. However, we could save lists as templates, so that’s what we did.
- Save a list as a template:
$list.SaveAsTemplate($filename, $templatename, $list.Description, $true); #true if you want to #include content, $false if you don’t.
- Once we have several templates saved in the List Template Gallery, we need to download them and then upload them into the other site collections. So let’s download all templates to a local folder:
function global:download-allListTemplates($dir,$siteCollectionURL)
{
cd $dir
$site = get-SPSite $siteCollectionURL
$rootweb = $site.RootWeb
$LTG = $rootweb.Lists["List Template Gallery"]
$LTG.Items | foreach {
$_.Name
$bytes = $_.File.OpenBinary()
$bytes | set-content $_.Name -Encoding byte
}
$rootweb.Dispose()
$site.Dispose()
dir $dir
}
- Now we can upload templates to the list template gallery. The reason I do a .Replace(space, no-space) on the filename of the list stemplate is to remove any spaces from the filenames. Also I am assuming that $templateLocalDir only contains list templates (.stp in MOSS 2007)
function global:upload-listTemplatesTo($SiteColl,$templateLocalDir)
{
$rootweb = $siteColl.RootWeb
$LTGrootFolder = $rootweb.GetFolder("List Template Gallery")
Get-ChildItem $templateLocalDir | foreach {
$stream = [IO.File]::OpenRead($_.FullName)
if ($SiteColl.ServerRelativeUrl -eq "/"){
$desturl = "/_catalogs/lt/"+$_.Name.Replace(" ","")
}
else {
$desturl = $SiteColl.ServerRelativeUrl+"/_catalogs/lt/"+$_.Name.Replace(" ","")
}
Write-host Loading $_.Fullname to $desturl
$resultingfile = $LTGrootFolder.files.Add($desturl,$stream,$true)
$stream.close()
Write-Host $_.Name uploaded to $resultingfile.Url in $siteColl.Url
}
$rootweb.Dispose()
}
You can loop over the set of site collections in your web app and do this for all of them. To check your work, you can report on how many templates are in the List Template Gallery in each site collection.
function global:get-AllSiteCols($webAppName){
$WA = get-spwebApplication |where {$_.Name -eq $webAppName}
return $WA.Sites
}
function global:report-TemplateCounts($webAppName){
get-AllSiteCols $webAppName | foreach {
$rootweb = $_.RootWeb
$ltg = $rootWeb.Lists["List Template Gallery"]
write-host $rootweb.Url $ltg.ItemCount
$rootweb.Dispose()
}
}
Once the templates are in the list template gallery, then you can create lists from all of them at once like this:
function global:Create-AllCustomLists($web){
$site = $web.Site
write-host In $web.Url
$templates = $site.GetCustomListTemplates($web)
Create-FromTemplates $web $templates
$site.Dispose()
}
function global:Create-FromTemplates($web,$templates){
$templates |foreach {
write-host Instantiating $_.Name
if ($web.Lists[$listname] -eq $null) {
$guid = $web.Lists.Add($listname, $_.Description, $_)
$resultingList = $web.Lists.GetList($guid,$false)
$resultingList.OnQuickLaunch = $True
$resultingList.Update();
} else {
Write-Host $listname "already exists."
}
}
}
Now you can create preconfigured lists in a site very quickly. List templates won’t preserve the relationship to site columns though. Lists that were created from templates will have list level column definitions for the columns that were originally site columns, and site column updates won’t roll down to these lists.
Next time – more or less – I will cover setting up a welcome page based on a custom layout and adding web parts to pages, all via POSH.
--Michael
More of my posts about using PowerShell with SharePoint