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