SharePoint Saturday Louisville 2012


Over the weekend I spoke in front of a great crowd at the first annual SharePoint Saturday Louisville!

While I left Columbus with the intention of only doing my topic about building WCM sites using PowerShell, due to a cancellation I ended up doing two, back-to-back presentations. I’ll detail them below, and since this will be a long post, here are links to the different areas within the page:

  1. Build your SharePoint Internet presence with PowerShell
  2. Funnel your Info down a new Path

Build your SharePoint Internet presence with PowerShell

The topic: Build your SharePoint Internet presence with PowerShell
The story: Everybody knows PowerShell is powerful, it’s in the name! But did you know that PowerShell can read and understand XML? By leveraging XML among other things, complete builds can be automated – making them efficient and predictable.

In this fun, interactive and demo-filled session – I will show you how you can leverage PowerShell to help you build your branded, company website from the ground up using PowerShell and XML. I will also pass along some tips and tricks that will help you become a PowerShell Rockstar!

This was the first SharePoint Saturday in Louisville, and I was very proud to be a part of a great event.

My session went pretty flawlessly, as I lucked out and had zero issues with the presentation or the demos. For those of you who attended, thank you for being a part of it – and if you have any feedback or questions feel free to contact me either on Twitter or via e-mail (Ryan at SharePointRyan dot com).

I promised to upload my slides and demo PowerShell code, so the slides are on Slideshare (and displayed at the bottom of the post) and the XML and PowerShell code is below:

Demo Script – Setup-SPWebAppAndSite.ps1

XML Syntax:

<?xml version="1.0" encoding="utf-8"?>
<Sites>
	<WebAppConfig>
		<Name>Vandelay Industries</Name>
		<AppPool>SharePoint - VandelayDemo</AppPool>
		<AppPoolAccount>ISG1085\SpAppPool</AppPoolAccount>
		<DBServer>ISG1085\SharePoint</DBServer>
		<DBName>SP2010_Content_Vandelay_Demo</DBName>
		<HostHeader>www.vandelay.com</HostHeader>
		<InetpubPath>C:\inetpub\wwwroot\wss\VirtualDirectories</InetpubPath>
		<Port>80</Port>
		<Protocol>http://</Protocol>
		<OwnerAlias>ISG1085\SharePointRyan</OwnerAlias>
		<OwnerEmail>SharePointRyan@demowebsite.com</OwnerEmail>
		<SecondaryOwnerAlias>ISG1085\SPFarm</SecondaryOwnerAlias>
		<SecondaryOwnerEmail>SPFarm@demowebsite.com</SecondaryOwnerEmail>
		<RootSite>
			<WebTemplate>BLANKINTERNET#0</WebTemplate>
		</RootSite>
	</WebAppConfig>
	<!-- root site -->
	<Site Create="false">
		<SiteTitle>Home</SiteTitle>
		<SiteUrl>/</SiteUrl>
		<Page>
		   <PageTitle>Home</PageTitle>
		   <PageUrl>Home.aspx</PageUrl>
		   <PageContent></PageContent>
		   <PageLayout>Body Only</PageLayout>
	   </Page>	
		<Page>
		   <PageTitle>Terms of Use</PageTitle>
		   <PageUrl>Terms-of-Use.aspx</PageUrl>
		   <PageContent></PageContent>
		   <PageLayout>Body Only</PageLayout>
	   </Page>
		<Page>
		   <PageTitle>Privacy Policy</PageTitle>
		   <PageUrl>Privacy-Policy.aspx</PageUrl>
		   <PageContent></PageContent>
		   <PageLayout>Body Only</PageLayout>
	   </Page>
		<Page>
		   <PageTitle>Linking Policy</PageTitle>
		   <PageUrl>Linking-Policy.aspx</PageUrl>
		   <PageContent></PageContent>
		   <PageLayout>Body Only</PageLayout>
	   </Page>
		<Page>
		   <PageTitle>Legal Disclaimer</PageTitle>
		   <PageUrl>Legal-Disclaimer.aspx</PageUrl>
		   <PageContent></PageContent>
		   <PageLayout>Body Only</PageLayout>
	   </Page>	
		<Page>
		   <PageTitle>404 - Page Not Found</PageTitle>
		   <PageUrl>Page-Not-Found.aspx</PageUrl>
		   <PageContent></PageContent>
		   <PageLayout>Body Only</PageLayout>
	   </Page>			   		   
	</Site>		
	<!-- 2nd level sites -->
	<Site>
		<SiteTitle>Products</SiteTitle>
		<SiteUrl>/Products</SiteUrl>
		<Page>
		   <PageTitle>Awesome Widget</PageTitle>
		   <PageUrl>Awesome-Widget.aspx</PageUrl>
		   <PageContent></PageContent>
		   <PageLayout>Body Only</PageLayout>
		</Page>
		<Page>
		   <PageTitle>The Spectacular Thingamajig</PageTitle>
		   <PageUrl>The-Spectacular-Thingamajig.aspx</PageUrl>
		   <PageContent></PageContent>
		   <PageLayout>Body Only</PageLayout>
		</Page>
		<Page>
		   <PageTitle>Store</PageTitle>
		   <PageUrl>Store.aspx</PageUrl>
		   <PageContent></PageContent>
		   <PageLayout>Body Only</PageLayout>
		</Page>
	</Site>
	<Site>
		<SiteTitle>Solutions</SiteTitle>
		<SiteUrl>/Solutions</SiteUrl>
		<Page>
		   <PageTitle>Customer Engagement</PageTitle>
		   <PageUrl>Customer-Engagement.aspx</PageUrl>
		   <PageContent></PageContent>
		   <PageLayout>Body Only</PageLayout>
		</Page>
		<Page>
		   <PageTitle>Custom Solutions</PageTitle>
		   <PageUrl>Custom-Solutions.aspx</PageUrl>
		   <PageContent></PageContent>
		   <PageLayout>Body Only</PageLayout>
		</Page>
	</Site>
	<Site>
		<SiteTitle>Shipping and Returns</SiteTitle>
		<SiteUrl>/Shipping-and-Returns</SiteUrl>
		<Page>
		   <PageTitle>Shipping Policies</PageTitle>
		   <PageUrl>Shipping-Policies.aspx</PageUrl>
		   <PageContent></PageContent>
		   <PageLayout>Body Only</PageLayout>
		</Page>
		<Page>
		   <PageTitle>Return Policies</PageTitle>
		   <PageUrl>Return-Policies.aspx</PageUrl>
		   <PageContent></PageContent>
		   <PageLayout>Body Only</PageLayout>
		</Page>
	</Site>
	<Site>
		<SiteTitle>About Us</SiteTitle>
		<SiteUrl>/About-Us</SiteUrl>
		<Page>
		   <PageTitle>Company</PageTitle>
		   <PageUrl>Company.aspx</PageUrl>
		   <PageContent></PageContent>
		   <PageLayout>Body Only</PageLayout>
		</Page>
		<Page>
		   <PageTitle>History</PageTitle>
		   <PageUrl>History.aspx</PageUrl>
		   <PageContent></PageContent>
		   <PageLayout>Body Only</PageLayout>
		</Page>
		<Page>
		   <PageTitle>Locations</PageTitle>
		   <PageUrl>Locations.aspx</PageUrl>
		   <PageContent></PageContent>
		   <PageLayout>Blank Web Part page</PageLayout>
		</Page>
		<Page>
		   <PageTitle>Employment Opportunities</PageTitle>
		   <PageUrl>Employment-Opportunities.aspx</PageUrl>
		   <PageContent></PageContent>
		   <PageLayout>Body Only</PageLayout>
		</Page>
	</Site>
	<Site>
		<SiteTitle>Contact Us</SiteTitle>
		<SiteUrl>/Contact-Us</SiteUrl>
		<Page>
		   <PageTitle>Social Media</PageTitle>
		   <PageUrl>Social-Media.aspx</PageUrl>
		   <PageContent></PageContent>
		   <PageLayout>Body Only</PageLayout>
		</Page>
		<Page>
		   <PageTitle>Locations</PageTitle>
		   <PageUrl>Locations.aspx</PageUrl>
		   <PageContent></PageContent>
		   <PageLayout>Body Only</PageLayout>
		</Page>
		<Page>
		   <PageTitle>Service Requests</PageTitle>
		   <PageUrl>Service-Requests.aspx</PageUrl>
		   <PageContent></PageContent>
		   <PageLayout>Body Only</PageLayout>
		</Page>
		<Page>
		   <PageTitle>Request a Catalog</PageTitle>
		   <PageUrl>Request-a-Catalog.aspx</PageUrl>
		   <PageContent></PageContent>
		   <PageLayout>Body Only</PageLayout>
		</Page>
	</Site>
	<Site>
		<SiteTitle>What We Do</SiteTitle>
		<SiteUrl>/What-We-Do</SiteUrl>
		<Page>
		   <PageTitle>Engagement</PageTitle>
		   <PageUrl>Engagement.aspx</PageUrl>
		   <PageContent></PageContent>
		   <PageLayout>Body Only</PageLayout>
		</Page>
		<Page>
		   <PageTitle>Ambassadors</PageTitle>
		   <PageUrl>Ambassadors.aspx</PageUrl>
		   <PageContent></PageContent>
		   <PageLayout>Body Only</PageLayout>
		</Page>
	</Site>
	<Site>
		<SiteTitle>Our Company</SiteTitle>
		<SiteUrl>/Our-Company</SiteUrl>
		<Page>
		   <PageTitle>Forms</PageTitle>
		   <PageUrl>Forms.aspx</PageUrl>
		   <PageContent></PageContent>
		   <PageLayout>Body Only</PageLayout>
		</Page>
		<Page>
		   <PageTitle>Travel</PageTitle>
		   <PageUrl>Travel.aspx</PageUrl>
		   <PageContent></PageContent>
		   <PageLayout>Body Only</PageLayout>
		</Page>
	</Site>
	<Site>
		<SiteTitle>Our Customers</SiteTitle>
		<SiteUrl>/Our-Customers</SiteUrl>
	</Site>
	<Site>
		<SiteTitle>News</SiteTitle>
		<SiteUrl>/News</SiteUrl>
	</Site>
</Sites>

PowerShell code:

<#
.Synopsis
	This PowerShell Script will create a new Web Application and root Site 
	Collection.
.Description
	This advanced script uses New-SPWebApplication, New-SPSite and 
	Enable-SPFeature to configure a web application and site collection using
	the Publishing Portal Site Template. Once the SPSite is created, 
	Standard and Enterprise Site and Web Features are activated.
.Example
	C:\PS>.\Setup-SPWebAppAndSite.ps1 -XmlInput .\SiteGenerationXml.xml
	
	This example runs with the default parameter values to configure a Web App
	and Site Collection based on the contents of an XML file called 
	SiteGenerationXml.xml in the current file directory.
.Notes
	Name: Setup-SPWebAppAndSite.ps1
	Author: Ryan Dennis
	Last Edit: 6/27/2012
	Keywords: New-SPWebApplication, New-SPSite
.Link
	http://www.sharepointryan.com
 	http://twitter.com/SharePointRyan
#Requires -Version 2.0
#>
[CmdletBinding()]
Param(
[Parameter(Mandatory=$true)][string]$XmlInput,
[Parameter(Mandatory=$true)][string]$BlobCacheLocation
)
# Store start time in variable for calculation later #
$StartTime = Get-Date

# Clear Host for a clean, empty shell #
Clear-Host

# Read in list of sites from XML file and create variables for use later #
[xml]$SitesXml = Get-Content $($XmlInput)
if ($SitesXml -eq $null) { return }
$Name = $SitesXml.Sites.WebAppConfig.Name
$ApplicationPool = $SitesXml.Sites.WebAppConfig.AppPool
$ApplicationPoolAccount = $SitesXml.Sites.WebAppConfig.AppPoolAccount
$DatabaseServer = $SitesXml.Sites.WebAppConfig.DBServer
$DatabaseName = $SitesXml.Sites.WebAppConfig.DBName
$InetpubPath = $SitesXml.Sites.WebAppConfig.InetpubPath
$HostHeader = $SitesXml.Sites.WebAppConfig.HostHeader
$Port = $SitesXml.Sites.WebAppConfig.Port
$WebsitePath=$InetpubPath+"\"+$HostHeader+$Port
$Protocol = $SitesXml.Sites.WebAppConfig.Protocol
$Url = $Protocol+$HostHeader+":"+$Port
$OwnerAlias = $SitesXml.Sites.WebAppConfig.OwnerAlias
$OwnerEmail = $SitesXml.Sites.WebAppConfig.OwnerEmail
$SecondaryOwnerAlias = $SitesXml.Sites.WebAppConfig.SecondaryOwnerAlias
$SecondaryOwnerEmail = $SitesXml.Sites.WebAppConfig.SecondaryOwnerEmail
$WebTemplate = $SitesXml.Sites.WebAppConfig.RootSite.WebTemplate

# Start SP Assignment for object disposal later #
Start-SPAssignment -Global

# Change Shell Title #
$title = $Host.UI.RawUI.WindowTitle
$Host.UI.RawUI.WindowTitle = "Provisioning Employee Portal Web Application..."

# If SharePoint Snapin isn't loaded - load it #
if ((Get-PSSnapin Microsoft.SharePoint.PowerShell)-eq $null)
{
	Write-Host "Adding SharePoint Snapin"
	Add-PSSnapin Microsoft.SharePoint.PowerShell
}
$ErrorPref = $ErrorActionPreference
$ErrorActionPreference = "SilentlyContinue"
$WarningPref = $WarningPreference
$WarningPreference = "SilentlyContinue"

# Tell us the Web App is getting created #
Write-Host "------------------------------------------------------------------"
Write-Host " Step 1 of 10: Creating Web Application at Url $($Url)..."
Write-Host "------------------------------------------------------------------"

# Create the Web App #
New-SPWebApplication -Name $Name -ApplicationPool $ApplicationPool `
-ApplicationPoolAccount $ApplicationPoolAccount -DatabaseName $DatabaseName `
-DatabaseServer $DatabaseServer -HostHeader $HostHeader -Port $Port `
-Path $WebsitePath -Url $HostHeader | Out-Null

# Add the BUILTIN\Administrators group to Full Control Policy #
$userOrGroup = "BUILTIN\Administrators" 
$displayName = "Administrators" 

$WebApp = Get-SPWebApplication $Name 
$policy = $webApp.Policies.Add($userOrGroup, $displayName) 
$policyRole = $webApp.PolicyRoles.GetSpecialRole([Microsoft.SharePoint.Administration.SPPolicyRoleType]::FullControl) 
$policy.PolicyRoleBindings.Add($policyRole) 
$webApp.Update() 

# Change Shell Title #
$Host.UI.RawUI.WindowTitle = "Provisioning Root Site Collection..."

# Tell us the Site Collection is getting created #
Write-Host "------------------------------------------------------------------"
Write-Host " Step 2 of 10: Creating Root Site Collection..."
Write-Host "------------------------------------------------------------------"

# Create the Root Site #
$SPSite = New-SPSite -Name $Name -OwnerAlias $OwnerAlias -OwnerEmail $OwnerEmail `
-SecondaryOwnerAlias $SecondaryOwnerAlias -SecondaryEmail $SecondaryOwnerEmail `
-Template $WebTemplate -Url $Url | Out-Null

# Tell us the Site Collection is getting created #
Write-Host "------------------------------------------------------------------"
Write-Host " Step 3 of 10: Configuring Cache Settings..."
Write-Host "------------------------------------------------------------------"
Write-Host "Configuring BLOB Caching..."
# Enable SP Blob Cache #
$WebApp = Get-SPWebApplication $Url 
# SPWebConfigModification to enable BlobCache 
$configMod1 = New-Object Microsoft.SharePoint.Administration.SPWebConfigModification 
$configMod1.Path = "configuration/SharePoint/BlobCache" 
$configMod1.Name = "enabled" 
$configMod1.Sequence = 0 
$configMod1.Owner = "BlobCacheMod" 
## SPWebConfigModificationType.EnsureChildNode -> 0 
## SPWebConfigModificationType.EnsureAttribute -> 1 
## SPWebConfigModificationType.EnsureSection -> 2 
$configMod1.Type = 1 
$configMod1.Value = "true"
	
######################################################################

# SPWebConfigModification to enable client-side Blob caching (max-age) 
$configMod2 = New-Object Microsoft.SharePoint.Administration.SPWebConfigModification 
$configMod2.Path = "configuration/SharePoint/BlobCache" 
$configMod2.Name = "max-age" 
$configMod2.Sequence = 0 
$configMod2.Owner = "BlobCacheMod" 
## SPWebConfigModificationType.EnsureChildNode -> 0 
## SPWebConfigModificationType.EnsureAttribute -> 1 
## SPWebConfigModificationType.EnsureSection -> 2 
$configMod2.Type = 1 
$configMod2.Value = "86400" 

######################################################################

# SPWebConfigModification to change the default location for the Blob Cache files
$configMod3 = New-Object Microsoft.SharePoint.Administration.SPWebConfigModification
$configMod3.Path = "configuration/SharePoint/BlobCache"
$configMod3.Name = "location"
$configMod3.Sequence = "0"
$configMod3.Owner = "BlobCacheMod"
## SPWebConfigModificationType.EnsureChildNode -> 0 
## SPWebConfigModificationType.EnsureAttribute -> 1 
## SPWebConfigModificationType.EnsureSection -> 2 
$configMod3.Type = 1
$configMod3.Value = $BlobCacheLocation
# Add mods, update, and apply 
$WebApp.WebConfigModifications.Add( $configMod1 ) 
$WebApp.WebConfigModifications.Add( $configMod2 )
$WebApp.WebConfigModifications.Add( $configMod3 )
$WebApp.Update() 
$WebApp.Parent.ApplyWebConfigModifications() 

# Sleep for 5 seconds # 
Start-Sleep -Seconds 5

# Enable Output Cache for Root Site Collection # 
Write-Host "Configuring Output Caching..."
$SPSite = Get-SPSite $Url
$cache = New-Object Microsoft.SharePoint.Publishing.SiteCacheSettingsWriter $SPSite
$cache.EnableCache = $true
$cache.AllowPublishingWebPageOverrides = $true
$cache.EnableDebuggingOutput = $true
$cache.SetAnonymousPageCacheProfileId($SPSite, 1)
$cache.SetAuthenticatedPageCacheProfileId($SPSite, 4)
$cache.SetFarmCacheFlushFlag()
$cache.Update()
$SPSite.Dispose()

# Change Shell Title #
$Host.UI.RawUI.WindowTitle = "Activating Features..."

# Activate Standard and Enterprise Features #
Write-Host "------------------------------------------------------------------"
Write-Host " Step 4 of 10: Activating Features..."
Write-Host "------------------------------------------------------------------"
# Standard #
Write-Host "Enabling Standard Site and Web Features..."
Enable-SPFeature BaseSite -Url $Url
Enable-SPFeature BaseWeb -Url $Url
# Enterprise #
Write-Host "Enabling Enterprise Site and Web Features..."
Enable-SPFeature PremiumSite -Url $Url
Enable-SPFeature PremiumWeb -Url $Url
# Team Collaboration Lists #
Enable-SPFeature TeamCollab -Url $Url
# Mavention Meta Fields #
Write-Host "Enabling Mavention Meta Fields Feature..."
Install-SPSolution Mavention.SharePoint.MetaFields.wsp -WebApplication $Url -GACDeployment
Start-Sleep -Seconds 5
Enable-SPFeature -Identity a6ad433b-0bdf-40aa-aec8-6a091d7a3c26 -Url $Url

# Change Shell Title #
$Host.UI.RawUI.WindowTitle = "Configuring Search Center and Settings..."

# Remove OOTB Search Center Lite Web #
Write-Host "------------------------------------------------------------------"
Write-Host " Step 5 of 10: Removing Search Center Subsite..."
Write-Host "------------------------------------------------------------------"
Remove-SPWeb -Identity $Url"/search" -Confirm:$false -ErrorAction SilentlyContinue

# Create Enterprise Search Center Site Collection #
Write-Host "------------------------------------------------------------------"
Write-Host " Step 6 of 10: Creating Enterprise Search Center Site Collection..."
Write-Host "------------------------------------------------------------------"
$searchUrl = $Url+"/search"
New-SPManagedPath -Explicit -RelativeURL search -WebApplication $Url | Out-Null
New-SPSite -Name "Search Center" -OwnerAlias $OwnerAlias `
-OwnerEmail $OwnerEmail -SecondaryOwnerAlias $SecondaryOwnerAlias `
-SecondaryEmail $SecondaryOwnerEmail -Template "SRCHCEN#0" `
-Url $searchUrl | Out-Null
# Apply MaxSiteCount to content DB #
Set-SPContentDatabase -Identity $DatabaseName -MaxSiteCount 2 `
-WarningSiteCount 1 | Out-Null
Set-SPUser -Identity "NT Authority\Authenticated Users" -Web $searchUrl `
-Group "Search Center Visitors"

# Set Site Collection Search Center Settings #
Write-Host "------------------------------------------------------------------"
Write-Host " Step 7 of 10: Configuring Search Scope Settings..."
Write-Host "------------------------------------------------------------------"
<# These are the possible values for Dropdown
Do Not Show Scopes Dropdown, and default to contextual scope	HideScopeDD_DefaultContextual
Do Not Show Scopes Dropdown, and default to target results page	HideScopeDD
Show scopes Dropdown	ShowDD
Show, and default to ‘s’ URL parameter	ShowDD_DefaultURL
Show and default to contextual scope	ShowDD_DefaultContextual
Show, do not include contextual scopes	ShowDD_NoContextual
Show, do not include contextual scopes, and default to ‘s’ URL parameter	ShowDD_NoContextual_DefaultURL
#>

$SPWeb = Get-SPWeb $Url
$SPWeb.AllProperties["SRCH_ENH_FTR_URL"] = "/search/pages"
$SPWeb.AllProperties["SRCH_SITE_DROPDOWN_MODE"] = "ShowDD"
$SPWeb.AllProperties["SRCH_TRAGET_RESULTS_PAGE"] = "/search/pages/results.aspx"
$SPWeb.Update()
# Search Site #
$searchWeb = Get-SPWeb $searchUrl
$searchWeb.AllProperties["SRCH_ENH_FTR_URL"] = "/search/pages"
$searchWeb.AllProperties["SRCH_SITE_DROPDOWN_MODE"] = "ShowDD"
$searchWeb.AllProperties["SRCH_TRAGET_RESULTS_PAGE"] = "/search/pages/results.aspx"
$searchWeb.Update()

# Create Meta Fields #
Write-Host "------------------------------------------------------------------"
Write-Host " Step 8 of 10: Creating SEO Meta Fields..."
Write-Host "------------------------------------------------------------------"
#Assign fieldXML variable with XML string for site column
# Author
$AuthorFieldXML = '<Field Type="Text"
Name="MetaAuthor"
Description="Author Meta Tag"
DisplayName="Author"
StaticName="MetaAuthor"
Group="Publishing Meta Tags"
Hidden="FALSE"
Required="FALSE"
Sealed="FALSE"
ShowInDisplayForm="TRUE"
ShowInEditForm="TRUE"
ShowInListSettings="TRUE"
ShowInNewForm="TRUE"></Field>'
# Copyright
$CopyrightFieldXML = '<Field Type="Text"
Name="MetaCopyright"
Description="Copyright Meta Tag"
DisplayName="Copyright"
StaticName="MetaCopyright"
Group="Publishing Meta Tags"
Hidden="FALSE"
Required="FALSE"
Sealed="FALSE"
ShowInDisplayForm="TRUE"
ShowInEditForm="TRUE"
ShowInListSettings="TRUE"
ShowInNewForm="TRUE"></Field>'
# Description
$DescriptionFieldXML = '<Field Type="Text"
Name="MetaDescription"
Description="Description Meta Tag"
DisplayName="Description"
StaticName="MetaDescription"
Group="Publishing Meta Tags"
Hidden="FALSE"
Required="FALSE"
Sealed="FALSE"
ShowInDisplayForm="TRUE"
ShowInEditForm="TRUE"
ShowInListSettings="TRUE"
ShowInNewForm="TRUE"></Field>'
# Expiration
$ExpirationFieldXML = '<Field Type="Text"
Name="MetaExpiration"
Description="Expiration Meta Tag"
DisplayName="Expiration"
StaticName="MetaExpiration"
Group="Publishing Meta Tags"
Hidden="FALSE"
Required="FALSE"
Sealed="FALSE"
ShowInDisplayForm="TRUE"
ShowInEditForm="TRUE"
ShowInListSettings="TRUE"
ShowInNewForm="TRUE"></Field>'
# Keywords
$KeywordsFieldXML = '<Field Type="Text"
Name="MetaKeywords"
Description="Keywords Meta Tag"
DisplayName="Keywords"
StaticName="MetaKeywords"
Group="Publishing Meta Tags"
Hidden="FALSE"
Required="FALSE"
Sealed="FALSE"
ShowInDisplayForm="TRUE"
ShowInEditForm="TRUE"
ShowInListSettings="TRUE"
ShowInNewForm="TRUE"></Field>'
# Refresh
$RefreshFieldXML = '<Field Type="Text"
Name="MetaRefresh"
Description="Refresh Meta Tag"
DisplayName="Refresh"
StaticName="MetaRefresh"
Group="Publishing Meta Tags"
Hidden="FALSE"
Required="FALSE"
Sealed="FALSE"
ShowInDisplayForm="TRUE"
ShowInEditForm="TRUE"
ShowInListSettings="TRUE"
ShowInNewForm="TRUE"></Field>'
# Robots
$RobotsFieldXML = '<Field Type="Text"
Name="MetaRobots"
Description="Robots Meta Tag"
DisplayName="Robots"
StaticName="MetaRobots"
Group="Publishing Meta Tags"
Hidden="FALSE"
Required="FALSE"
Sealed="FALSE"
ShowInDisplayForm="TRUE"
ShowInEditForm="TRUE"
ShowInListSettings="TRUE"
ShowInNewForm="TRUE"></Field>'
# Title
$TitleFieldXML = '<Field Type="Text"
Name="MetaTitle"
Description="Title Meta Tag"
DisplayName="Title"
StaticName="MetaTitle"
Group="Publishing Meta Tags"
Hidden="FALSE"
Required="FALSE"
Sealed="FALSE"
ShowInDisplayForm="TRUE"
ShowInEditForm="TRUE"
ShowInListSettings="TRUE"
ShowInNewForm="TRUE"></Field>'

	$SPWeb = Get-SPWeb $Url
	$SPWeb.Fields.AddFieldAsXml($AuthorFieldXML)
	$SPWeb.Fields.AddFieldAsXml($CopyrightFieldXML)
	$SPWeb.Fields.AddFieldAsXml($DescriptionFieldXML)
	$SPWeb.Fields.AddFieldAsXml($ExpirationFieldXML)
	$SPWeb.Fields.AddFieldAsXml($KeywordsFieldXML)
	$SPWeb.Fields.AddFieldAsXml($RefreshFieldXML)
	$SPWeb.Fields.AddFieldAsXml($RobotsFieldXML)
	$SPWeb.Fields.AddFieldAsXml($TitleFieldXML)
	# Grab columns for manipulation
	$Author = $SPWeb.Fields["MetaAuthor"]
	$Copyright = $SPWeb.Fields["MetaCopyright"]
	$Description = $SPWeb.Fields["MetaDescription"]
	$Expiration = $SPWeb.Fields["MetaExpiration"]
	$Keywords = $SPWeb.Fields["MetaKeywords"]
	$Refresh = $SPWeb.Fields["MetaRefresh"]
	$Robots = $SPWeb.Fields["MetaRobots"]
	$Title = $SPWeb.Fields["MetaTitle"]
	# Rename Display Name
	$Author.Title = "Author"
	$Copyright.Title = "Copyright"
	$Description.Title = "Description"
	$Expiration.Title = "Expiration"
	$Keywords.Title = "Keywords"
	$Refresh.Title = "Refresh"
	$Robots.Title = "Robots"
	$Title.Title = "Title"
	# Update All
	$Author.Update()
	$Copyright.Update()
	$Description.Update()
	$Expiration.Update()
	$Keywords.Update()
	$Refresh.Update()
	$Robots.Update()
	$Title.Update()
	$SPWeb.Dispose()

# Add the columns to the Welcome Page content type #
$Web = Get-SPWeb $Url
$Ctype = $Web.ContentTypes["Welcome Page"]
$fields = $web.Fields | Where-Object {$_.group -eq "Publishing Meta Tags"}
$fields | ForEach-Object {
$Ctype.FieldLinks.Add($_)
$Ctype.Update($true)
$Web.Update()
}
$Web.Dispose()

# Change Shell Title #
$Host.UI.RawUI.WindowTitle = "Creating Subsites from XML..."

# Create subwebs from XML input #
Write-Host "------------------------------------------------------------------"
Write-Host " Step 9 of 10: Creating subsites from XML file..."
Write-Host "------------------------------------------------------------------"

Start-SPAssignment -Global

# Loop through each site node to extract data #
$SitesXml.Sites.Site | ForEach-Object {
	Write-Host "---------------------------------------------------------------"
	Write-Host " Step 9 of 10: Creating an SPWeb at $($SiteUrl)"
	Write-Host "---------------------------------------------------------------"
	$SiteTitle = [string]$_.SiteTitle
	$SiteUrl = [string]$_.SiteUrl
	$SiteOwner = [string]$_.Owner
	$SiteUser = [String]$_.User
	$WebTemplate = "CMSPUBLISHING#0"
	$LangId = "1033"
	$SiteUrl = $Url+$SiteUrl
	# Create the SPWeb #
	if ($_.create -ne "false")
	{
	$Web = New-SPWeb -Url $SiteUrl -Language $LangId -Template $WebTemplate `
	-Name $SiteTitle
	}
	# Get publishing site and web objects
	$site = New-Object Microsoft.SharePoint.SPSite($SiteUrl)
	$psite = New-Object Microsoft.SharePoint.Publishing.PublishingSite($site)
	$web = $site.OpenWeb()
	$pWeb = [Microsoft.SharePoint.Publishing.PublishingWeb]::GetPublishingWeb($web)

	# Create all Pages using ForEach-Object #
	if ($_.Page -ne $null){
	$pages = $_.Page | ForEach-Object {
	
	# Create page content variables from XML file
	$PageTitle = [string]$_.PageTitle
	$PageUrl = [string]$_.PageUrl
	$PageLayout = [string]$_.PageLayout
	#$PageContent = [xml]$_.PageContent
	$PageImage = [string]$_.PageImage
	$layout = $pWeb.GetAvailablePageLayouts() | Where-Object {$_.Title -match $PageLayout}
	
    # Create blank page using Add method
	Write-Host "Creating $($PageTitle).aspx page"
    $pages = $pWeb.GetPublishingPages($pWeb)
	$page = $pages.Add($PageUrl, $layout)
	$page.Update()
	
    # Update the filename to the one specified in the XML, add HTML content to Page Content zone
    $item = $page.ListItem
	$item["Title"] = $PageTitle;
	$item["Page Content"] = $PageContent;
	
	# Experimenting with adding a CEWP #
#	$page.CheckOut() 
#	$webpartmanager = $web.GetLimitedWebPartManager($page.Url,
#	[System.Web.UI.WebControls.WebParts.PersonalizationScope]::Shared) 
#	$webpart = New-Object  Microsoft.SharePoint.WebPartPages.ContentEditorWebPart
#	$webpart.ChromeType = [System.Web.UI.WebControls.WebParts.PartChromeType]::None;
#	$webpart.Title = "Added By PowerShell" 
#	$webpart.Content = $PageContent
#	$webpartmanager.AddWebPart($webpart, "Header", 0); 
	$item.Update()
	
    # Check-in and publish page
    $item.File.CheckIn("")
    $item.File.Publish("")
	$file = $item.File
	$pWeb.Update()
	
	} #end Page Foreach
	
	} # End if block #
	
} # End ForEach-Object loop #

# Upload Footer List and create list #
Write-Host "------------------------------------------------------------------"
Write-Host " Step 10 of 10: Creating Footer List and applying branding..."
Write-Host "------------------------------------------------------------------"
$site = Get-SPSite $Url
$Web = $site.OpenWeb()
$spFolder = $web.GetFolder("List Template Gallery")
$spFileCollection = $spFolder.Files
$file = Get-Item C:\Solutions\ConsumersEnergy\CEEP-FooterDirectoryList-LT.stp
$spFileCollection.Add("_catalogs/lt/CEEP-FooterDirectoryList-LT.stp", $file.OpenRead(), $true) | Out-Null
$listTemplates = $site.GetCustomListTemplates($web)
$Web.Lists.Add("CEEP-FooterDirectoryList","",$listTemplates["CEEP-FooterDirectoryList-LT"]) | Out-Null
$Web.Dispose()
$site.Dispose()
Enable-SPFeature -Identity "8d36bad6-e39a-41be-aff4-1a4be71ddcb6" -Url $Url | Out-Null




$EndTime = Get-Date
$TimeSpan = New-TimeSpan $StartTime $EndTime
$Mins = $TimeSpan.Minutes
$Secs = $TimeSpan.Seconds
$Time = $EndTime.ToShortTimeString()
# Tell us it's done #
Write-Host "------------------------------------------------------------------"
Write-Host " Portal Configuration Complete at $($Time)."
Write-Host " Process took $($Mins) minutes and $($Secs) seconds to complete."
Write-Host "------------------------------------------------------------------"

# Set the Window Title back to default #
$Host.UI.RawUI.WindowTitle = $title

# Hit the site to warm it up #
function get-webpage([string]$url,[System.Net.NetworkCredential]$cred=$null)
{
   $wc = new-object net.webclient
   if($cred -eq $null)
   {
     $cred = [System.Net.CredentialCache]::DefaultCredentials;
   }
   $wc.credentials = $cred;
   return $wc.DownloadString($url);
}

Write-Host "------------------------------------------------------------------"
Write-Host " Warming up the new Sites"
Write-Host "------------------------------------------------------------------" 
$cred = [System.Net.CredentialCache]::DefaultCredentials;
$sites = Get-SPSite -WebApplication $WebApp -Limit ALL
foreach ($site in $sites) {
$siteurl = $site.url
$spsite = New-Object Microsoft.SharePoint.SPSite($siteurl)
$pubsite = New-Object Microsoft.SharePoint.Publishing.PublishingSite($spsite)
foreach ($web in $site.AllWebs) {
$pubweb = [Microsoft.SharePoint.Publishing.PublishingWeb]::GetPublishingWeb($web)
$pages = $pubweb.GetPublishingPages($pubweb)
	foreach ($page in $pages) {
	$html = Get-WebPage -Url $page.uri -cred $cred;
	#Write-Host $page.uri
	}
}
}

# Dispose all objects #
Stop-SPAssignment -Global

# Set Error and Warning Preferences back #
$ErrorActionPreference = $ErrorPref
$WarningPreference = $WarningPref

# Open the site in IE #
$ie = New-Object -ComObject InternetExplorer.Application
$ie.Navigate($Url)
$ie.Visible = $true;

Funnel your Info down a new Path

The topic:  Funnel your Info down a new Path
The story:InfoPath provides business users with a familiar, feature rich means of creating dynamic, powerful electronic forms. While it has been around since the 2003 release of Microsoft Office, InfoPath 2010 combined with SharePoint 2010, is a match made in heaven.

InfoPath is heavily integrated into SharePoint 2010, and users can now create engaging forms within minutes and without writing a single line of code. This presentation will show you how you can start leveraging InfoPath to funnel your business information down a new path. Demos, gotchas, tips & tricks will all be a part of this 10,000 foot view of Microsoft InfoPath as it relates to SharePoint 2010.

SPS Louisville Slides

View more presentations from Ryan Dennis.
Advertisements

SharePoint Saturday Dayton 2012


This past weekend I spoke in front of a good sized crowd at the first annual SharePoint Saturday Dayton!

The topic: Build your SharePoint Internet presence with PowerShell
The story: Everybody knows PowerShell is powerful, it’s in the name! But did you know that PowerShell can read and understand XML? By leveraging XML among other things, complete builds can be automated – making them efficient and predictable.

In this fun, interactive and demo-filled session – I will show you how you can leverage PowerShell to help you build your branded, company website from the ground up using PowerShell and XML. I will also pass along some tips and tricks that will help you become a PowerShell Rockstar!

This was the first SharePoint Saturday in Dayton, and I was very proud to be a part of a great event.

My session went pretty flawlessly, as I lucked out and had zero issues with the presentation or the demos. For those of you who attended, thank you for being a part of it – and if you have any feedback or questions feel free to contact me either on Twitter or via e-mail (Ryan at SharePointRyan dot com).

I promised to upload my slides and demo PowerShell code, so the slides are on Slideshare (and displayed at the bottom of the post) and the XML and PowerShell code is below:

Demo Script – Setup-SPWebAppAndSite.ps1

XML Syntax:

<?xml version="1.0" encoding="utf-8"?>
<Sites>
	<WebAppConfig>
		<Name>Vandelay Industries</Name>
		<AppPool>SharePoint - VandelayDemo</AppPool>
		<AppPoolAccount>ISG1085\SpAppPool</AppPoolAccount>
		<DBServer>ISG1085\SharePoint</DBServer>
		<DBName>SP2010_Content_Vandelay_Demo</DBName>
		<HostHeader>www.vandelay.com</HostHeader>
		<InetpubPath>C:\inetpub\wwwroot\wss\VirtualDirectories</InetpubPath>
		<Port>80</Port>
		<Protocol>http://</Protocol>
		<OwnerAlias>ISG1085\SharePointRyan</OwnerAlias>
		<OwnerEmail>SharePointRyan@demowebsite.com</OwnerEmail>
		<SecondaryOwnerAlias>ISG1085\SPFarm</SecondaryOwnerAlias>
		<SecondaryOwnerEmail>SPFarm@demowebsite.com</SecondaryOwnerEmail>
		<RootSite>
			<WebTemplate>BLANKINTERNET#0</WebTemplate>
		</RootSite>
	</WebAppConfig>
	<!-- root site -->
	<Site Create="false">
		<SiteTitle>Home</SiteTitle>
		<SiteUrl>/</SiteUrl>
		<Page>
		   <PageTitle>Home</PageTitle>
		   <PageUrl>Home.aspx</PageUrl>
		   <PageContent></PageContent>
		   <PageLayout>Body Only</PageLayout>
	   </Page>	
		<Page>
		   <PageTitle>Terms of Use</PageTitle>
		   <PageUrl>Terms-of-Use.aspx</PageUrl>
		   <PageContent></PageContent>
		   <PageLayout>Body Only</PageLayout>
	   </Page>
		<Page>
		   <PageTitle>Privacy Policy</PageTitle>
		   <PageUrl>Privacy-Policy.aspx</PageUrl>
		   <PageContent></PageContent>
		   <PageLayout>Body Only</PageLayout>
	   </Page>
		<Page>
		   <PageTitle>Linking Policy</PageTitle>
		   <PageUrl>Linking-Policy.aspx</PageUrl>
		   <PageContent></PageContent>
		   <PageLayout>Body Only</PageLayout>
	   </Page>
		<Page>
		   <PageTitle>Legal Disclaimer</PageTitle>
		   <PageUrl>Legal-Disclaimer.aspx</PageUrl>
		   <PageContent></PageContent>
		   <PageLayout>Body Only</PageLayout>
	   </Page>	
		<Page>
		   <PageTitle>404 - Page Not Found</PageTitle>
		   <PageUrl>Page-Not-Found.aspx</PageUrl>
		   <PageContent></PageContent>
		   <PageLayout>Body Only</PageLayout>
	   </Page>			   		   
	</Site>		
	<!-- 2nd level sites -->
	<Site>
		<SiteTitle>Products</SiteTitle>
		<SiteUrl>/Products</SiteUrl>
		<Page>
		   <PageTitle>Awesome Widget</PageTitle>
		   <PageUrl>Awesome-Widget.aspx</PageUrl>
		   <PageContent></PageContent>
		   <PageLayout>Body Only</PageLayout>
		</Page>
		<Page>
		   <PageTitle>The Spectacular Thingamajig</PageTitle>
		   <PageUrl>The-Spectacular-Thingamajig.aspx</PageUrl>
		   <PageContent></PageContent>
		   <PageLayout>Body Only</PageLayout>
		</Page>
		<Page>
		   <PageTitle>Store</PageTitle>
		   <PageUrl>Store.aspx</PageUrl>
		   <PageContent></PageContent>
		   <PageLayout>Body Only</PageLayout>
		</Page>
	</Site>
	<Site>
		<SiteTitle>Solutions</SiteTitle>
		<SiteUrl>/Solutions</SiteUrl>
		<Page>
		   <PageTitle>Customer Engagement</PageTitle>
		   <PageUrl>Customer-Engagement.aspx</PageUrl>
		   <PageContent></PageContent>
		   <PageLayout>Body Only</PageLayout>
		</Page>
		<Page>
		   <PageTitle>Custom Solutions</PageTitle>
		   <PageUrl>Custom-Solutions.aspx</PageUrl>
		   <PageContent></PageContent>
		   <PageLayout>Body Only</PageLayout>
		</Page>
	</Site>
	<Site>
		<SiteTitle>Shipping and Returns</SiteTitle>
		<SiteUrl>/Shipping-and-Returns</SiteUrl>
		<Page>
		   <PageTitle>Shipping Policies</PageTitle>
		   <PageUrl>Shipping-Policies.aspx</PageUrl>
		   <PageContent></PageContent>
		   <PageLayout>Body Only</PageLayout>
		</Page>
		<Page>
		   <PageTitle>Return Policies</PageTitle>
		   <PageUrl>Return-Policies.aspx</PageUrl>
		   <PageContent></PageContent>
		   <PageLayout>Body Only</PageLayout>
		</Page>
	</Site>
	<Site>
		<SiteTitle>About Us</SiteTitle>
		<SiteUrl>/About-Us</SiteUrl>
		<Page>
		   <PageTitle>Company</PageTitle>
		   <PageUrl>Company.aspx</PageUrl>
		   <PageContent></PageContent>
		   <PageLayout>Body Only</PageLayout>
		</Page>
		<Page>
		   <PageTitle>History</PageTitle>
		   <PageUrl>History.aspx</PageUrl>
		   <PageContent></PageContent>
		   <PageLayout>Body Only</PageLayout>
		</Page>
		<Page>
		   <PageTitle>Locations</PageTitle>
		   <PageUrl>Locations.aspx</PageUrl>
		   <PageContent></PageContent>
		   <PageLayout>Blank Web Part page</PageLayout>
		</Page>
		<Page>
		   <PageTitle>Employment Opportunities</PageTitle>
		   <PageUrl>Employment-Opportunities.aspx</PageUrl>
		   <PageContent></PageContent>
		   <PageLayout>Body Only</PageLayout>
		</Page>
	</Site>
	<Site>
		<SiteTitle>Contact Us</SiteTitle>
		<SiteUrl>/Contact-Us</SiteUrl>
		<Page>
		   <PageTitle>Social Media</PageTitle>
		   <PageUrl>Social-Media.aspx</PageUrl>
		   <PageContent></PageContent>
		   <PageLayout>Body Only</PageLayout>
		</Page>
		<Page>
		   <PageTitle>Locations</PageTitle>
		   <PageUrl>Locations.aspx</PageUrl>
		   <PageContent></PageContent>
		   <PageLayout>Body Only</PageLayout>
		</Page>
		<Page>
		   <PageTitle>Service Requests</PageTitle>
		   <PageUrl>Service-Requests.aspx</PageUrl>
		   <PageContent></PageContent>
		   <PageLayout>Body Only</PageLayout>
		</Page>
		<Page>
		   <PageTitle>Request a Catalog</PageTitle>
		   <PageUrl>Request-a-Catalog.aspx</PageUrl>
		   <PageContent></PageContent>
		   <PageLayout>Body Only</PageLayout>
		</Page>
	</Site>
	<Site>
		<SiteTitle>What We Do</SiteTitle>
		<SiteUrl>/What-We-Do</SiteUrl>
		<Page>
		   <PageTitle>Engagement</PageTitle>
		   <PageUrl>Engagement.aspx</PageUrl>
		   <PageContent></PageContent>
		   <PageLayout>Body Only</PageLayout>
		</Page>
		<Page>
		   <PageTitle>Ambassadors</PageTitle>
		   <PageUrl>Ambassadors.aspx</PageUrl>
		   <PageContent></PageContent>
		   <PageLayout>Body Only</PageLayout>
		</Page>
	</Site>
	<Site>
		<SiteTitle>Our Company</SiteTitle>
		<SiteUrl>/Our-Company</SiteUrl>
		<Page>
		   <PageTitle>Forms</PageTitle>
		   <PageUrl>Forms.aspx</PageUrl>
		   <PageContent></PageContent>
		   <PageLayout>Body Only</PageLayout>
		</Page>
		<Page>
		   <PageTitle>Travel</PageTitle>
		   <PageUrl>Travel.aspx</PageUrl>
		   <PageContent></PageContent>
		   <PageLayout>Body Only</PageLayout>
		</Page>
	</Site>
	<Site>
		<SiteTitle>Our Customers</SiteTitle>
		<SiteUrl>/Our-Customers</SiteUrl>
	</Site>
	<Site>
		<SiteTitle>News</SiteTitle>
		<SiteUrl>/News</SiteUrl>
	</Site>
</Sites>

PowerShell code:

<#
.Synopsis
	This PowerShell Script will create a new Web Application and root Site 
	Collection.
.Description
	This advanced script uses New-SPWebApplication, New-SPSite and 
	Enable-SPFeature to configure a web application and site collection using
	the Publishing Portal Site Template. Once the SPSite is created, 
	Standard and Enterprise Site and Web Features are activated.
.Example
	C:\PS>.\Setup-SPWebAppAndSite.ps1 -XmlInput .\SiteGenerationXml.xml
	
	This example runs with the default parameter values to configure a Web App
	and Site Collection based on the contents of an XML file called 
	SiteGenerationXml.xml in the current file directory.
.Notes
	Name: Setup-SPWebAppAndSite.ps1
	Author: Ryan Dennis
	Last Edit: 6/27/2012
	Keywords: New-SPWebApplication, New-SPSite
.Link
	http://www.sharepointryan.com
 	http://twitter.com/SharePointRyan
#Requires -Version 2.0
#>
[CmdletBinding()]
Param(
[Parameter(Mandatory=$true)][string]$XmlInput,
[Parameter(Mandatory=$true)][string]$BlobCacheLocation
)
# Store start time in variable for calculation later #
$StartTime = Get-Date

# Clear Host for a clean, empty shell #
Clear-Host

# Read in list of sites from XML file and create variables for use later #
[xml]$SitesXml = Get-Content $($XmlInput)
if ($SitesXml -eq $null) { return }
$Name = $SitesXml.Sites.WebAppConfig.Name
$ApplicationPool = $SitesXml.Sites.WebAppConfig.AppPool
$ApplicationPoolAccount = $SitesXml.Sites.WebAppConfig.AppPoolAccount
$DatabaseServer = $SitesXml.Sites.WebAppConfig.DBServer
$DatabaseName = $SitesXml.Sites.WebAppConfig.DBName
$InetpubPath = $SitesXml.Sites.WebAppConfig.InetpubPath
$HostHeader = $SitesXml.Sites.WebAppConfig.HostHeader
$Port = $SitesXml.Sites.WebAppConfig.Port
$WebsitePath=$InetpubPath+"\"+$HostHeader+$Port
$Protocol = $SitesXml.Sites.WebAppConfig.Protocol
$Url = $Protocol+$HostHeader+":"+$Port
$OwnerAlias = $SitesXml.Sites.WebAppConfig.OwnerAlias
$OwnerEmail = $SitesXml.Sites.WebAppConfig.OwnerEmail
$SecondaryOwnerAlias = $SitesXml.Sites.WebAppConfig.SecondaryOwnerAlias
$SecondaryOwnerEmail = $SitesXml.Sites.WebAppConfig.SecondaryOwnerEmail
$WebTemplate = $SitesXml.Sites.WebAppConfig.RootSite.WebTemplate

# Start SP Assignment for object disposal later #
Start-SPAssignment -Global

# Change Shell Title #
$title = $Host.UI.RawUI.WindowTitle
$Host.UI.RawUI.WindowTitle = "Provisioning Employee Portal Web Application..."

# If SharePoint Snapin isn't loaded - load it #
if ((Get-PSSnapin Microsoft.SharePoint.PowerShell)-eq $null)
{
	Write-Host "Adding SharePoint Snapin"
	Add-PSSnapin Microsoft.SharePoint.PowerShell
}
$ErrorPref = $ErrorActionPreference
$ErrorActionPreference = "SilentlyContinue"
$WarningPref = $WarningPreference
$WarningPreference = "SilentlyContinue"

# Tell us the Web App is getting created #
Write-Host "------------------------------------------------------------------"
Write-Host " Step 1 of 10: Creating Web Application at Url $($Url)..."
Write-Host "------------------------------------------------------------------"

# Create the Web App #
New-SPWebApplication -Name $Name -ApplicationPool $ApplicationPool `
-ApplicationPoolAccount $ApplicationPoolAccount -DatabaseName $DatabaseName `
-DatabaseServer $DatabaseServer -HostHeader $HostHeader -Port $Port `
-Path $WebsitePath -Url $HostHeader | Out-Null

# Add the BUILTIN\Administrators group to Full Control Policy #
$userOrGroup = "BUILTIN\Administrators" 
$displayName = "Administrators" 

$WebApp = Get-SPWebApplication $Name 
$policy = $webApp.Policies.Add($userOrGroup, $displayName) 
$policyRole = $webApp.PolicyRoles.GetSpecialRole([Microsoft.SharePoint.Administration.SPPolicyRoleType]::FullControl) 
$policy.PolicyRoleBindings.Add($policyRole) 
$webApp.Update() 

# Change Shell Title #
$Host.UI.RawUI.WindowTitle = "Provisioning Root Site Collection..."

# Tell us the Site Collection is getting created #
Write-Host "------------------------------------------------------------------"
Write-Host " Step 2 of 10: Creating Root Site Collection..."
Write-Host "------------------------------------------------------------------"

# Create the Root Site #
$SPSite = New-SPSite -Name $Name -OwnerAlias $OwnerAlias -OwnerEmail $OwnerEmail `
-SecondaryOwnerAlias $SecondaryOwnerAlias -SecondaryEmail $SecondaryOwnerEmail `
-Template $WebTemplate -Url $Url | Out-Null

# Tell us the Site Collection is getting created #
Write-Host "------------------------------------------------------------------"
Write-Host " Step 3 of 10: Configuring Cache Settings..."
Write-Host "------------------------------------------------------------------"
Write-Host "Configuring BLOB Caching..."
# Enable SP Blob Cache #
$WebApp = Get-SPWebApplication $Url 
# SPWebConfigModification to enable BlobCache 
$configMod1 = New-Object Microsoft.SharePoint.Administration.SPWebConfigModification 
$configMod1.Path = "configuration/SharePoint/BlobCache" 
$configMod1.Name = "enabled" 
$configMod1.Sequence = 0 
$configMod1.Owner = "BlobCacheMod" 
## SPWebConfigModificationType.EnsureChildNode -> 0 
## SPWebConfigModificationType.EnsureAttribute -> 1 
## SPWebConfigModificationType.EnsureSection -> 2 
$configMod1.Type = 1 
$configMod1.Value = "true"
	
######################################################################

# SPWebConfigModification to enable client-side Blob caching (max-age) 
$configMod2 = New-Object Microsoft.SharePoint.Administration.SPWebConfigModification 
$configMod2.Path = "configuration/SharePoint/BlobCache" 
$configMod2.Name = "max-age" 
$configMod2.Sequence = 0 
$configMod2.Owner = "BlobCacheMod" 
## SPWebConfigModificationType.EnsureChildNode -> 0 
## SPWebConfigModificationType.EnsureAttribute -> 1 
## SPWebConfigModificationType.EnsureSection -> 2 
$configMod2.Type = 1 
$configMod2.Value = "86400" 

######################################################################

# SPWebConfigModification to change the default location for the Blob Cache files
$configMod3 = New-Object Microsoft.SharePoint.Administration.SPWebConfigModification
$configMod3.Path = "configuration/SharePoint/BlobCache"
$configMod3.Name = "location"
$configMod3.Sequence = "0"
$configMod3.Owner = "BlobCacheMod"
## SPWebConfigModificationType.EnsureChildNode -> 0 
## SPWebConfigModificationType.EnsureAttribute -> 1 
## SPWebConfigModificationType.EnsureSection -> 2 
$configMod3.Type = 1
$configMod3.Value = $BlobCacheLocation
# Add mods, update, and apply 
$WebApp.WebConfigModifications.Add( $configMod1 ) 
$WebApp.WebConfigModifications.Add( $configMod2 )
$WebApp.WebConfigModifications.Add( $configMod3 )
$WebApp.Update() 
$WebApp.Parent.ApplyWebConfigModifications() 

# Sleep for 5 seconds # 
Start-Sleep -Seconds 5

# Enable Output Cache for Root Site Collection # 
Write-Host "Configuring Output Caching..."
$SPSite = Get-SPSite $Url
$cache = New-Object Microsoft.SharePoint.Publishing.SiteCacheSettingsWriter $SPSite
$cache.EnableCache = $true
$cache.AllowPublishingWebPageOverrides = $true
$cache.EnableDebuggingOutput = $true
$cache.SetAnonymousPageCacheProfileId($SPSite, 1)
$cache.SetAuthenticatedPageCacheProfileId($SPSite, 4)
$cache.SetFarmCacheFlushFlag()
$cache.Update()
$SPSite.Dispose()

# Change Shell Title #
$Host.UI.RawUI.WindowTitle = "Activating Features..."

# Activate Standard and Enterprise Features #
Write-Host "------------------------------------------------------------------"
Write-Host " Step 4 of 10: Activating Features..."
Write-Host "------------------------------------------------------------------"
# Standard #
Write-Host "Enabling Standard Site and Web Features..."
Enable-SPFeature BaseSite -Url $Url
Enable-SPFeature BaseWeb -Url $Url
# Enterprise #
Write-Host "Enabling Enterprise Site and Web Features..."
Enable-SPFeature PremiumSite -Url $Url
Enable-SPFeature PremiumWeb -Url $Url
# Team Collaboration Lists #
Enable-SPFeature TeamCollab -Url $Url
# Mavention Meta Fields #
Write-Host "Enabling Mavention Meta Fields Feature..."
Install-SPSolution Mavention.SharePoint.MetaFields.wsp -WebApplication $Url -GACDeployment
Start-Sleep -Seconds 5
Enable-SPFeature -Identity a6ad433b-0bdf-40aa-aec8-6a091d7a3c26 -Url $Url

# Change Shell Title #
$Host.UI.RawUI.WindowTitle = "Configuring Search Center and Settings..."

# Remove OOTB Search Center Lite Web #
Write-Host "------------------------------------------------------------------"
Write-Host " Step 5 of 10: Removing Search Center Subsite..."
Write-Host "------------------------------------------------------------------"
Remove-SPWeb -Identity $Url"/search" -Confirm:$false -ErrorAction SilentlyContinue

# Create Enterprise Search Center Site Collection #
Write-Host "------------------------------------------------------------------"
Write-Host " Step 6 of 10: Creating Enterprise Search Center Site Collection..."
Write-Host "------------------------------------------------------------------"
$searchUrl = $Url+"/search"
New-SPManagedPath -Explicit -RelativeURL search -WebApplication $Url | Out-Null
New-SPSite -Name "Search Center" -OwnerAlias $OwnerAlias `
-OwnerEmail $OwnerEmail -SecondaryOwnerAlias $SecondaryOwnerAlias `
-SecondaryEmail $SecondaryOwnerEmail -Template "SRCHCEN#0" `
-Url $searchUrl | Out-Null
# Apply MaxSiteCount to content DB #
Set-SPContentDatabase -Identity $DatabaseName -MaxSiteCount 2 `
-WarningSiteCount 1 | Out-Null
Set-SPUser -Identity "NT Authority\Authenticated Users" -Web $searchUrl `
-Group "Search Center Visitors"

# Set Site Collection Search Center Settings #
Write-Host "------------------------------------------------------------------"
Write-Host " Step 7 of 10: Configuring Search Scope Settings..."
Write-Host "------------------------------------------------------------------"
<# These are the possible values for Dropdown
Do Not Show Scopes Dropdown, and default to contextual scope	HideScopeDD_DefaultContextual
Do Not Show Scopes Dropdown, and default to target results page	HideScopeDD
Show scopes Dropdown	ShowDD
Show, and default to ‘s’ URL parameter	ShowDD_DefaultURL
Show and default to contextual scope	ShowDD_DefaultContextual
Show, do not include contextual scopes	ShowDD_NoContextual
Show, do not include contextual scopes, and default to ‘s’ URL parameter	ShowDD_NoContextual_DefaultURL
#>

$SPWeb = Get-SPWeb $Url
$SPWeb.AllProperties["SRCH_ENH_FTR_URL"] = "/search/pages"
$SPWeb.AllProperties["SRCH_SITE_DROPDOWN_MODE"] = "ShowDD"
$SPWeb.AllProperties["SRCH_TRAGET_RESULTS_PAGE"] = "/search/pages/results.aspx"
$SPWeb.Update()
# Search Site #
$searchWeb = Get-SPWeb $searchUrl
$searchWeb.AllProperties["SRCH_ENH_FTR_URL"] = "/search/pages"
$searchWeb.AllProperties["SRCH_SITE_DROPDOWN_MODE"] = "ShowDD"
$searchWeb.AllProperties["SRCH_TRAGET_RESULTS_PAGE"] = "/search/pages/results.aspx"
$searchWeb.Update()

# Create Meta Fields #
Write-Host "------------------------------------------------------------------"
Write-Host " Step 8 of 10: Creating SEO Meta Fields..."
Write-Host "------------------------------------------------------------------"
#Assign fieldXML variable with XML string for site column
# Author
$AuthorFieldXML = '<Field Type="Text"
Name="MetaAuthor"
Description="Author Meta Tag"
DisplayName="Author"
StaticName="MetaAuthor"
Group="Publishing Meta Tags"
Hidden="FALSE"
Required="FALSE"
Sealed="FALSE"
ShowInDisplayForm="TRUE"
ShowInEditForm="TRUE"
ShowInListSettings="TRUE"
ShowInNewForm="TRUE"></Field>'
# Copyright
$CopyrightFieldXML = '<Field Type="Text"
Name="MetaCopyright"
Description="Copyright Meta Tag"
DisplayName="Copyright"
StaticName="MetaCopyright"
Group="Publishing Meta Tags"
Hidden="FALSE"
Required="FALSE"
Sealed="FALSE"
ShowInDisplayForm="TRUE"
ShowInEditForm="TRUE"
ShowInListSettings="TRUE"
ShowInNewForm="TRUE"></Field>'
# Description
$DescriptionFieldXML = '<Field Type="Text"
Name="MetaDescription"
Description="Description Meta Tag"
DisplayName="Description"
StaticName="MetaDescription"
Group="Publishing Meta Tags"
Hidden="FALSE"
Required="FALSE"
Sealed="FALSE"
ShowInDisplayForm="TRUE"
ShowInEditForm="TRUE"
ShowInListSettings="TRUE"
ShowInNewForm="TRUE"></Field>'
# Expiration
$ExpirationFieldXML = '<Field Type="Text"
Name="MetaExpiration"
Description="Expiration Meta Tag"
DisplayName="Expiration"
StaticName="MetaExpiration"
Group="Publishing Meta Tags"
Hidden="FALSE"
Required="FALSE"
Sealed="FALSE"
ShowInDisplayForm="TRUE"
ShowInEditForm="TRUE"
ShowInListSettings="TRUE"
ShowInNewForm="TRUE"></Field>'
# Keywords
$KeywordsFieldXML = '<Field Type="Text"
Name="MetaKeywords"
Description="Keywords Meta Tag"
DisplayName="Keywords"
StaticName="MetaKeywords"
Group="Publishing Meta Tags"
Hidden="FALSE"
Required="FALSE"
Sealed="FALSE"
ShowInDisplayForm="TRUE"
ShowInEditForm="TRUE"
ShowInListSettings="TRUE"
ShowInNewForm="TRUE"></Field>'
# Refresh
$RefreshFieldXML = '<Field Type="Text"
Name="MetaRefresh"
Description="Refresh Meta Tag"
DisplayName="Refresh"
StaticName="MetaRefresh"
Group="Publishing Meta Tags"
Hidden="FALSE"
Required="FALSE"
Sealed="FALSE"
ShowInDisplayForm="TRUE"
ShowInEditForm="TRUE"
ShowInListSettings="TRUE"
ShowInNewForm="TRUE"></Field>'
# Robots
$RobotsFieldXML = '<Field Type="Text"
Name="MetaRobots"
Description="Robots Meta Tag"
DisplayName="Robots"
StaticName="MetaRobots"
Group="Publishing Meta Tags"
Hidden="FALSE"
Required="FALSE"
Sealed="FALSE"
ShowInDisplayForm="TRUE"
ShowInEditForm="TRUE"
ShowInListSettings="TRUE"
ShowInNewForm="TRUE"></Field>'
# Title
$TitleFieldXML = '<Field Type="Text"
Name="MetaTitle"
Description="Title Meta Tag"
DisplayName="Title"
StaticName="MetaTitle"
Group="Publishing Meta Tags"
Hidden="FALSE"
Required="FALSE"
Sealed="FALSE"
ShowInDisplayForm="TRUE"
ShowInEditForm="TRUE"
ShowInListSettings="TRUE"
ShowInNewForm="TRUE"></Field>'

	$SPWeb = Get-SPWeb $Url
	$SPWeb.Fields.AddFieldAsXml($AuthorFieldXML)
	$SPWeb.Fields.AddFieldAsXml($CopyrightFieldXML)
	$SPWeb.Fields.AddFieldAsXml($DescriptionFieldXML)
	$SPWeb.Fields.AddFieldAsXml($ExpirationFieldXML)
	$SPWeb.Fields.AddFieldAsXml($KeywordsFieldXML)
	$SPWeb.Fields.AddFieldAsXml($RefreshFieldXML)
	$SPWeb.Fields.AddFieldAsXml($RobotsFieldXML)
	$SPWeb.Fields.AddFieldAsXml($TitleFieldXML)
	# Grab columns for manipulation
	$Author = $SPWeb.Fields["MetaAuthor"]
	$Copyright = $SPWeb.Fields["MetaCopyright"]
	$Description = $SPWeb.Fields["MetaDescription"]
	$Expiration = $SPWeb.Fields["MetaExpiration"]
	$Keywords = $SPWeb.Fields["MetaKeywords"]
	$Refresh = $SPWeb.Fields["MetaRefresh"]
	$Robots = $SPWeb.Fields["MetaRobots"]
	$Title = $SPWeb.Fields["MetaTitle"]
	# Rename Display Name
	$Author.Title = "Author"
	$Copyright.Title = "Copyright"
	$Description.Title = "Description"
	$Expiration.Title = "Expiration"
	$Keywords.Title = "Keywords"
	$Refresh.Title = "Refresh"
	$Robots.Title = "Robots"
	$Title.Title = "Title"
	# Update All
	$Author.Update()
	$Copyright.Update()
	$Description.Update()
	$Expiration.Update()
	$Keywords.Update()
	$Refresh.Update()
	$Robots.Update()
	$Title.Update()
	$SPWeb.Dispose()

# Add the columns to the Welcome Page content type #
$Web = Get-SPWeb $Url
$Ctype = $Web.ContentTypes["Welcome Page"]
$fields = $web.Fields | Where-Object {$_.group -eq "Publishing Meta Tags"}
$fields | ForEach-Object {
$Ctype.FieldLinks.Add($_)
$Ctype.Update($true)
$Web.Update()
}
$Web.Dispose()

# Change Shell Title #
$Host.UI.RawUI.WindowTitle = "Creating Subsites from XML..."

# Create subwebs from XML input #
Write-Host "------------------------------------------------------------------"
Write-Host " Step 9 of 10: Creating subsites from XML file..."
Write-Host "------------------------------------------------------------------"

Start-SPAssignment -Global

# Loop through each site node to extract data #
$SitesXml.Sites.Site | ForEach-Object {
	Write-Host "---------------------------------------------------------------"
	Write-Host " Step 9 of 10: Creating an SPWeb at $($SiteUrl)"
	Write-Host "---------------------------------------------------------------"
	$SiteTitle = [string]$_.SiteTitle
	$SiteUrl = [string]$_.SiteUrl
	$SiteOwner = [string]$_.Owner
	$SiteUser = [String]$_.User
	$WebTemplate = "CMSPUBLISHING#0"
	$LangId = "1033"
	$SiteUrl = $Url+$SiteUrl
	# Create the SPWeb #
	if ($_.create -ne "false")
	{
	$Web = New-SPWeb -Url $SiteUrl -Language $LangId -Template $WebTemplate `
	-Name $SiteTitle
	}
	# Get publishing site and web objects
	$site = New-Object Microsoft.SharePoint.SPSite($SiteUrl)
	$psite = New-Object Microsoft.SharePoint.Publishing.PublishingSite($site)
	$web = $site.OpenWeb()
	$pWeb = [Microsoft.SharePoint.Publishing.PublishingWeb]::GetPublishingWeb($web)

	# Create all Pages using ForEach-Object #
	if ($_.Page -ne $null){
	$pages = $_.Page | ForEach-Object {
	
	# Create page content variables from XML file
	$PageTitle = [string]$_.PageTitle
	$PageUrl = [string]$_.PageUrl
	$PageLayout = [string]$_.PageLayout
	#$PageContent = [xml]$_.PageContent
	$PageImage = [string]$_.PageImage
	$layout = $pWeb.GetAvailablePageLayouts() | Where-Object {$_.Title -match $PageLayout}
	
    # Create blank page using Add method
	Write-Host "Creating $($PageTitle).aspx page"
    $pages = $pWeb.GetPublishingPages($pWeb)
	$page = $pages.Add($PageUrl, $layout)
	$page.Update()
	
    # Update the filename to the one specified in the XML, add HTML content to Page Content zone
    $item = $page.ListItem
	$item["Title"] = $PageTitle;
	$item["Page Content"] = $PageContent;
	
	# Experimenting with adding a CEWP #
#	$page.CheckOut() 
#	$webpartmanager = $web.GetLimitedWebPartManager($page.Url,
#	[System.Web.UI.WebControls.WebParts.PersonalizationScope]::Shared) 
#	$webpart = New-Object  Microsoft.SharePoint.WebPartPages.ContentEditorWebPart
#	$webpart.ChromeType = [System.Web.UI.WebControls.WebParts.PartChromeType]::None;
#	$webpart.Title = "Added By PowerShell" 
#	$webpart.Content = $PageContent
#	$webpartmanager.AddWebPart($webpart, "Header", 0); 
	$item.Update()
	
    # Check-in and publish page
    $item.File.CheckIn("")
    $item.File.Publish("")
	$file = $item.File
	$pWeb.Update()
	
	} #end Page Foreach
	
	} # End if block #
	
} # End ForEach-Object loop #

# Upload Footer List and create list #
Write-Host "------------------------------------------------------------------"
Write-Host " Step 10 of 10: Creating Footer List and applying branding..."
Write-Host "------------------------------------------------------------------"
$site = Get-SPSite $Url
$Web = $site.OpenWeb()
$spFolder = $web.GetFolder("List Template Gallery")
$spFileCollection = $spFolder.Files
$file = Get-Item C:\Solutions\ConsumersEnergy\CEEP-FooterDirectoryList-LT.stp
$spFileCollection.Add("_catalogs/lt/CEEP-FooterDirectoryList-LT.stp", $file.OpenRead(), $true) | Out-Null
$listTemplates = $site.GetCustomListTemplates($web)
$Web.Lists.Add("CEEP-FooterDirectoryList","",$listTemplates["CEEP-FooterDirectoryList-LT"]) | Out-Null
$Web.Dispose()
$site.Dispose()
Enable-SPFeature -Identity "8d36bad6-e39a-41be-aff4-1a4be71ddcb6" -Url $Url | Out-Null




$EndTime = Get-Date
$TimeSpan = New-TimeSpan $StartTime $EndTime
$Mins = $TimeSpan.Minutes
$Secs = $TimeSpan.Seconds
$Time = $EndTime.ToShortTimeString()
# Tell us it's done #
Write-Host "------------------------------------------------------------------"
Write-Host " Portal Configuration Complete at $($Time)."
Write-Host " Process took $($Mins) minutes and $($Secs) seconds to complete."
Write-Host "------------------------------------------------------------------"

# Set the Window Title back to default #
$Host.UI.RawUI.WindowTitle = $title

# Hit the site to warm it up #
function get-webpage([string]$url,[System.Net.NetworkCredential]$cred=$null)
{
   $wc = new-object net.webclient
   if($cred -eq $null)
   {
     $cred = [System.Net.CredentialCache]::DefaultCredentials;
   }
   $wc.credentials = $cred;
   return $wc.DownloadString($url);
}

Write-Host "------------------------------------------------------------------"
Write-Host " Warming up the new Sites"
Write-Host "------------------------------------------------------------------" 
$cred = [System.Net.CredentialCache]::DefaultCredentials;
$sites = Get-SPSite -WebApplication $WebApp -Limit ALL
foreach ($site in $sites) {
$siteurl = $site.url
$spsite = New-Object Microsoft.SharePoint.SPSite($siteurl)
$pubsite = New-Object Microsoft.SharePoint.Publishing.PublishingSite($spsite)
foreach ($web in $site.AllWebs) {
$pubweb = [Microsoft.SharePoint.Publishing.PublishingWeb]::GetPublishingWeb($web)
$pages = $pubweb.GetPublishingPages($pubweb)
	foreach ($page in $pages) {
	$html = Get-WebPage -Url $page.uri -cred $cred;
	#Write-Host $page.uri
	}
}
}

# Dispose all objects #
Stop-SPAssignment -Global

# Set Error and Warning Preferences back #
$ErrorActionPreference = $ErrorPref
$WarningPreference = $WarningPref

# Open the site in IE #
$ie = New-Object -ComObject InternetExplorer.Application
$ie.Navigate($Url)
$ie.Visible = $true;

DAYSPUG Presentation December 13th 2011


Last night I spoke to a great crowd of PowerShell Enthusiasts at the Dayton SharePoint Users Group (DAYSPUG) in Dayton, Ohio. I knew most of the folks in attendance from other local SharePoint and PowerShell events, so it was nice to see everyone again.

It was a pleasure to speak in front of all of you, and I thoroughly enjoyed the engagement that you all showed.

Since the actual presentation/demo wasn’t much different from my recent engagement at SharePoint Saturday Cincinnati, I’ll simply point to that post for the actual PowerShell and XML code I used in the demos. That content is located here: SPS Cincinnati Post

Here is a post which contains the two Christmas functions I shared last night as well: Two PowerShell Functions for the Christmas Season

Thanks again to Tony Maddin and the rest of the DAYSPUG members for welcoming me to speak. See you all next time!

RD

Use Find/Replace in PowerShell to fix InfoPath Forms after moving to a new Site Collection


I know I know, that’s a really long title.

I found some pretty good PowerShell how-to’s which described how to use Get-ChildItem to iterate through a folder – checking each item for a string and then using -replace to fix the string.

However, my situation was slightly different as I wanted to walk through a SharePoint 2010 Form Library – fixing InfoPath forms which had been moved into a new site collection and thus did not open in the browser and would not save due to the old reference to the XSN.

I’m sure there may be better methods on moving XSNs and XMLs across site collections where maybe this wouldn’t be necessary, but if you’re reading this I’ll assume you don’t care.

In any case, what I ended up doing (after obviously re-publishing the XSN template to the new site collection so new IP forms wouold work) is:

  1. Copy all of the forms using Windows Explorer (we didn’t care about versions or modified by metadata, just the content type metadata) into the new Form Lib.
  2. Run the following PowerShell code to fix each XML file – replacing the link to the old XSN with a link to the new XSN (Note: I ran this on my desktop, NOT on the server as I didn’t need any SP cmdlets):
$files = Get-ChildItem \\sitecollection\davwwwroot\FormLib -Filter "*.xml"
foreach ($file in $files) {
(Get-Content $file.fullname) | ForEach-Object {$_ -replace "http://sitecollection/library/OLDXSNPATH.xsn", "http://newsitecollection/library/NEWXSNPATH.xsn"} | Set-Content $file.fullname
}

Voila, all IP forms are now fixed and will not only open in the browser as expected – but I can now update these forms in the new location as they now point to the correct XSN template.

If you’re a frequent reader you’re probably thinking “Wow, normally he gives us these nice functions with parameters, help, etc.”… You’re right, this time it was a quick and dirty chunk of code. However, chances are I’ll need to do this again – so I did actually write a function for future needs:

function Reset-InfoPathTemplateLink {
Param(
[string]$FilePath,
[string]$FileExtension,
[string]$OldPath,
[string]$NewPath
)
$files = Get-ChildItem $FilePath -Filter $FileExtension
	foreach ($file in $files) {
		(Get-Content $file.fullname) |
		ForEach-Object {$_ -replace $OldPath,$NewPath} |
		Set-Content $file.fullname
	} #end foreach
} #end function

To run the function, first dot-source it and then use the following syntax:

Reset-InfoPathTemplateLink -FilePath "\\sitecollection\subsite\formlib" -FileExtension "*.xml" -OldPath "http://sitecollection/doclib/template.xsn" -NewPath "http://newsitecollection/newdoclib/newtemplate.xsn"

As always, happy PowerShelling!

SharePoint Saturday Cincinnati 2011


This past weekend I broke new ground in my career – I completed my first public speaking engagement! While I have spoken on various topics in front of my SharePoint Team at ICC – this was my first public speaking engagement and overall I think it went very well.

The topic: The Power is in the Shell, use it wisely!
The story: What is PowerShell – how does it fit into the SharePoint 2010 puzzle? How can we take commands run in the Shell and easily convert them to scripts or functions? How can we use the Get-Content cmdlet and some XML to automate content loading or migrations? What are some best practices around PowerShell as it relates to SharePoint 2010?

This was the first SharePoint Saturday in Cincinnati, and I was very proud to be a part of a great event.

My session went pretty flawlessly, as I lucked out and had zero issues with the presentation or the three demos. I had a small group of attendees, but all of them were very engaged in dialog throughout. For those of you who attended, thank you for being a part of it – and if you have any feedback or questions feel free to contact me either on Twitter or via e-mail (rdennis at iccohio dot com).

I promised to upload my slides and demo PowerShell code, so the slides are on Slideshare and the XML and PowerShell code is below:

First demo function – Set-SPWebTitle

function Set-SPWebTitle {
Param(
[string]$SiteUrl,
[string]$SiteTitle
)
$site = Get-SPSite $SiteUrl
$web = $site.RootWeb                                                                                                   
$web.Title = $SiteTitle
Write-Host "Changing title to:" $SiteTitle
$web.Update()                                                                                                          
$web.Dispose()                                                                                                        
$site.Dispose()           
Write-Host "Finished!"
}

Second demo function – New-SPWebFromXml
XML Syntax:

<?xml version="1.0" encoding="utf-8"?>
<Sites>
  	<Site>
    		<SiteTitle>Ryan Dennis</SiteTitle>
	    	<SiteUrl>http://sps.adventureworks.com/rdennis</SiteUrl>
	    	<Page>
			<PageTitle>Home</PageTitle>
			<PageUrl>Home.aspx</PageUrl>
			<PageContent>HTML Content</PageContent>
			<PageLayout>Body Only</PageLayout>
		</Page>
  	</Site>
</Sites>

PowerShell code:

function New-SPWebFromXml {
# Xml Input parameter - accepts string to filename
[CmdletBinding()]
	Param(
    [Parameter(Mandatory=$true)]
	[string]$XmlInput
	)

# Read in list of sites from XML file
[xml]$SitesXml = Get-Content $($XmlInput)
if ($SitesXml -eq $null) {return}
Start-SPAssignment -Global #Stores all objects in the global store for proper disposal
$StartTime = Get-Date #Grab the date & time for further calculation later

# Upload speaker images to the PublishingImages library
Write-Host "Uploading speaker images to the PublishingImages library..."
Add-SPFilesToLibrary -WebUrl http://sps.adventureworks.com -LibraryName PublishingImages -FileExtension "*.jpg" -FolderLocation "C:\SPSDemo\Speakers"

	# Loop through each site node to extract data
	$SitesXml.Sites.Site | ForEach-Object {
	$SiteTitle = [string]$_.SiteTitle
	$SiteUrl = [string]$_.SiteUrl
	$WebTemplate = "CMSPUBLISHING#0"
	$LangId = "1033"
	
	# Get publishing site and web objects
	$site = New-Object Microsoft.SharePoint.SPSite($SiteUrl)
	$psite = New-Object Microsoft.SharePoint.Publishing.PublishingSite($site)
	$web = $site.OpenWeb()
	$pWeb = [Microsoft.SharePoint.Publishing.PublishingWeb]::GetPublishingWeb($web)
	
	# Create the SPWeb
	Write-Host "Creating an SPWeb at $($SiteUrl)"
	New-SPWeb -Url $SiteUrl	-Language $LangId -Template $WebTemplate -Name $SiteTitle
	
	# Create page content variables from XML file
	$PageTitle = [string]$_.Page.PageTitle
	$PageUrl = [string]$_.Page.PageUrl
	$PageLayout = [string]$_.Page.PageLayout
	$PageContent = [string]$_.Page.PageContent
	$PageImage = [string]$_.Page.PageImage
	$layout = $pWeb.GetAvailablePageLayouts() | Where-Object {$_.Title -match $PageLayout}
	
    # Create blank page using Add method
	Write-Host "Creating $($PageTitle).aspx page"
    $pages = $pWeb.GetPublishingPages($pWeb)
	$page = $pages.Add($PageUrl, $layout)
	$page.Update()
	
    # Update the filename to the one specified in the XML, add HTML content to Page Content zone
    $item = $page.ListItem
	$item["Title"] = $PageTitle;
	$item["Page Content"] = $PageContent;
	$item.Update()
	
    # Check-in and publish page
    $item.File.CheckIn("")
    $item.File.Publish("")
	$file = $item.File
	$pWeb.DefaultPage = $file
	$pWeb.Update()
	
	# Get and delete original default.aspx page
	Write-Host "Deleting default.aspx page"
	$list = $web.lists["Pages"]
	$oldPage = $list.items | Where-Object {$_.Name -match "default"}
	$oldPage.Delete();
	$web.Update()
	} #End ForEach-Object loop
	
$EndTime = Get-Date #Grab the ending date & time to get the timespan
$TimeSpan = New-TimeSpan $StartTime $EndTime #Calculate total time taken
Write-Host "$($SitesXml.Sites.Site.Count) sites created in $timespan"
Stop-SPAssignment -Global #Stop assignment, safely disposing all site and web objects
} #End Function