Backing up and restoring "sensitive" metadata
It happened a few times that specific lists or document libraries showed behaviors which we couldn't explain very easily, and for which it would have been easier just to create a new list / document library and migrate the content. There is a small problem still: the metadata regarding the "Created" / "Created by" / "Modified" / "Modified by" fields was lost.
In order to overcome this, I wrote the following script. Nevertheless, it doesn't adress versioning inside a list / document library - but this may be added in a future version of the program ...
using Microsoft.SharePoint;
using System;
using System.Collections;
using System.IO;
namespace EditUserNamesAndDates {
class FourStrings {
public string created;
public string modified;
public string author;
public string editor;
}
class Program {
static readonly string siteUrl = @"https://testserver";
static readonly string webUrl = @"/";
static readonly string listName = @"Shared Documents";
static readonly string filePath = @"Metadata_Export.txt";
static void Main(string[] args) {
if (args.Length == 1)
if (args[0].ToString() == "-backup") {
StreamWriter logFile = File.AppendText(filePath);
SPSite mySite = null; SPWeb myWeb = null; int counter = 0;
try {
mySite = new SPSite(siteUrl);
myWeb = mySite.OpenWeb(webUrl);
SPList myList = myWeb.Lists[listName];
foreach (SPListItem anItem in myList.Items) {
logFile.WriteLine(anItem["Name"]);
logFile.WriteLine(anItem["Created"]);
logFile.WriteLine(anItem["Modified"]);
logFile.WriteLine(anItem["Author"]);
logFile.WriteLine(anItem["Editor"]);
counter++;
if (counter % 50 == 0)
Console.WriteLine(counter + " metadata sets backed up.");
} }
catch (Exception ex) {
Console.WriteLine(ex.GetType() + ": " + ex.Message);
Console.WriteLine(ex.StackTrace);
}
finally {
Console.WriteLine(counter + " metadata sets backed up.");
if (myWeb != null) myWeb.Dispose();
if (mySite != null) mySite.Dispose();
}
logFile.Close(); return;
}
else if (args[0].ToString() == "-restore") {
StreamReader logFile = File.OpenText(filePath);
SPSite mySite = null; SPWeb myWeb = null; int counter = 0;
try {
mySite = new SPSite(siteUrl);
myWeb = mySite.OpenWeb(webUrl);
SPList myList = myWeb.Lists[listName];
Hashtable readData = new Hashtable();
for (int i = 0; i < myList.Items.Count; i++) {
FourStrings newEntry = new FourStrings();
string newEntryTitle = logFile.ReadLine();
newEntry.created = logFile.ReadLine();
newEntry.modified = logFile.ReadLine();
newEntry.author = logFile.ReadLine();
newEntry.editor = logFile.ReadLine();
readData.Add(newEntryTitle, newEntry);
}
foreach (SPListItem anItem in myList.Items) {
FourStrings foundEntry = (FourStrings)readData[anItem["Name"]];
anItem["Created"] = foundEntry.created;
anItem["Modified"] = foundEntry.modified;
anItem["Author"] = foundEntry.author;
anItem["Editor"] = foundEntry.editor;
anItem.UpdateOverwriteVersion(); counter++;
if (counter % 50 == 0)
Console.WriteLine(counter + " metadata sets restored.");
}
}
catch (Exception ex) {
Console.WriteLine(ex.GetType() + ": " + ex.Message);
Console.WriteLine(ex.StackTrace);
}
finally {
Console.WriteLine(counter + " metadata sets restored.");
if (myWeb != null) myWeb.Dispose();
if (mySite != null) mySite.Dispose();
}
logFile.Close(); return;
}
Console.WriteLine("Usage: EditUserNamesAndDates [-backup | -restore]");
} } }
You just need to add a reference to Microsoft.SharePoint.dll to your Visual Studio console application project. An alternative method to compile the project would be to use the .NET C# compiler, as follows:
C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\csc.exe EditUserNamesAndDates.cs /R:"C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\ISAPI\Microsoft.SharePoint.dll"