SharePoint–How To: Delete Versions of documents in a Document Library, keeping Top N Versions

 

I have this requirement coming to me multiple times where people enable versioning on the Document Library, but never keep an upper limit of number of versions to be retained. This results in an unmanageable number of versions created for the document in the SharePoint library. If the number is too high, deleting all the versions through the UI also results in time out. Hence the recommendation is to keep a check on the number of versions you want to retain and configure that in the Versioning Settings for the library.

In this post, I’ll share the code to delete the old versions of a Document in a Document library and retaining the Top N versions.

1. Create a new Console Application Project using Visual Studio. You can use either 2008 or 2010 depending on the SharePoint version.

2. Add the reference to the Microsoft.SharePoint.dll

3. Make Sure to change the Platform target to “Any CPU”. You can do that by going to Build tab in the Project Properties window.

4. In the class where the Main Method is defined, add the following code below and call the method from the Main method.

 static void Main(string[] args)
        {
            ProcessRequest(args);
            Console.ReadLine();
        }
        private static void ProcessRequest(string[] args)
        {
            string siteURL;
            string webURL;
            string ListName;
            string versionsToKeep;
            getValues(args, out siteURL, out webURL, out ListName, out versionsToKeep);
            Console.WriteLine("Site URL: " + siteURL);
            Console.WriteLine("Web URL: " + webURL);
            Console.WriteLine("List Name: " + ListName);
            Console.WriteLine("Versions To Keep: " + versionsToKeep);
            FileStream fs1 = new FileStream("Log.txt", FileMode.Append);
            // First, save the standard output.
            TextWriter tmp = Console.Out;
            StreamWriter sw1 = new StreamWriter(fs1);
            sw1.AutoFlush = true;
            TextWriter dual = new DualWriter(sw1, tmp);
            Console.SetOut(dual);
            try
            {
                DeleteVersionHistory(siteURL, webURL, ListName, int.Parse(versionsToKeep));
            }
            catch (Exception ex)
            {
                Console.WriteLine("Exception Occurred during processing...");
                Console.WriteLine(ex.Message + System.Environment.NewLine + ex.StackTrace);
            }
            finally
            {
                sw1.Close();
                Console.SetOut(tmp);
            }
        }
        private static void getValues(string[] args, out string siteURL, out string webURL, out string ListName, out string versionsToKeep)
        {
            siteURL = string.Empty;
            webURL = string.Empty;
            ListName = string.Empty;
            versionsToKeep = string.Empty;
            if (args.Length == 4)
            {
                siteURL = args[0];
                webURL = args[1];
                ListName = args[2];
                versionsToKeep = args[3];
            }
            else
            {
                Console.WriteLine("Arguments are missing ...");
                Console.WriteLine("Please provide the values below...");
                Console.Write("Site URL: ");
                siteURL = Console.ReadLine();
                Console.WriteLine();
                Console.Write("Web URL: ");
                webURL = Console.ReadLine();
                Console.WriteLine();
                Console.Write("List Name: ");
                ListName = Console.ReadLine();
                Console.WriteLine();
                Console.Write("Versions To Keep: ");
                versionsToKeep = Console.ReadLine();
            }
        }
        
            
                
        private static void DeleteVersionHistory(string siteURL, string webURL, string listname, int versionToKeep)
        {
            Console.WriteLine("Started the code to delete the versions.. ");
            #region SPSite
            using (SPSite spSite = new SPSite(siteURL))
            {
                Console.WriteLine("Found the Site instance..");
                #region SPWeb
                using (SPWeb spWeb = spSite.OpenWeb(webURL))
                {
                    Console.WriteLine("Found the Web instance..");
                    SPList list = spWeb.Lists[listname];
                    Console.WriteLine("Found the List instance..");
                    #region DocumentLibrary
                    if (list.BaseTemplate == SPListTemplateType.DocumentLibrary)
                    {
                        SPDocumentLibrary library = (SPDocumentLibrary)list;
                        foreach (SPListItem item in list.Items)
                        {
                            SPFile file = item.File;
                            Console.WriteLine("Deleting versions for Item with ID: {0} Name {1}", item.ID, item.Name);
                            int verCount = item.Versions.Count;
                            if (verCount - versionToKeep < 0)
                            {
                                Console.WriteLine("Versions Count is Less than the specified versions to keep ");
                            }
                            else
                            {
                                do
                                {
                                    try
                                    {
                                        Console.WriteLine("File version {0}, Item Version {1} ", file.Versions[0].VersionLabel, item.Versions[item.Versions.Count - 1].VersionLabel);
                                        item.Versions[item.Versions.Count – 1].Delete();
                                        file.Versions[0].Delete();
                                    }
                                    catch (Exception ex)
                                    {
                                        Console.WriteLine("Exception occured deleting.......");
                                        Console.WriteLine(ex.Message + System.Environment.NewLine + ex.StackTrace);
                                    }
                                } while (file.Versions.Count > versionToKeep || item.Versions.Count > versionToKeep + 1);
                            }
                        }
                    }
                    #endregion DocumentLibrary
                   
                }
                #endregion SPWeb
            }
            #endregion SPSite
            Console.WriteLine("Exiting the code to delete the versions.. ");
        }

5. In the same project Add a new class file and add the class code below:

 public class DualWriter : TextWriter
    {
        private TextWriter one;
        private TextWriter two;
        public DualWriter(TextWriter A, TextWriter B)
        {
            one = A;
            two = B;
        }
        public override System.Text.Encoding Encoding
        {
            get
            {
                return one.Encoding;
            }
        }
        public override void Write(char c)
        {
            one.Write(c);
            two.Write(c);
        }
        public override void WriteLine(string value)
        {
            one.WriteLine(value);
            two.WriteLine(value);
        }
    }

6. The above class file is required as I am writing the Console Output to the console window as well as to a Log file which would be created if not present where the .exe for the console application would reside.

7. The Input parameters for the code to delete the versions are:

a. The Site Collection URL

b. The Sub Site relative URL

c. The Document Library Name

d. The number of latest versions to keep

8. The parameters can be passed as argument line parameters and if not supplied, the code would ask for those parameter values at run time.

9. Build the project and run the .exe to delete the old versions of each items in the Document Library

10. Test it on a Development Server before running it on any production Server.

 

Quote of the Day:

The company's most urgent task is to learn to welcome, beg for, demand - innovation from everyone

--Tom Peters

Disclaimer: The code sample above is provided is as is and the owner holds no responsibility for any issues if any arrive.