Tuesday, December 8, 2009
Document icons missing in the search results
To summarize here is what I did :
- Verify that there are no double mapping keys
- Check the icons file names
- IIS reset or recycle the pools
Hope this helps someone.
Sunday, November 22, 2009
SharePoint 2010 Public Beta available for download
Also, Bill Baer has posted a nice article on how to install SharePoint 2010 and SharePoint Foundation 2010 (aka WSS 4). You can read his article here : http://blogs.technet.com/wbaer/archive/2009/11/18/installation-notes-for-microsoft-sharepoint-server-and-microsoft-sharepoint-foundation-2010-beta.aspx
It is not recommended to use SharePoint 2010 Beta in a production environment because it is not supported. Use it only for evaluation purposes. The release version of SharePoint 2010 is expected in first half of the year 2010.
Happy SharePointing...
Tuesday, November 3, 2009
SharePoint Search : Some files are not crawled (indexed)!
Comparing the crawled documents with the non-crawled ones, it appeared that the non-crawled ones are in minor versions (draft). By default, the crawler account is granted 'Full Read' permission. Which mean that it just cannot see draft documents which are visible only to authors who have 'Edit' permission.
So what is the solution? You have to :
- Either grant the crawler account the 'Edit' permission to let him see unpublished files and crawl them. In this case, all draft documents will show in search results to everyone, even to visitors who are not supposed to see them. The search results are not security trimmed (1). However, if you do not have access to a document, you still be denied the access even if it shows in the search result.
- Or keep the crawler account with 'Full Read' and publish the draft documents into major versions.
- Otherwise, accept to not index draft documents
I cannot recommend a solution or another. Every company must have a documents management policy, and its according to this policy that we can decide if we have to raise the right of the crawler account or keep draft documents out of the search scope.
Here are some interesting links to better understand SharePoint search behaviour :
What Does the Crawler Crawl and When?
SharePoint indexing/search behavior on major and minor versions
MOSS Enterprise Search - 16 things you might not know
Hope this helps.
(1) The search results are not trimmed only for draft items. That's what I noticed. For the other items, the results shown are trimmed at query time according to the permissions the user has.
Tuesday, September 29, 2009
WSS 3.0 August 2009 CU...Another issue!
For more details please read the post of Stefan Gossner here .
Thursday, August 27, 2009
SharePoint SP2 Alternate Access Mapping issue... Fixed
The Kb states the following, amongst the issues fixed :
'You have a Web application that has more than five incoming URLs. You cannot change Alternate Access Mappings (AAM) settings after you install the 2007 Microsoft Office system cumulative update that was released in April 2008.'
<Update >
Please be aware of the new issue found in these updates. Read here.
</Update >
Saturday, August 8, 2009
SharePoint Alternate Access Mappings explained....my way!
What AAms are?
AAMs are different urls mapped to the same application in order to give access to the same content using different zones. We cannot talk about AAMs without talking about web application zones. Each SharePoint web application can have five zones : Default, Internet, Intranet, Extranet and Custom. Each zone can have its own authentication provider. For example, Integrated windows authentication for the Default zone, Anonymous access for the Internet zone and Form based authentication for the Extranet zone. All the five zones share the same Database. i.e. the same content, but each one has its proper IIS web Site. Each zone has a public url. When we create a web application, the default zone is created. Let's say "http://default.mycompany:80". Then, we can extend this web application to the four remaining zones if we need to. For our example, we will extend our web application to the Internet zone "http://www.mycompany.com" and the Extranet zone "http://extranet.mycompany.com".
When to use AAMs?
Suppose that for convenience, I want my internal users to access the default zone using a more simplified url. What to do? Create a new AAM (http://mycompany) and map it the default zone. Now, the default zone can be accessed using whether http://mycompany or http://default.mycompany:80.
Suppose again that my company has been sold to a rich man. The urls I created for my web application are no longer valid. What to do to rename my web application urls from mycompany to hiscompany? Backup the content, create a new web application with new urls then restore the content? Yes, it could be. However, there is a better and simpler solution : AAMs. Create new AAMs, i.e. "http://default.hiscompany:80", "http://mycompany", "http://www.hiscompany.com" and "http://extranet.hiscompany.com" and map each url to the appropriate zone.
Where do I define these AAMs?
I'm glad you asked! Go to Central Admin > Operations > Alternate Access Mappings, under the Global Configuration section.
It goes without saying that the urls we are talking about must be first defined in the DNS and IIS.
I hope I have shed more light on AAMs by now. Nevertheless, if you have any question, feel free to ask.
Hope this post is helpful.
Saturday, July 25, 2009
Batch solution deployment between farms
Here is what the console applications has to do :
- Create a folder "SolutionsToDeploy" where the WSPs will be extracted and the command file created.
- Iterate through the solutions in the solutions store, extract the wsp file and generate the Stsadm command needed to install it.
Here is the code :
Imports System.Text
Imports System.IO
Imports System
Imports Microsoft.SharePoint
Imports Microsoft.SharePoint.Administration
Imports System.Xml
Imports System.Web
Module ExtractSolutions
Sub Main(ByVal args() As String)
Try
Dim solutions As SPSolutionCollection = SPFarm.Local.Solutions
Dim Path As String = "SolutionsToDeploy/"
Dim AllowGac As Boolean = False
Dim AllowCas As Boolean = False
' Create the folder if it does not exist
If Not System.IO.Directory.Exists(Path) Then
System.IO.Directory.CreateDirectory(Path)
End If
'Create a file stream where StsAdm command will be added
Dim wrt As System.IO.TextWriter = New StreamWriter(Path + "DeploySolutions.cmd")
For Each sol As SPSolution In solutions
'See if the parameters -AllowGacDeployment and -AllowCasPolicies are needed
AllowGac = IIf(sol.ContainsGlobalAssembly, True, False)
AllowCas = IIf(sol.ContainsCasPolicy, True, False)
Dim strline As String = String.Empty
'Extract the solution into a file
Dim wsp As SPPersistedFile = sol.SolutionFile
wsp.SaveAs(Path + sol.Name)
'For every solution we need two commands : AddSolution and DeploySolution
strline = "Stsadm -o AddSolution -FileName " + sol.Name
wrt.WriteLine(strline)
If sol.DeploymentState = SPSolutionDeploymentState.GlobalAndWebApplicationDeployed Or sol.DeploymentState = SPSolutionDeploymentState.WebApplicationDeployed Then
For Each wapp As SPWebApplication In sol.DeployedWebApplications
strline = "Stsadm -o DeploySolution -name " + sol.Name + " -url " + wapp.GetResponseUri(SPUrlZone.Default).ToString() + IIf(AllowGac, " -AllowGacDeployment", "") + IIf(AllowCas, " -AllowCasPolicies", "") + " -Immediate"
Next
Else
strline = "Stsadm -o DeploySolution -name " + sol.Name + IIf(AllowGac, " -AllowGacDeployment", "") + IIf(AllowCas, " -AllowCasPolicies", "") + " -Immediate"
End If
wrt.WriteLine(strline)
' Execute the timer job
strline = "Stsadm -o ExecAdmSvcJobs"
wrt.WriteLine(strline)
wrt.WriteLine()
Next
'Write the command file to disk and close the stream
wrt.Flush()
wrt.Close()
wrt = Nothing
Catch ex As Exception
Console.WriteLine(ex.Message)
End Try
End Sub
End Module
I executed the console application, copied the new folder created (SolutionsToDeploy) to the new farm and ran the command file (DeploySolutions.cmd). With one shot, all my 50 solutions were added and deployed to the new farm.
Hope this helps.
Friday, July 3, 2009
April 2009 CU Alternate Access Mapping issue... Again
Sunday, June 28, 2009
Extending STSADM...Develop your own commands : Part 2
We have deployed our new command manually, which is not the way we deploy things in SharePoint. The best way is to build a SharePoint solution file (WSP), then deploy it to the farm.
A SharePoint solution is a cab file with a .wsp extension that tells SharePoint how to install this solution and how to use it.
There are two ways to build a SharePoint solution file :
- The automated way, using tools available on the web such as Wspbuilder or STSDEV or VSeWSS.
- The other way is to do the whole thing yourself. This is the best way if you want to understand how solutions files are built, and that's what we are going to do for our Farm Manifest STSADM extension project.
There are four steps to manually create and deploy a SharePoint solution file :
To begin, here is how our project looks in the solution explorer :
The project as you have noticed, contains two folders : "Config" whose content will be copied to the "/Config" folder of the 12 hive, and the folder "Solution" where the generated solution file will go.
Step 1 : Create the manifest.xml file
The manifest.xml contains a unique ID for the solution and the files this solution will deploy :
<?xml version="1.0" encoding="utf-8" ?>
<Solution
SolutionId="2D7B9843-6285-4e67-B393-CB210278E976"
xmlns="http://schemas.microsoft.com/sharepoint/">
<Assemblies>
<Assembly Location="MyStsadmCommands.dll" DeploymentTarget="GlobalAssemblyCache" />
</Assemblies>
<RootFiles>
<RootFile Location="Config\stsadmcommands.MyStsadmCommands.xml" />
<RootFile Location="MyStsadmCommands.dll" />
</RootFiles>
</Solution>
Step 2 : Create the the DDF (Diamond Directive File)
The .ddf file is used with the makecab.exe tool to build the .wsp file
.Set CabinetNameTemplate=MyStsadmCommands.wsp
.Set DiskDirectory1=Solution
.Set Cabinet=on
.Set MaxDiskSize=0
.Set CompressionType=MSZIP;
.Set DiskDirectoryTemplate=CDROM;
manifest.xml manifest.xml
CONFIG\stsadmcommands.MyStsadmCommands.xml config\stsadmcommands.MyStsadmCommands.xml
bin\Debug\MyStsadmCommands.dll MyStsadmCommands.dll
Step 3 : Build the solution file (wsp)
I usually use a command file "MakeSolution.cmd" to build the solution :
makecab.exe /f Cab.ddf
The execution of this command file is done in the post build events of the project :
Now that every thing is ready, right-click on the project name in the solution explorer window then click "Build" or just press CTRL+SHIF+B. the "MyStsadmCommands.wsp" file should be by now created in the "/Solution" folder of the project.
Step 4 : Deploy the solution
To deploy the solution, we have to first add it to the solutions store by using the command :
Stsadm -o AddSolution -filename c:\vsprojects\Mystsadmcommands\solution\MyStsadmCommands.wsp 'Or whatever is the path of your solution file.
Then we have to deploy the solution to the farm :
Stsadm -o DeploySolution -name MyStsadmCommands.wsp -immediate -AllowGacDeployment
To verify that the solution is really deployed and can be used, go to "Central Administration > Operations > Solution Management". You should see it in the solutions list as shown below :
That's it. Hope this helps.
Tuesday, June 16, 2009
Extending STSADM...Develop your own commands : Part 1
You can read the MSDN article first to understand the different steps needed to develop custom STSADM commands : How to: Extend the STSADM Utility
Let's begin by enumerating what it takes to develop our custom command :
- We need to know what should our command do
- Create a Visual Studio Class Library project and add a references to "Microsoft.SharePoint"
- Create a class that implements the "ISPStsadmCommand" interface
- Write the "GetHelpMessage" method
- Write the "Run" method
- Write the XML file that informs STSADM of our new command
- Sign, build and deploy the DLL of our project to the Global Assembly Cache.
What sould our command do?
The STSADM command we will develop will help us have the content of our SharePoint farm in an XML file. We'll call it "FarmManifest". The command will iterate through the farm content service and write to the XML file the content hierarchy as shown below :
- Web Applications
- Content Databases
- Site Collections
- Webs
- Lists
- Web Features
- Site Features
- Web Application Features
- Solutions
- Farm Features Definition
-Filename
[-IncludeAll] (optional) : Include all sites, webs and lists
[-IncludeSites] (optional) : Include only sites
[-IncludeWebs] (optional) : Include webs if IncludeSites
[-IncludeLists] (optional) : Include lists if IncludeSites and IncludeWebs
You may ask what's this command for? Honestly, I think it can be used for many purposes. Let's just say that it can show you all the content of your farm and help you compare the content of two farms, especially when it comes to compare features and solutions. Furthermore, you can enhance this command to include other content such as list items, event handlers, jobs, etc.
The project
Now that we know what should our command do, let's get to work. In Visual Studio we will :
- Create a new Visual Basic Class Library Project. Let's call it "MyStsadmCommands"
- Add a reference to "Windows SharePoint Services"
- Rename the default class "Class1.vb" to "FarmManifest.vb"
- Add the necessary "Imports" to the class :
Imports Microsoft.SharePoint
Imports Microsoft.SharePoint.StsAdmin
Imports Microsoft.SharePoint.Administration
Imports System.Text
Imports System.Xml
Imports System.IO
- Add a "GetHelpMessage" method to our class :
Public Function GetHelpMessage(ByVal command As String) As String Implements Microsoft.SharePoint.StsAdmin.ISPStsadmCommand.GetHelpMessage
Dim strHelpMsg As String = String.Empty
strHelpMsg = "The help message goes here ..."
Return strHelpMsg
End Function
- Add a "Run" method to the class :
Public Function Run(ByVal command As String, ByVal keyValues As System.Collections.Specialized.StringDictionary, ByRef output As String) As Integer Implements Microsoft.SharePoint.StsAdmin.ISPStsadmCommand.Run
' Here goes the code of what sould the command do....
End Function
- For our particular command the "FarmManifest.vb" class when finished, should look like this :
Imports Microsoft.SharePoint
Imports Microsoft.SharePoint.StsAdmin
Imports Microsoft.SharePoint.Administration
Imports System.Text
Imports System.Xml
Imports System.IO
''' <summary>
''' Classe implementing the StsAdm Extension
''' </summary>
''' <remarks></remarks>
Public Class FarmManifest
Implements ISPStsadmCommand
'Private variables
Private ManifestFile As String = String.Empty
Private writer As XmlTextWriter
Private mincludeAll As Boolean = False
Private mincludeSites As Boolean = False
Private mincludeWebs As Boolean = False
Private mincludeLists As Boolean = False
''' <summary>
''' Methode to return the help message
''' </summary>
''' <param name="command"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Function GetHelpMessage(ByVal command As String) As String Implements Microsoft.SharePoint.StsAdmin.ISPStsadmCommand.GetHelpMessage
Dim strHelpMsg As String = String.Empty
strHelpMsg = "stsadm -o FarmManifest" + Environment.NewLine
strHelpMsg = strHelpMsg + " -Filename <filename> (required)" + Environment.NewLine
strHelpMsg = strHelpMsg + " [-IncludeAll] (optional) : Include all sites, webs and lists" + Environment.NewLine
strHelpMsg = strHelpMsg + " [-IncludeSites] (optional) : Include only sites" + Environment.NewLine
strHelpMsg = strHelpMsg + " [-IncludeWebs] (optional) : Include webs if IncludeSites" + Environment.NewLine
strHelpMsg = strHelpMsg + " [-IncludeLists] (optional) : Include lists if IncludeSites and IncludeWebs" + Environment.NewLine
Return strHelpMsg
End Function
''' <summary>
''' Method to execute the STSADM command
''' </summary>
''' <param name="command"></param>
''' <param name="keyValues"></param>
''' <param name="output"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Function Run(ByVal command As String, ByVal keyValues As System.Collections.Specialized.StringDictionary, ByRef output As String) As Integer Implements Microsoft.SharePoint.StsAdmin.ISPStsadmCommand.Run
'Read the commad entered parameters
If keyValues.ContainsKey("IncludeAll") Then
mincludeAll = True
Else
If keyValues.ContainsKey("IncludeSites") Then
mincludeSites = True
If keyValues.ContainsKey("IncludeWebs") Then
mincludeWebs = True
If keyValues.ContainsKey("IncludeLists") Then
mincludeLists = True
End If
End If
End If
End If
'Using the farm content service
Dim contentService As SPWebService = SPWebService.ContentService
If keyValues.ContainsKey("FileName") And keyValues("FileName") IsNot Nothing Then
Try
' Open a new XML file stream for writing
Dim stream As IO.FileStream
stream = File.OpenWrite(keyValues("FileName"))
writer = New XmlTextWriter(stream, Encoding.UTF8)
' Causes child elements to be indented
writer.Formatting = Formatting.Indented
writer.WriteProcessingInstruction("xml", "version=""1.0"" encoding=""utf-8""")
writer.WriteStartElement("Manifest")
' Web Applications element
writer.WriteStartElement("WebApplications")
writer.WriteAttributeString("Count", contentService.WebApplications.Count.ToString)
Dim webApp As SPWebApplication
For Each webApp In contentService.WebApplications
If Not webApp.IsAdministrationWebApplication Then
writer.WriteStartElement("WebApplication")
writer.WriteAttributeString("ID", webApp.Id.ToString)
writer.WriteAttributeString("Name", webApp.Name)
writer.WriteAttributeString("AppPool", webApp.ApplicationPool.Name)
'Content databases element
writer.WriteStartElement("ContentDataBases")
writer.WriteAttributeString("Count", webApp.ContentDatabases.Count.ToString)
Dim contentDatabases As SPContentDatabaseCollection = webApp.ContentDatabases
Dim database As SPContentDatabase
For Each database In contentDatabases
writer.WriteStartElement("ContentDataBase")
writer.WriteAttributeString("Name", database.Name)
writer.WriteAttributeString("DataBaseServer", database.Server)
writer.WriteAttributeString("SiteCount", database.Sites.Count.ToString)
writer.WriteAttributeString("WarningSiteCount", database.WarningSiteCount.ToString)
writer.WriteAttributeString("MaximumSiteCount", database.MaximumSiteCount.ToString)
writer.WriteEndElement() ' Content DataBase
Next database
writer.WriteEndElement() ' Content DataBases
'Site Collections
If mincludeAll Or mincludeSites Then
writer.WriteStartElement("SiteCollections")
writer.WriteAttributeString("Count", webApp.Sites.Count.ToString)
For Each site As SPSite In webApp.Sites
writer.WriteStartElement("Site")
writer.WriteAttributeString("ID", site.ID.ToString)
writer.WriteAttributeString("Url", site.Url)
writer.WriteAttributeString("OwnerName", site.Owner.Name)
writer.WriteAttributeString("OwnerEmail", site.Owner.Email)
' Webs
If mincludeAll Or mincludeWebs Then
For Each web As SPWeb In site.AllWebs
If web.IsRootWeb Then
'RootWeb
writer.WriteStartElement("RootWeb")
writer.WriteAttributeString("ID", web.ID.ToString)
writer.WriteAttributeString("Url", web.Url)
writer.WriteAttributeString("Title", web.Title)
writer.WriteAttributeString("Template", web.WebTemplate & "#" & web.WebTemplateId.ToString)
writer.WriteStartElement("SubWebs")
writer.WriteAttributeString("Count", web.Webs.Count.ToString)
'Webs
ProcessWebs(web.Webs)
writer.WriteEndElement() 'SubWebs
writer.WriteEndElement() ' RootWeb
End If
web.Dispose()
Next
End If
'Site features
ProcessFeatures(site.Features, "SiteFeatures")
writer.WriteEndElement() ' Site
site.Dispose()
Next site
writer.WriteEndElement() 'Site Collections
End If
'Web App features
ProcessFeatures(webApp.Features, "WebAppFeatures")
writer.WriteEndElement() ' Web Application
End If
Next webApp
writer.WriteEndElement() ' Web Applications
'Solutions
writer.WriteStartElement("Solutions")
writer.WriteAttributeString("Count", SPFarm.Local.Solutions.Count.ToString)
For Each solution As SPSolution In SPFarm.Local.Solutions
writer.WriteStartElement("Solution")
writer.WriteAttributeString("ID", solution.Id.ToString)
writer.WriteAttributeString("Name", solution.Name)
writer.WriteAttributeString("Deployed", solution.Deployed.ToString)
writer.WriteAttributeString("ContainsGlobalAssembly", solution.ContainsGlobalAssembly.ToString)
writer.WriteAttributeString("ContainsCodeAccessSecurityPolicy", solution.ContainsCasPolicy.ToString)
writer.WriteAttributeString("LastOperationResult", solution.LastOperationResult.ToString)
writer.WriteAttributeString("LastOperationTime", solution.LastOperationEndTime.ToString)
writer.WriteEndElement() ' Solution
Next solution
writer.WriteEndElement() ' Farm features
'Features
writer.WriteStartElement("Features")
writer.WriteAttributeString("Count", SPFarm.Local.FeatureDefinitions.Count.ToString)
For Each feature As SPFeatureDefinition In SPFarm.Local.FeatureDefinitions
writer.WriteStartElement("Feature")
writer.WriteAttributeString("ID", feature.Id.ToString)
writer.WriteAttributeString("Name", feature.DisplayName)
writer.WriteAttributeString("Scope", feature.Scope.ToString)
writer.WriteAttributeString("SolutionID", feature.SolutionId.ToString)
writer.WriteEndElement() ' Feature
Next feature
writer.WriteEndElement() ' Farm features
writer.WriteEndElement() ' Manifest
' Flush the writer and close the stream
writer.Flush()
stream.Close()
Catch ex As Exception
Console.WriteLine(ex.Message)
End Try
Else
Throw New ArgumentException("FileName parameter is empty")
End If
End Function
''' <summary>
''' 'Recusive method to process webs and sub webs
''' </summary>
''' <param name="webcollection"></param>
''' <remarks></remarks>
Private Sub ProcessWebs(ByVal webcollection As SPWebCollection)
For Each web As SPWeb In webcollection
writer.WriteStartElement("Web")
writer.WriteAttributeString("ID", web.ID.ToString)
writer.WriteAttributeString("Url", web.Url)
writer.WriteAttributeString("Title", web.Title)
writer.WriteAttributeString("Template", web.WebTemplate & "#" & web.WebTemplateId.ToString)
'Web Lists
If mincludeLists Or mincludeAll Then
writer.WriteStartElement("Lists")
writer.WriteAttributeString("Count", web.Lists.Count.ToString)
For Each list As SPList In web.Lists
writer.WriteStartElement("List")
writer.WriteAttributeString("ID", list.ID.ToString)
writer.WriteAttributeString("Title", list.Title)
writer.WriteAttributeString("Author", list.Author.Name)
writer.WriteAttributeString("Template", list.BaseTemplate.ToString)
writer.WriteAttributeString("ItemsCount", list.ItemCount.ToString)
writer.WriteEndElement() ' List
Next
writer.WriteEndElement() 'Lists
End If
'Web features
ProcessFeatures(web.Features, "WebFeatures")
'Sub Webs
ProcessWebs(web.Webs)
writer.WriteEndElement() ' Web
web.Dispose()
Next
End Sub
''' <summary>
''' Processing features
''' </summary>
''' <param name="features"></param>
''' <param name="element"></param>
''' <remarks></remarks>
Private Sub ProcessFeatures(ByVal features As SPFeatureCollection, ByVal element As String)
writer.WriteStartElement(element)
writer.WriteAttributeString("Count", features.Count.ToString)
For Each feature As SPFeature In features
writer.WriteStartElement("Feature")
writer.WriteAttributeString("ID", feature.Definition.Id.ToString)
writer.WriteAttributeString("Name", feature.Definition.DisplayName)
writer.WriteAttributeString("Scope", feature.Definition.Scope.ToString)
writer.WriteAttributeString("SolutionID", feature.Definition.SolutionId.ToString)
writer.WriteEndElement() ' Feature
Next feature
writer.WriteEndElement() 'Features
End Sub
End Class
- Now that our custom command is ready, it's time to tell STSADM about it. To do that, we have to write a specific xml file and store it in "/config" directory of the "12 hive" (C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\CONFIG). The name of the xml file must begin with "stsadmcommands." Let's call ours "stsadmcommands.MyStsadmCommands.xml". In this file is a very simple xml, we put a "
<?xml version="1.0" encoding="utf-8" ?>
<commands>
<command name="FarmManifest"
class="MyStsadmCommands.FarmManifest, MyStsadmCommands, Version=1.0.0.0, Culture=neutral, PublicKeyToken=606cd03fbee78308" />
</commands>
As you certainly have noticed, the class attribute of the command is a string containing {the class name, the namespace, the version, the culture, the public key token}. To obtain the public key token, we have to sign our project first. To do so, go to Project properties (right click on the projet name), select the "Signing" tab, select the "Sign the assembly" option and choose
The "MyStsadmCommands.snk" file is now added to the project. Now, build the project. We still do not have our public key token, I know ! Check out this link : Visual Studio tip to get the public key token.
For now, to begin to test our fresh StsAdm command, we only have to copy the
Congratulation! Now in a command line window, try this :
stsadm -o FarmManifest -filename c:\FarmManifest.xml -includeall
Warning : If you have a large farm, this command may take long to execute.
In part 2 of this post, I'll explain how to build a SharePoint solution file (wsp) to deploy our custom command. Until then, if you have any question, feel free to ask.
Friday, May 29, 2009
SharePoint SP2 Alternate Access Mapping issue...continued
The following links may help make your decision :
- FAQ concerning Service Pack 2 and the Cumulative Updates for April 2009 for the 2007 Microsoft® Office System and Microsoft Office servers
- Description of the Windows SharePoint Services 3.0 cumulative update package: April 30, 2009
- Description of the SharePoint Server 2007 cumulative update package (MOSS server package): April 30, 2009
Tuesday, May 26, 2009
SharePoint SP2 Alternate Access Mapping issue
<Update date="August, 27, 2009">
The fix for this issue has been published in August 2009 CU : http://support.microsoft.com/kb/973410. The Kb states the following, amongst the issues fixed :
'You have a Web application that has more than five incoming URLs. You cannot change Alternate Access Mappings (AAM) settings after you install the 2007 Microsoft Office system cumulative update that was released in April 2008.'
Thank you Joe Reichard.
</Update>
I wonder if any of you has encountered this problem. Just after installing WSS and MOSS SP2 and April Cumulative Updates, SharePoint began to throw the following exception, when there are multiple Alternate Access Mappings (in my case more than six) and try to add or delete one :
Unexpected end of file has occurred. The following elements are not closed: MappedUrl, AlternateDomain, AlternateDomains. Line 25, position 34.
at System.Xml.XmlTextReaderImpl.Throw(Exception e)
at System.Xml.XmlTextReaderImpl.Throw(String res, String arg)
at System.Xml.XmlTextReaderImpl.Throw(Int32 pos, String res, String arg)
at System.Xml.XmlTextReaderImpl.ThrowUnclosedElements()
at System.Xml.XmlTextReaderImpl.ParseElementContent()
at System.Xml.XmlTextReaderImpl.Read()
at System.Xml.XmlLoader.LoadNode(Boolean skipOverWhitespace)
at System.Xml.XmlLoader.LoadDocSequence(XmlDocument parentDoc)
at System.Xml.XmlLoader.Load(XmlDocument doc, XmlReader reader, Boolean preserveWhitespace)
at System.Xml.XmlDocument.Load(XmlReader reader)
at System.Xml.XmlDocument.LoadXml(String xml)
at Microsoft.SharePoint.Administration.SPAlternateUrlCollection.HasMissingUrl(String xml)
at Microsoft.SharePoint.Administration.SPContentDatabase.UpdateAlternateAccessMapping(SPAlternateUrlCollection collection)
at Microsoft.SharePoint.Administration.SPAlternateUrlCollection.UpdateAlternateAccessMappingInContent()
at Microsoft.SharePoint.Administration.SPAlternateUrlCollection.Update()
at Microsoft.SharePoint.Administration.SPAlternateUrlCollection.Delete(Int32 index, Boolean update)
at Microsoft.SharePoint.Administration.SPAlternateUrlCollection.Delete(String incomingUrl, Boolean update, Boolean throwIfNotFound)
at Microsoft.SharePoint.ApplicationPages.EditIncomingUrlPage.BtnDelete_Click(Object sender, EventArgs e)
at System.Web.UI.WebControls.Button.OnClick(EventArgs e)
at System.Web.UI.WebControls.Button.RaisePostBackEvent(String eventArgument)
at System.Web.UI.WebControls.Button.System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(String eventArgument)
at System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument)
at System.Web.UI.Page.RaisePostBackEvent(NameValueCollection postData)
at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
After this exception is thrown, it's impossible to add or delete an Alternate Access Mapping, extend or unextend the web application. The same error shows.
This issue began to happen just after installing WSS and MOSS SP2 and the cumulative updates of april 2009. I have not seen it with SP1.
After many digging ups, I found out that SharePoint stores the AAMs in two places :
1. In the config DB, exactly in the dbo.Objects table
2. In the content DB, in the table dbo.DatabaseInformation in a line where the name is 'AlternateAccessMappingXml' and the value (nvarchar(1023)) is an Xml string containing all the AAMs. This line is absent in SP1.
So, the “Unexpected end of file has occurred” that SharePoint is talking about is the xml string stored in the line ‘AlternateAccessMappingXml’. Remember this string is limited to 1023 characters. Therefore, when the number of AAMs is big, it just does not fit in the field. The xml string is then truncated to 1023 characters and becomes invalid xml.
It is very easy to reproduce the issue :
1. Create a new web application with a Publishing site for example “BlueBand”.
2. Extend the Internet zone (or any zone) of the web application
3. Add six or more Alternate Access Mapping to the zone extended
4. Perform a IISRESET
5. Try to delete the last AAM or add a new one.
At the moment the only workaround I found is to alter the xml string in the content database and, make it fit in 1023 characters and well formed. Of course in coherence with what is stored in the config DB. But, I do not recommand this solution to any one since it is not supported. Use it at your own risk.
My colleague Mario Leblond has also blogged in french on this issue. You can read him here
Tuesday, March 31, 2009
Custom publishing site definition and MCMS 2002 migration to SharePoint 2007
Last week I developed a custom minimal publishing site definition based on the Andrew
Connell’s one. All the tests went just fine. After that we wanted to use it for the
conversion of our portal from MCMS 2002 to SharePoint 2007. We created a site collection
based on this custom site definition as the destination of the conversion and launched
the operation. Few minutes later the content migration failed with the following
error :
Migration throws exception: An item with the same key has already been added.
Stacktrace:
At System.ThrowHelper.ThrowArgumentException(ExceptionResource resource)
at System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean
add) at System.Collections.Generic.Dictionary`2.Add(TKey key, TValue value) at Microsoft.SharePoint.SPFeaturePropertyCollection.Add(SPFeatureProperty
property) at Microsoft.SharePoint.Publishing.Administration.ContentMigration.<>c__DisplayClass4.
at Microsoft.SharePoint.Publishing.CmsSecurityUtilities.RunWithWebCulture(SPWeb
web, CodeToRun webCultureDependentCode) at Microsoft.SharePoint.Publishing.Administration.ContentMigration.ConvertToComplexPublishing(SPWeb
web)
....
FYI, if the “SimplePublishing” property is set to “false”, that means that the approval workflow is required for every publishing page. We changed our custom publishing site definition to have this property set to “false” :
< Property key="SimplePublishing" value="false"/>
After this, the content migration went just as we have expected.
Saturday, February 28, 2009
STSADM : A tool I can't live with out!
Furthermore, what is interesting about STSADM, and since it is a command-line tool, is that we can group many commands in a batch file to execute them all together. We can even schedule the execution to run at a specific time.
STSADM default location is in the BIN directory under the 12 hive: “c:\program files\common files\microsoft shared\web server extensions\12\bin”. To make things easier for your self, add this location to your path variable, so you can execute stsadm.exe anywhere on your command prompt.
As an example (a very simple one), here is a sample of a batch file to perform a backup of a SharePoint site:
Use Notepad or your favorite texte editor and write in the line below:
stsadm.exe -o backup -url %1 -filename c:\backups\%2.bkp
Save this to sitebackup.cmd for example.
As you see, this command file accepts two parameters: %1 and %2. The first parameter is the url of the site to backup and the second is the name you want to give to your backup file.
On the command prompt, enter the following:
sitebackup.cmd http://yoursharepointsiteurl yourbackupfilename
As a result, you will have a backup of your site http://yoursharepointsiteurl.com stored in c:\backups\yourbackupfilename.bkp.
If you want this backup to be performed periodically, just create a scheduled task to execute at any time you want, the command file you have created.
One last thing : STSADM comes with about a hundred of commands that cover many administration tasks. However, if you find that none of these commands can achieve that task you want and of course, this task cannot be done via the central admin, you can develop your own STSADM command and add it to SharePoint. It is very easy and I will show you that in my next post. Until then, try to get acquainted with STSADM commands and enjoy this powerful tool.
Extending STSADM...Develop your own commands : Part 1
Saturday, January 31, 2009
Microsoft Office SharePoint Server 2007 (MOSS) : Features and CALs.
features such as Excel services and electronic forms, we need to purchase per user
licenses called CALs, Client Access Licenses. So, here is what you should know about
MOSS licensing:
- Windows SharePoint Services 3.0 (WSS) are server components, same as IIS among other server components. All you have to acquire is a license to use Windows server 2003 or 2008.
- Watch out! Depending on what features you need and the number of users you have,
MOSS may be very expensive. There are to versions: Standard end Enterprise and each
version has its own CALs. To use Enterprise features, both Standard and Enterprise
CALs must be purchased.
- To use MOSS enterprise features such as “Business intelligence” and “Enterprise
search”, you have to pay for per user licenses.
- Microsoft Office SharePoint Server 2007 and Related Technologies pricing
- Microsoft Office SharePoint Server 2007 frequently asked questions
- Microsoft Office SharePoint Server: How to Buy
Tuesday, January 13, 2009
SharePoint : The need for a governance plan
Governance plan is critical step for any successful SharePoint deployment. The absence of such a plan may even lead to a total chaos. Since no organization wants to loose control over her information, a plan to structure this information and establish the responsibilities between users and IT professionals is unavoidable.
This has been said, the governance plan is neither meant to very limit the end-user nor to overload administrators and developers.
Where to start then?
- Plan governance (Technet)
- Microsoft SharePoint Team Blog
- Mark Schneider's SharePoint Taxonomy and Governance Blog