Sunday, September 23, 2012

Importing a SharePoint 2010 .CMP file and the “String was not recognized as a valid DateTime” Error

There are plenty of excellent posts out there on how to do a SharePoint 2010 granular backup and restore operation on a document library using PowerShell. A good overview is provided in this blog post on MSDN: SharePoint 2010 Granular Backup-Restore Part 1. I use this process to deploy a set of custom dashboards that I’ve created.

I've put together a couple of PowerShell functions to export (i.e. backup) and import (i.e. restore) a .CMP file (again, plenty of great examples out there), and they work great. However, I ran into a problem when importing one of my document libraries, which lead me to discover an error, similar to the following, in the corresponding log file:

[9/19/2012 1:21:50 PM] [ListItem] [MyDashboard.aspx] Progress: Importing
[9/19/2012 1:21:50 PM] [ListItem] [MyDashboard.aspx] Verbose: List URL: /aSiteCollection/aSite/DashboardPages
[9/19/2012 1:21:50 PM] [ListItem] [MyDashboard.aspx] Error: String was not recognized as a valid DateTime.
[9/19/2012 1:21:50 PM] [ListItem] [MyDashboard.aspx] Debug: at System.DateTimeParse.Parse(String s, DateTimeFormatInfo dtfi, DateTimeStyles styles)
   at System.String.System.IConvertible.ToDateTime(IFormatProvider provider)
   at ...

After a little Googling, I discovered this forum post on TechNet which identified the problem and a workaround: String was not recognized as a valid DateTime on import of site
.

The problem turns out to be in the Manifest.xml file located within the .CMP. The actual line in the .XML causing the problem contains an erroneous year (i.e. 60354):

<Property Name="vti_syncwith_smartbidev\:80/ymus" Type="Time" Value="29 May 60354 05:36:10 -0000" Access="ReadWrite"/>

And now for the purpose of this post: the following PowerShell script basically renames the .CMP file to a .CAB, extracts the files into a folder, searches and replaces the erroneous date in the Manifest.xml and imports it using import-spweb with the NoFileCompression switch.
 
function ImportCAB {
    param(
        [Parameter(mandatory=$true)] [string]$webUrl,
        [Parameter(mandatory=$true)] [string]$fileName
    )    

    try
    {
        $cabFile = $fileName.Replace(".cmp", ".cab")

        if(!(test-path $fileName)) 
        {
            write-host "$fileName does not exist. Exiting..."
            return
        }

        write-host "Copying $fileName to CAB file"
        copy-item $fileName $cabFile
        write-host "Copied $fileName to CAB file"

        $cabFolder = "$(split-path $fileName -Parent)\$((Get-Item -path $fileName).basename)"
        
        if(test-path $cabFolder) { remove-item $cabFolder -recurse }
        
        New-Item -ItemType directory -Path $cabFolder
    
        # Creating CAB Files with Windows PowerShell
        # http://lab.technet.microsoft.com/en-us/magazine/dd547834#id0070049
        $comObject = "Shell.Application" 
        write-host "Creating $comObject" 
        $shell = New-Object -Comobject $comObject 
        if(!$?) { $(Throw "unable to create $comObject object")} 
        write-host "Creating CAB object for $cabFile"
        $sourceCab = $shell.Namespace($cabFile).items()
        write-host "Creating destination folder object for $cabFolder" 
        $DestinationFolder = $shell.Namespace($cabFolder)
        write-host "Expanding $cabFile to $cabFolder" 
        $DestinationFolder.CopyHere($sourceCab)
        
        # Search Manifest.xml for the following and replace "60354" with a valid year
        $findText = "Value=`"29 May 60354 05:36:10 -0000`""
        $replaceText = "Value=`"29 May 2012 05:36:10 -0000`""
        
        (Get-Content "$($cabFolder)\Manifest.xml") | 
            Foreach-Object {$_ -replace $findText, $replaceText} | 
            Set-Content "$($cabFolder)\Manifest.xml" -encoding UTF8

        import-spweb -identity $webUrl -path $cabFolder -force -UpdateVersions 2 -nofilecompression #-whatif
    }
    catch [Exception]
    {
        write-host $_.Exception.ToString() -ForegroundColor Green
    }
}

This works rather well, but does not address the real issue of how to fix the source so that the export produces a valid .CMP file in the first place. In theory, I can import this back into my development machine and fix the issue (try at your own risk).

No comments:

Post a Comment