Listing all sites per variations - an STSADM extension solution
A little while ago, we ran into an issue with the Variation label creation process; it was ending successfully without creating everything. To make matters worst, it wasn't picking the missing sites/pages with the Synchronization Timer Job.
So it was very difficult to figure out what was missing in a particular variation except by browsing to each pages and figuring out if the page was missing. While we only had 150 sub-sites, it could create 10 or 140 of them.
For those interested, it seems that the issue is due to 3 things combined:
- Memory leak in the variation creation process (scheduled to be fixed)
- Potential memory leak when the farm is on a VMWare virtual environment
- Not enough memory on the server :)
Now, while waiting to have more memory and a fix, we still had to create variations correctly. So far, we could only delete a variation and recreate it while hoping it would be done successfully. In order to assert that we had an incorrect variation label and to what extend, I ended up creating a small STSADM extension that was simply listing each sub-sites in an Xml format along with a counter on each node to mention how many sub-sites is under.
Essentially, create a class that implements ISPStsadmCommand and in the main class, call the EnumSites method passing the output file name & Url. Here's the Visual Basic.NET code excerpt :
Private Function EnumSites(ByVal vOutputFile As String, ByVal vUrl As String) As String
Dim output As String = String.Empty
Dim siteMOSS As SPSite = Nothing
Dim rootWeb As SPWeb = Nothing
Dim publishingRootWeb As Publishing.PublishingWeb = Nothing
Try
siteMOSS = New SPSite(vUrl)
rootWeb = siteMOSS.OpenWeb
publishingRootWeb = PublishingWeb.GetPublishingWeb(rootWeb)
Dim xmlDoc As New XmlDocument()
Dim xmlDeclaration As XmlDeclaration = xmlDoc.CreateXmlDeclaration("1.0", "UTF-8", Nothing)
xmlDoc.AppendChild(xmlDeclaration)
Dim xmlRoot As XmlElement = xmlDoc.CreateElement("Variations")
For Each web As PublishingWeb In publishingRootWeb.GetPublishingWebs
If web.Label IsNot Nothing Then
Dim variation As XmlElement = xmlDoc.CreateElement("Variation")
Dim attrSource As XmlAttribute = xmlDoc.CreateAttribute("source")
Dim attrName As XmlAttribute = xmlDoc.CreateAttribute("name")
Dim attrSiteCount As XmlAttribute = xmlDoc.CreateAttribute("numOfSubSites")
Dim numOfSubSites As Integer = 0
attrSource.Value = web.Label.IsSource.ToString
attrName.Value = web.Name
variation.Attributes.Append(attrName)
variation.Attributes.Append(attrSource)
output &= "Variation : " & web.Name & ", isSource=" & web.Label.IsSource.ToString & Environment.NewLine
numOfSubSites += EnumSites(xmlDoc, variation, web.Web.GetSubwebsForCurrentUser(), output)
attrSiteCount.Value = numOfSubSites.ToString
variation.Attributes.Append(attrSiteCount)
xmlRoot.AppendChild(variation)
End If
Next
xmlDoc.AppendChild(xmlRoot)
output &= "Saving Xml output file ..."
xmlDoc.Save(vOutputFile)
Return output
Catch ex As Exception
output &= "Error : " & ex.Message & Environment.NewLine
Finally
If siteMOSS IsNot Nothing Then _
siteMOSS.Dispose()
If rootWeb IsNot Nothing Then _
rootWeb.Dispose()
End Try
Return output
End Function
Private Function EnumSites( _
ByVal vXmlDoc As XmlDocument, _
ByVal vXmlParent As XmlElement, _
ByVal vWebs As SPWebCollection, _
ByRef rOutput As String _
) As Integer
Dim numOfSubSites As Integer = 0
Try
For Each web As SPWeb In vWebs
numOfSubSites += 1
Dim site As XmlElement = vXmlDoc.CreateElement("Site")
Dim attrName As XmlAttribute = vXmlDoc.CreateAttribute("name")
Dim attrWelcomePage As XmlAttribute = vXmlDoc.CreateAttribute("welcomePage")
Dim attrSiteCount As XmlAttribute = vXmlDoc.CreateAttribute("numOfSubSites")
attrName.Value = web.Name
Try
attrWelcomePage.Value = PublishingWeb.GetPublishingWeb(web).DefaultPage.Name
Catch ex As Exception
attrWelcomePage.Value = "N/D --- " & ex.Message
End Try
site.Attributes.Append(attrName)
site.Attributes.Append(attrWelcomePage)
Dim numofSubSubSites As Integer = EnumSites(vXmlDoc, site, web.GetSubwebsForCurrentUser, rOutput)
numOfSubSites += numofSubSubSites
attrSiteCount.Value = numofSubSubSites.ToString
site.Attributes.Append(attrSiteCount)
vXmlParent.AppendChild(site)
Next
Catch ex As Exception
rOutput &= "Error : " & ex.Message & Environment.NewLine
End Try
Return numOfSubSites
End Function
You can essentially do the same for pages if you want to list them and do a compare with the source variation in order to list exactly what's missing, however, when we found out that the memory was the issue, we didn't extend this application so it's still in the "napkin format" :)
Maxime
Comments
Anonymous
September 24, 2007
PingBack from http://msdnrss.thecoderblogs.com/2007/09/24/listing-all-sites-per-variations-an-stsadm-extension-solution/Anonymous
October 03, 2008
I have written a tool that may be able to help you in validating your labels. It's a small part of it, but it will show you the association between the label and the associated URL. It'll also help fix many Variations problems you may have on your site. http://www.thesug.org/blogs/lsuslinky/Lists/Posts/ViewPost.aspx?ID=21Anonymous
October 06, 2008
That's a very interesting tool. Thanks for sharing it! Maxime