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"