Tuesday, April 24, 2012

SharePoint 2010 - error in DIP when opening Office 2010-documents

Scenario: SharePoint 2010 portal with subsites created from a customized Site Template - a very common situation I guess. An error shows in Office 2010 programs on DIP (document information panel)...

When opening Office-documents from a SharePoint 2010 portal I received the following error when clicking on Edit Properties:

"The Document Informatin Panel was unable to load. The document will continue to load. For more information, contact your system administrator."
"The form cannot be opened. To fix this problem, contact the form designer. Form template: http://your-portal-name/your-site-name/../proppanel.xsn. The XML Schema for the form template has an invalid value for the following attribute: Location." 


Click OK and try to use default proppanl.xsn (click OK i next dialog) but no DIP shows in header - only this:



This is appearently a bug discovered by Microsoft China i january 2012 (will occur even after SP1 and CumUpd Nov 2011), and is described in more details her (thanks to Boman for sharing this!):

http://wss.boman.biz/Lists/Posts/Post.aspx?ID=82

The reason is an error that occurs when creating new subsites from a customized Site Template. The XML Schema field "ScopeID" doesn't get a correct GUID for the list but instead gets the value "$ListId:Shared Documents;" - hence the error on the attribute "Location". Result: the sourceID field can not identity from which list the document comes from in SharePoint.

NOTE: the value "$ListId:Shared Documents;" is based on the library name used in your customized Site Template, which was "Shared Documents" in my case. In Boman's article the value is "$ListId:Project Documents;" - probably because that was the name of the library in his customized Site Template.

In my scenario I had a site-structure of four levels and all my sites where generated based on customized Site Template, so I needed to check all sites. This is the script I ended up with and it fixed this error on every library in all my sites (this is probably not the best way of coding a recursive loop for 4 levels but it did the job for me -:)):

# This script fixes a bug in Location field in XML Schema for sites created with customized Site Template.
# Checks root sites and 3 levels of subsites.
# Copy this PS file to local SharePOint 2010 server and open Powershell with Import Modules.
# Run at prompt: <path-to-ps1-file>\<name-of-ps1-file>
# Credits to:
http://wss.boman.biz/Lists/Posts/Post.aspx?List=c0143750%2D7a4e%2D4df3%2D9dba%2D8a3651407969&ID=82

function Apply-Fix($siteUrl)
{
    clear
    Add-PSSnapin "Microsoft.SharePoint.Powershell" -ErrorAction SilentlyContinue # -EA 0
    [Environment]::CurrentDirectory=(Get-Location -PSProvider FileSystem).ProviderPath
   
    foreach ($spwTarget1 in (Get-SPSite $siteUrl).RootWeb.Webs)
    {
 Write-Host "Checking Web: " $spwTarget1.Url
 foreach($list in $spwTarget1.Lists)
        {
#  Write-Host $list.Title
  $fields = $list.fields
  foreach($field in $fields)
         {
              if($field.SourceId -eq '{$ListId:Shared Documents;}')
              {
    $schemaxml = $field.SchemaXML
                  $schemaxmldata = [xml]$schemaxml
                  $schemaxmldata.Field.SetAttribute("SourceID", $list.ID)
                $schemaxml = $schemaxmldata.get_InnerXml()
                 $field.SchemaXML = $schemaxml
                  $field.Update()
                  Write-Host "Fixed" $field.Title "field"
              }
         }

 }
     foreach ($spwTarget2 in $spwTarget1.Webs)
     {
         Write-Host "Checking Web: " $spwTarget2.Url
  foreach($list in $spwTarget2.Lists)
         {
#   Write-Host $list.Title
   $fields = $list.fields
 
  foreach($field in $fields)
          {
               if($field.SourceId -eq '{$ListId:Shared Documents;}')
               {
      $schemaxml = $field.SchemaXML
                    $schemaxmldata = [xml]$schemaxml
                    $schemaxmldata.Field.SetAttribute("SourceID", $list.ID)
                  $schemaxml = $schemaxmldata.get_InnerXml()
                   $field.SchemaXML = $schemaxml
                    $field.Update()
                   Write-Host "Fixed" $field.Title "field"
               }
          }
  }
  
  foreach ($spwTarget3 in $spwTarget2.Webs)
      {
   Write-Host "Checking Web: " $spwTarget3.Url
   foreach($list in $spwTarge3.Lists)
          {
#    Write-Host $list.Title
    $fields = $list.fields
    foreach($field in $fields)
           {
                if($field.SourceId -eq '{$ListId:Shared Documents;}')
                {
       $schemaxml = $field.SchemaXML
                     $schemaxmldata = [xml]$schemaxml
                     $schemaxmldata.Field.SetAttribute("SourceID", $list.ID)
                   $schemaxml = $schemaxmldata.get_InnerXml()
                    $field.SchemaXML = $schemaxml
                     $field.Update()
                    Write-Host "Fixed" $field.Title "field"
                }
           }
   }

   foreach ($spwTarget4 in $spwTarget3.Webs)
       {
           Write-Host "Checking Web: " $spwTarget4.Url

           foreach($list in $spwTarget4.Lists)
               {
#     Write-Host $list.Title
     $fields = $list.fields
     foreach($field in $fields)
            {
                 if($field.SourceId -eq '{$ListId:Shared Documents;}')
                 {
                    $schemaxml = $field.SchemaXML
                      $schemaxmldata = [xml]$schemaxml
                      $schemaxmldata.Field.SetAttribute("SourceID", $list.ID)
                    $schemaxml = $schemaxmldata.get_InnerXml()
                     $field.SchemaXML = $schemaxml
                      $field.Update()
                     Write-Host "Fixed" $field.Title "field"
                 }
            }

    }
   }
  }
 }
    }
     Write-Host "Done."
}

Apply-Fix -siteUrl "http://your-webname/your-portal-name/"
To use this script: copy all code and save as .ps1 file. Store it on one of your SharePoint 2010 servers. Open Powershell (import system modules) and at PS prompt type:

<path-to-folder-with-ps1-file>\<name-of-ps1-file> and hit ENTER.

You will get an error right after fields that has been modified/fixed for each list, but don't worry - just ignore them:


 Re-run the script again to verify that no fields has the incorrect value ("$ListId:Shared Documents;"). Test and verify in your SharePoint libraries - the DIP should now work OK.

UPDATE May 3, 2012:

Another error with the DIP I encountered (maybe related to the error mentioned above?) was an "Undeclared XSD element" on a Site Column used in a library. All library settings was default (no customization on the DIP or custom Content Types). When a Word document opens the main error appears:
"The Document Informatin Panel was unable to load. The document will continue to load. For more information, contact your system administrator."

The detailed error (I didn't copy it before I resolved it :-( ) explain an error with an Undeclared XSD element with the ID and name of a column (in my case a Site Column).


Solution: removed the Site Column from the library (remember to document the values used per document from the Site Column first in order to re-enter the same values afterwards), and then added it again to the library. Re-enter the same values in the Site Column for each document and the DIP should work again.