Microsoft SharePoint Developer Documentation Team Blog
The Official Blog of the SharePoint Developer Documentation Team

February, 2008

  • Microsoft SharePoint Developer Documentation Team Blog

    How to: Create a Content Class That Can Be Backed Up and Restored

    • 1 Comments

    Introduction

    If you have a custom content component that you want to be included in Windows SharePoint Server 3.0 backups and restores, you must represent the component with a class that implements the IBackupRestore interface. This post explains how to do that. There is a complete example following the procedures. This post assumes that you are familiar with my earlier post: Programming with the Windows SharePoint Services Backup/Restore Object Model.

    Note: Unless explicitly stated otherwise, all classes and interfaces referred to in this post are in the Microsoft.SharePoint.Administration.Backup namespace. Classes that you will create are in bold pink. Also, this post refers at times to the “reference topic” for this or that method/property for supplementary information. As of the date of this posting these reference topics in the most recent versions of the WSS SDK (1.3), in either download or MSDN form, did not yet contain this new material. Look for another update soon. The additional information is not necessary for using this post as a learning exercise or implementing the example it contains.

    Your class does not have to derive from Microsoft.SharePoint.Administration.SPPersistedObject but if your content is a database, we recommend that you derive your class from either Microsoft.SharePoint.Administration.SPDatabase or from Microsoft.SharePoint.Administration.SPContentDatabase. Both of the latter classes are derived from SPPersistedObject and both implement IBackupRestore. Therefore, you will have default implementations of members of IBackupRestore that you can use when appropriate.

    You can create as many types of IBackupRestore classes you want and, if you want, they can be nested as a tree of component classes. But the highest class in any such tree must derive (directly or indirectly) from SPPersistedObject object and must be a child of Microsoft.SharePoint.Administration.SPFarm. If your content class is not a child of any other custom content class, it must derive (directly or indirectly) from SPPersistedObject object and must be a child of SPFarm.

    If your class derives from a class that already implements IBackupRestore object (whether or not it derives from SPPersistedObject), and you want to replace an inherited implementation of an IBackupRestore member, your class declaration should explicitly reference IBackupRestore like this:

    [C#]

    public class MyClass : SPPersistedObject, IBackupRestore

    Your "override" of any IBackupRestore member should explicitly include "IBackupRestore" in the member name and it should not include the public keyword. The following is an example:

    [C#]

    UInt64 IBackupRestore.DiskSizeRequired { ... }

    Alternatively, if the implementation of the member in the parent class used the virtual or override keywords, you can use the override keyword in your implementation like this:

    [C#]

    public override UInt64 DiskSizeRequired { ... }

    Warning: Do not hide the inherited member implementation by redeclaring the member either with or without the new keyword ([new] public UInt64 DiskSizeRequired { ... }). In the procedure below, the member signatures are written as they would be for a class that does not derive from a class that already implements IBackupRestore. Be sure to change them to the required pattern if your class does derive from such a parent.

    If your class derives from SPPersistedObject, let the Id and Name properties of that class serve as the implementation of the IBackupRestore.Id and IBackupRestore.Name properties. You may override the properties, but do not create a second implementation of either of them. Your class should have just one Name and one Id property.

    Procedures

     

    To Implement the Members of IBackupRestore

    1.    Begin a new Class project in Visual Studio.

    2.    Add a reference to Windows SharePoint Services to your Visual Studio project and add using statements for the Microsoft.SharePoint.Administration and Microsoft.SharePoint.Administration.Backup namespaces to your class file.

    3.    If your class does not derive from SPPersistedObject, implement the IBackupRestore.Name property. This will serve as the name of the content component in the UI of stsadm.exe, the Central Administration application and the UI of any custom backup and restore application. In most cases you implement the property by creating a private field for the name value and implement the public property as a wrapper around the field. For information on possible variant implementations, see the reference topic for the property.

    [C#]

    private String name;

    public String Name

    {

    get {return name;}

    set {name = value;}

    }

    4.    If your class does not derive from SPPersistedObject, implement the IBackupRestore.Id property. In most cases, you implement the property by creating a private field for the name value and implement the public property as a wrapper around the field. For information on possible variant implementations, see the reference topic for the property.

    [C#]

    private Guid id;

    public Guid Id

    {

    get {return id;}

    set {id = value;}

    }

    5.    Implement the IBackupRestore.DiskSizeRequired property. If your class is just a container for some child IBackupRestore classes, the property should return 0. Otherwise, the property should calculate the size of the content. (Include the size of any non-IBackupRestore child objects, but do not include the size of any child IBackupRestore objects. They each have their own IBackupRestore.DiskSizeRequired property and Windows SharePoint Server 3.0 will add those values in automatically.) The following example sums the sizes of all the files whose paths are contained in a collection called FrontEndFilePaths.

    [C#]

    public UInt64 DiskSizeRequired

    {

        get

        {

            UInt64 total = 0;

            List<FileInfo> FrontEndFiles = new List<FileInfo>(NUMBER_OF_FILES_TO_BACK_UP);

           

            foreach (String path in FrontEndFilePaths)

            {

                FileInfo file = new FileInfo(path);

                FrontEndFiles.Add(file);

            }

           

            foreach (FileInfo file in FrontEndFiles)

            {

                total = total + (UInt64)file.Length;

            }

            

            return total;

        }

    }

    6.    Implement the IBackupRestore.CanSelectForBackup property. If users should never be able to backup objects of your class independently of a backup of the parent object, the get accessor should return false. If users should always be able to select any object of your class for independent backup, the get accessor should return true. In either case, the set accessor should be an empty pair of braces "{ }". If some objects of your class can be backed up independently of their parent, but some cannot be, implement the property as a wrapper around a private System.Boolean field.

    7.    Implement the IBackupRestore.CanSelectForRestore property. If users should never be able to restore objects of your custom component class independently of a restoration of the parent object, the get accessor should return false. If users should always be able to select any object of your class for independent restoration, the get accessor should return true. In either case, the set accessor should be an empty pair of braces "{ }". If some objects of your class can be restored independently of their parent, but some cannot be, implement the property as a wrapper around a private System.Boolean field.

    8.    Implement the IBackupRestore.CanRenameOnRestore property. If users should never be able to restore objects of your custom component class to a new location, the get accessor should return false. If users should be able to migrate any object of your class, the get accessor should return true. If objects of your class can sometimes be migrated, but not always, implement the property as a wrapper around a private System.Boolean field.

    9.    Implement the IBackupRestore.AddBackupObjects method.

    a.    Your implementation code should begin by throwing an exception if there is no valid parent to which the component can be added.

    b.    Use the SPBackupRestoreObject.AddChild method to add your component to the tree of objects that the backup or restore operation will process.

    c.    Use the SPBackupRestoreInformation.SetParameter method to specify a type name and description of the component that can be used by the UI of backup/restore applications.

    d.    If the component has child IBackupRestore objects, your implementation should iterate through them and recursively call the IBackupRestore.AddBackupObjects method of each child. 

    e.    See the reference topic for the IBackupRestore.AddBackupObjects method for more ideas about implementations of it.

    The following example code assumes that your content class has a ChildContentCollection of child IBackupRestore objects. If your class has more than one type of child component, you may have separate collections for each type and iterate through each collection.

    [C#]

    public void AddBackupObjects(SPBackupRestoreObject parent)

    {

        if (parent == null)

        {

            throw new ArgumentNullException("parent");

        }

     

        SPBackupRestoreObject self = parent.AddChild(this);

        self.Information.SetParameter(SPBackupRestoreObject.SPTypeName, this.GetType());

        self.Information.SetParameter(SPBackupRestoreObject.SPDescription,

        "Description of custom content component");

     

        foreach (ChildContent child in ChildContentCollection)

        {

            IBackupRestore childIBR = child as IBackupRestore;

            childIBR.AddBackupObjects(self);

        }

    }

    10. Implement the IBackupRestore.OnAbort method. It should always return true. In most cases it should do nothing more, but see the reference topic for IBackupRestore.OnAbort for information about exceptions to this general rule.

    11. Implement the IBackupRestore.OnPrepareBackup method. At a minimum, you should use the SPBackupRestoreInformation.SetParameter method to specify a name for the content object. Beyond that, few generalizations can be made. See the reference topic for IBackupRestore.OnPrepareBackup for more information. The following example shows a minimal implementation of the method, which is often all that is needed.

    [C#]

    public Boolean OnPrepareBackup(Object sender, SPBackupInformation args)

    {

        if (args == null)

        }

            throw new ArgumentNullException("args");

        }

        args.SetParameter(SPBackupRestoreObject.SPName, this.Name);

        return true;

    }

    12. Implement the IBackupRestore.OnBackup method. If your content class has no content outside of any IBackupRestore child objects it may have, your implementation should simply set the SPBackupRestoreInformation.CurrentProgess to a value that approximately represents the percentage of the total backup operation time that is consumed by the IBackupRestore.OnBackup and IBackupRestore.OnPrepareBackup methods. It should then return true as seen in the following example. Do not call the IBackupRestore.OnBackup method of any IBackupRestore child objects.

    [C#]

    public Boolean OnBackup(Object sender, SPBackupInformation args)

    {

        if (args == null)

        {

            throw new ArgumentNullException("args");

        }

        args.CurrentProgress = 50;

        return true;

    }

    If your class does have content outside of any IBackupRestore child objects it may have, your implementation must copy this content to args.SPBackupRestoreInformation.Location and return false if the copy fails. You should include logic to backup any child objects that do not implement IBackupRestore, but you should not explicitly backup any child objects that do implement IBackupRestore. They will be backed up by their own IBackupRestore.OnBackup method, which the runtime will call. You should not call the IBackupRestore.OnBackup methods of the child objects in your own code. The following example shows the overall structure of a substantive implementation of IBackupRestore.OnBackup.

    [C#]

    public Boolean OnBackup(Object sender, SPBackupInformation args)

    {

        if (args == null)

        {

            throw new ArgumentNullException("args");

        }

        args.CurrentProgress = 50;

        Boolean successSignal = true;

     

        // TODO: Implement copying your content to args.Location

        //       If the copy fails, set successSignal to false.

     

        return successSignal;

    }

    13. Implement the IBackupRestore.OnBackupComplete method. At a minimum, your implementation should set SPBackupRestoreInformation.CurrentProgess to 100 percent and return true as shown in the following example. This is typically all that is required. For information about other work your implementation may need to perform, see the reference topic for IBackupRestore.OnBackupComplete.

    [C#]

    public Boolean OnBackupComplete(Object sender, SPBackupInformation args)

    {

        if (args == null)

        {

            throw new ArgumentNullException("args");

        }

        args.CurrentProgress = 100;

        return true;

    }

    14. Implement the IBackupRestore.OnPreRestore method. In most situations, a restoration operation requires no preparation and your implementation of IBackupRestore.OnPreRestore should just return true. For information about other work your implementation may need to perform, see the reference topic for IBackupRestore.OnPreRestore.

    15. Implement the IBackupRestore.OnRestore method.

    ·         If your content class can be migrated, your code should check to see what the restore method is and call SPBackupRestoreInformation.Rename if the method is New.

    ·         If your content class has no content outside of any IBackupRestore child objects it may have, your implementation should simply set the SPBackupRestoreInformation.CurrentProgess to a value that approximately represents the percentage of the total restore operation time that is consumed by the IBackupRestore.OnRestore and the IBackupRestore.OnPreRestore methods. It should then return true as seen in the following example. Do not call the IBackupRestore.OnRestore method of any IBackupRestore child objects.

    [C#]

    public Boolean OnRestore(Object sender, SPRestoreInformation args)

    {

        if (args == null)

        {

            throw new ArgumentNullException("args");

        }

        if (args.RestoreMethod == SPRestoreMethodType.New)

        {

            args.Rename();

        }

        args.CurrentProgress = 50;

        return true;

    }

    ·         If your class does have content outside of any IBackupRestore child objects it may have, your implementation must copy this content to the restoration destination. Return false, if for any reason the copy of content fails.

    The following example shows the overall structure of a substantive implementation of IBackupRestore.OnRestore:

    [C#]

    public Boolean OnRestore(Object sender, SPRestoreInformation args)

    {

        if (args == null)

        {

            throw new ArgumentNullException("args");

        }

        if (args.RestoreMethod == SPRestoreMethodType.New)

        {

            args.Rename();

        }

        args.CurrentProgress = 50;

        Boolean successSignal = true;

     

        // TODO: Implement copying your content to the destination.

        //       If the copy fails, set successSignal to false.

     

        return successSignal;

    }

    16. Implement the IBackupRestore.OnPostRestore method. At a minimum, your implementation should set SPBackupRestoreInformation.CurrentProgess to 100 percent and return true as shown in the following example. This is typically all that is required. For information about other work your implementation may need to perform, see the reference topic for IBackupRestore.OnPostRestore.

    [C#]

    public Boolean OnPostRestore(Object sender, SPRestoreInformation args)

    {

        if (args == null)

        {

            throw new ArgumentNullException("args");

        }

        args.CurrentProgress = 100;

        return true;

    }

     

     

    Add other Members to Your Class As Needed

    17. Add fields, properties, and helper methods as needed to complete your class. As you work, keep these points in mind:

    ·         Use fields and properties to hold child content objects.

    ·         If your class derives from Microsoft.SharePoint.Administration.SPPersistedObject, then the declaration of fields that you want to persist in the configuration database must be preceded with the [Persisted] attribute. However, you can only mark the following types of fields in this way: primitive types such as strings, integers, and GUIDs; other Microsoft.SharePoint.Administration.SPPersistedObject objects or Microsoft.SharePoint.Administration.SPAutoserializingObject objects; or collections of any of the above. For example, the class cannot have a System.IO.FileInfo field marked with the [Persisted] attribute. If the data you would like to persist is not of a persistable class, use a persistable substitute. The sample implementation above of the IBackupRestore.DiskSizeRequired property envisions a class that persists a collection of file names and uses them to create a temporary collection of System.IO.FileInfo objects at runtime.

    ·         If your class can have multiple children of the same type, create a property or field of a collection type or other enumerable type to hold a collection of all children of a given type. This is particularly important if the child type itself implements IBackupRestore, because your implementation of the IBackupRestore.AddBackupObjects method should iterate through such children and call the IBackupRestore.AddBackupObjects method of each child. See the procedure step for implementing the IBackupRestore.AddBackupObjects method above, for more information.

    18. Add constructors to your class to initialize its fields and properties as needed. If the class derives from SPPersistedObject, there must be at least one constructor that names the object and assigns it to a parent. Typically, such a constructor takes at least these two arguments:

    ·         A String argument that will be the name of the content object.

    ·         An SPPersistedObject argument that represents the parent of the content object.

    This constructor must call the base constructor that takes the same two arguments. The following is an example:

    [C#]

    public MyContentComponent(String componentName, SPPersistedObject parent, SomeType someOtherArgument, ... )

                       : base(componentName, parent)

    {

        somePrivateField = someOtherArgument;

        ...

    }

    You must pass Microsoft.SharePoint.Administration.SPFarm.Local as the parent when the content object is the top most object in a tree of custom IBackupRestore objects. If your custom component type is always the top most object, then leave out the SPPersistedObject argument and hard code a reference to SPFarm.Local in the call to the base constructor. The following is an example:

    [C#]

    public MyContentComponent(String componentName, SomeType someOtherArgument, ... )

                       : base(componentName, SPFarm.Local)

    {

        somePrivateField = someOtherArgument;

        ...

    }

    If objects of your class always have the same name, you can leave out the String argument and hard code the name in the call to the base constructor. (If all objects of a given type have the same name, there should never be more than one child of that type for a given parent and; thus, no more than one object of that type on the entire farm if the object is a child of the farm.)

    19. Compile your class project.

    Warning: You must give the assembly a strong name and put the assembly in the General Assembly Cache (GAC).

     

     

    To Create an Object of Your Class and Make it a Child of the Farm

    20. Start a new console application project in Visual Studio.

    21. Add a reference to the DLL of your custom component class to the project.

    22. Add a using statement for Microsoft.SharePoint.Administration.

    23. Add a using statement for the namespace that you used in your custom component class (or just use the same namespace in your console application).

    24. Add to the Main method of your project a call to the constructor of your custom component class. If you created a hierarchy of custom types, call the constructor of the top most class.

    25. If needed, precede the call to the constructor of the component with code that creates parameters for the constructor.

    26. After the call to the constructor of your component, your code should call the component object's SPPersistedObject.Update method. The following is an example of what you should have in the Main method:

    [C#]

    MyContentComponent myContentObject = new MyContentComponent("component name", SPFarm.Local);

    myContentObject.Update();

    27. Compile and run the application.

    28. In the Central Administration application navigate to Operations | Perform a Backup. Your object should appear as child of the farm on the Perform a Backup page.

    Note: There is a sample console application for creating and deleting custom content objects in the Example section below.

     

    Development Advice

    The following tips may be helpful as you develop your custom content classes particularly because you will probably be creating objects and adding them to the farm multiple times as you work.

     

    Points to Keep in Mind

    1.    If you need to delete your object from the configuration database, use SPPersistedObject.Delete.

    2.    An exception is thrown if you call obj.Update() and there is already an object of the same class as obj with the same SPPersistedObject.Name property value and the same parent in the configuration database. There is an overloaded version of SPPersistedObject.Update that may be preferable.

    3.    There is an example console application in the second Example section below that can be used to add or delete your custom objects from the configuration database.

    4.    Run iisreset at the command line after every recompile of your IBackupRestore class. You may need to reboot the server as well.

    5.    The various IBackupRestore.On* methods take either a SPBackupInformation parameter or a SPRestoreInformation parameter. You can use their members for debugging purposes. Particularly helpful is the SPBackupRestoreInformation.Log method.

     

    Example

    The following code implements a custom content component that represents a single Web.config file on a front end server. Replace the TestSite part of the file path in the constructor implementation with a directory name from your test server. The compiled assembly must be strong-named and installed in the GAC.

    In the example following the class implementation, there is the code for a simple console application that will register the component as a child of the farm or delete it from the farm.

    using System;

    using System.IO;

    using System.Collections.Generic;

    using Microsoft.SharePoint.Administration;

    using Microsoft.SharePoint.Administration.Backup;

     

    namespace MyCompany.SharePoint.Administration

    {

        public class CriticalFiles : SPPersistedObject, IBackupRestore

        {

     

            public CriticalFiles() { }

     

            public CriticalFiles(String componentName, SPPersistedObject parent)

                       : base(componentName, parent)

            {

                String pathOfFile = @"C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\LAYOUTS\TestSite\Web.config";

                FrontEndFilePaths.Add(pathOfFile);

            }

     

            [Persisted]

            private const Int32 NUMBER_OF_FILES_TO_BACK_UP = 1;

     

            [Persisted]

            private List<String> FrontEndFilePaths = new List<String>(NUMBER_OF_FILES_TO_BACK_UP);

     

            public Boolean CanSelectForBackup

            {

                get { return true; }

                set { }

            }

     

            public Boolean CanSelectForRestore

            {

                get { return true; }

                set { }

            }

     

            public Boolean CanRenameOnRestore

            {

                get { return false; }

            }

     

            public UInt64 DiskSizeRequired

            {

                get

                {

                    UInt64 total = 0;

                    List<FileInfo> FrontEndFiles = new List<FileInfo>(NUMBER_OF_FILES_TO_BACK_UP);

                   

                    foreach (String path in FrontEndFilePaths)

                    {

                        FileInfo file = new FileInfo(path);

                        FrontEndFiles.Add(file);

                    }

                   

                    foreach (FileInfo file in FrontEndFiles)

                    {

                        total = total + (UInt64)file.Length;

                    }

                   

                    return total;

                }

            }

     

            public void AddBackupObjects(SPBackupRestoreObject parent)

            {

                if (parent == null)

                {

                    throw new ArgumentNullException("parent");

                }

     

                SPBackupRestoreObject self = parent.AddChild(this);

                self.Information.SetParameter(SPBackupRestoreObject.SPTypeName, this.GetType());

                self.Information.SetParameter(SPBackupRestoreObject.SPDescription, "The critical files on all front end servers.");

            }

     

            public Boolean OnAbort(Object sender, SPBackupRestoreInformation args)

            {

                return true;

            }

     

            public Boolean OnPrepareBackup(Object sender, SPBackupInformation args)

            {

                if (args == null)

                {

                    throw new ArgumentNullException("args");

                }

                args.SetParameter(SPBackupRestoreObject.SPName, this.Name);

                return true;

            }

     

            public Boolean OnBackup(Object sender, SPBackupInformation args)

            {

                if (args == null)

                {

                    throw new ArgumentNullException("args");

                }

               

                Boolean successSignal = true;

     

                foreach (String path in FrontEndFilePaths)

                {

                    FileInfo file = new FileInfo(path);

                    try

                    {

                        String mappedFileName = args.GenerateFileMapping(file.Name);

                        file.CopyTo(args.Location + @"\" + mappedFileName, true);

                        args.Log(SPBackupRestoreLogSeverity.Verbose, "Backed up " + file.Name + " in (" + mappedFileName + ")");

                    }

                    catch (Exception e)

                    {

                        args.Log(SPBackupRestoreLogSeverity.Verbose, file.Name + " not backed u " + e.Message);

                        successSignal = false;

                    }

                }

     

                args.CurrentProgress = 50;

                return successSignal;

            }

     

            public Boolean OnBackupComplete(Object sender, SPBackupInformation args)

            {

                if (args == null)

                {

                    throw new ArgumentNullException("args");

                }

                args.CurrentProgress = 100;

                return true;

            }

     

            public Boolean OnPreRestore(Object sender, SPRestoreInformation args)

            {

                if (args == null)

                {

                    throw new ArgumentNullException("args");

                }

                return true;

            }

     

            public Boolean OnRestore(Object sender, SPRestoreInformation args)

            {

                if (args == null)

                {

                    throw new ArgumentNullException("args");

                }

     

                // If the CriticalFiles object was deleted from the farm after it was

                // backed up, restore it to the configuration database.

                CriticalFiles cf = SPFarm.Local.GetChild<CriticalFiles>(this.Name);

                if (cf == null)

                {

                    this.Update();

                    args.Log(SPBackupRestoreLogSeverity.Verbose, this.Name + " added back to configuration database.");

                }

     

                Boolean successSignal = true;

     

                // TODO: The following loop restores files to the local server. If there are

                //       multiple front end servers, your code must iterate through all of

                //       SPFarm.Local.Servers and restore the same files to every server whose

                //       Role property is SPServerRole.WebFrontEnd

     

                foreach (String path in FrontEndFilePaths)

                {

                    FileInfo backupCopy = new FileInfo(path);

                    String mappedFileName = args.ReverseFileMapping(backupCopy.Name);

                    FileInfo file = new FileInfo(args.Location + @"\" + mappedFileName);

     

                    try

                    {

                        file.CopyTo(path, true);

                        args.Log(SPBackupRestoreLogSeverity.Verbose, "Restored " + backupCopy.Name);

                    }

                    catch (Exception e)

                    {

                        args.Log(SPBackupRestoreLogSeverity.Verbose, file.Name + " not restored: " + e.Message);

                        successSignal = false;

                    }

                }

               

                args.CurrentProgress = 50;

                return successSignal;

            }

           

            public Boolean OnPostRestore(Object sender, SPRestoreInformation args)

            {

                if (args == null)

                {

                    throw new ArgumentNullException("args");

                }

     

                args.CurrentProgress = 100;

                return true;

            }

     

        }

    }

    Description

    The following is a console application that will add or delete your content object from the configuration database.

    using System;

    using System.Collections.Generic;

    using System.Text;

    using Microsoft.SharePoint.Administration;

    using Microsoft.SharePoint.Administration.Backup;

     

    namespace MyCompany.SharePoint.Administration

    {

        class Program

        {

            static void Main(string[] args)

            {

                CriticalFiles cf = SPFarm.Local.GetChild<CriticalFiles>("Critical Front End Files");

                if (cf == null)

                {

                    Console.WriteLine("There is no CriticalFiles object in the configuration database.");

                    Console.Write("Enter 'A' to add it. Press Return to do nothing:");

                    String response = Console.ReadLine();

                    if (response == "A")

                    {

                        CriticalFiles myCriticalFiles = new CriticalFiles("Critical Front End Files", SPFarm.Local);

                        myCriticalFiles.Update();

                    }

                }

                else

                {

                    Console.WriteLine("There is a CriticalFiles object in the configuration database.");

                    Console.Write("Enter 'D' to delete it. Press Return to do nothing:");

                    String response = Console.ReadLine();

                    if (response == "D")

                    {

                        cf.Delete();

                    }

                }

            }// end Main

        }// end Program

    }

     

    See Also

    Programming with the Windows SharePoint Services Backup/Restore Object Model

    How to: Programmatically Back Up Content

    How to: Programmatically Restore Content

     

     

  • Microsoft SharePoint Developer Documentation Team Blog

    How to: Programmatically Back Up and Restore a Single Site Collection

    • 2 Comments

    Introduction

    This post describes how to back up and restore individual site collections programmatically.

    Note: Unless explicitly stated otherwise, all classes referred to in this post are in the Microsoft.SharePoint.Administration or Microsoft.SharePoint namespaces (not Microsoft.SharePoint.Administration.Backup).

    Procedures                         

     

    To Back Up or Restore a Site Collection

    1.    Add to your Visual Studio project a reference to Windows SharePoint Services.

    2.    Add using statements for Microsoft.SharePoint and Microsoft.SharePoint.Administration.   

    3.    Add the following lines to obtain a reference to the farm and its collection of services.

    [C#]

    SPFarm myFarm = SPFarm.Local;

    SPServiceCollection myServices = myFarm.Services;

    4.    Obtain a reference to the Web service that publishes the Web application that hosts your site collection by using the service's System.Guid which is the value of its SPWebService.Id property.

    [C#]

    Guid serviceID = new Guid("21d91b29-5c5b-4893-9264-4e9c758618b4");

    SPWebService webPubService = (SPWebService)myServices[serviceID];

    If you do not know the SPWebService.Id of the application publishing Web service, you can iterate through all the services and report their SPWebService.Name, SPWebService.TypeName, and SPWebService.Id. The following is an example:

    [C#]

    foreach (SPService service in myServices)

    {

        if (service is SPWebService)

        {

        Console.WriteLine("Web service name:" + webService.Name);

        Console.WriteLine("Web service type:" + webService.TypeName);

        Console.WriteLine("Web service ID:" + webService.Id);

        Console.WriteLine();

        Console.Readline();

        }

    }

    5.    Obtain a reference to the Web application that hosts your site collection. If you know the URL of the Web application you can obtain a reference with the static SPWebApplication.Lookup method. Alternatively, you can use the application's System.Guid which is the value of its SPWebApplication.Id property. The following code shows the second method.

    [C#]

    SPWebApplicationCollection myApps = webPubService.WebApplications;

    Guid appID = new Guid("10ea4e6f-ae37-4909-b04f-f516c066bc37");

    SPWebApplication myApp = myApps[appID];

    If you do not know the SPWebApplication.Id of the Web application that hosts your site collection, you can iterate through all the Web applications and report their SPWebApplication.Name, SPWebApplication.TypeName, and SPWebApplication.Id. The following is an example:

    [C#]

    foreach (SPWebApplication app in webApps)

    {

        Console.WriteLine("Web application name:" + app.Name);

        Console.WriteLine("Web application type:" + app.TypeName);

        Console.WriteLine("Web application ID:" + app.Id);

        Console.WriteLine();

        Console.Readline();

    }

    6.    Get a reference to the Web application's collection of site collections.

    [C#]

    SPSiteCollection mySiteCols = myApp.Sites;

    7.    To back up a site collection, call the SPSiteCollection.Backup method. As parameters pass the following:

    ·         The full URL of the site collection; that is, the full URL of its Top Level Web site.

    ·         The full path and file name of the file that will hold the compressed content of the site collection.

    ·         True, if the operation should overwrite an existing backup file of the same name; false, if it should not.

    [C#]

    mySiteCols.Backup(@"htt//Server/sites/MySiteCollection", @"\\OtherServer\WSSBackups\SiteCollections\BackupOfMySiteCollection", true);

    8.    To restore a site collection, call the SPSiteCollection.Restore method. It takes the same parameters as the SPSiteCollection.Backup method. The Boolean parameter indicates whether the site collection should be overwritten if it already exists at the specified URL.

    [C#]

    mySiteCols.Restore(@"htt//Server/sites/MySiteCollection", @"\\OtherServer\WSSBackups\SiteCollections\BackupOfMySiteCollection", true);

     

    Example

    The following example shows a simple way to programmatically back up or restore a site collection. You will need to replace all the System.Guid values with actual values from your deployment and replace the placeholder values in the Backup and Restore methods with actual URLs and paths from your deployment.

     

    // Get a reference to the Web application publishing

    // Web service.

    SPFarm myFarm = SPFarm.Local;

    SPServiceCollection myServices = myFarm.Services;

    Guid serviceID = new Guid("21d91b29-5c5b-4893-9264-4e9c758618b4");

    SPWebService webPubService = (SPWebService)myServices[serviceID];

     

    // Get a reference to the Web application that hosts the

    // site collection.

    SPWebApplicationCollection myApps = webPubService.WebApplications;

    Guid appID = new Guid("10ea4e6f-ae37-4909-b04f-f516c066bc37");

    SPWebApplication myApp = myApps[appID];

     

    // As alternative to the preceding three lines, you can use

    // the following when you know the URL of the Web application:

    //     SPWebApplication myApp = SPWebApplication.Lookup(url_of_Web_app)

     

    // Get a reference to the Web application's collection of

    // site collections.

    SPSiteCollection mySiteCols = myApp.Sites;

     

    // Back up a specified site collection.

    mySiteCols.Backup(@"htt//Server/sites/MySiteCollection", @"\\OtherServer\WSSBackups\SiteCollections\BackupOfMySiteCollection", true);

     

    // Restoring the site collection is identical to the preceding

    // code except that the "Restore" is used in place of "Backup".

    //

    // mySiteCols.Restore(@"htt//Server/sites/MySiteCollection", @"\\OtherServer\WSSBackups\SiteCollections\BackupOfMySiteCollection", true);

    Comments

    The Microsoft.SharePoint.SPSite class does not implement Backup.IBackupRestore and the SPSiteCollection.Backup and SPSiteCollection.Restore methods do not use the facilities of the Microsoft.SharePoint.Administration.Backup namespace. This means that records of backups and restorations of site collections are not kept in a history file (spbrtoc.xml) in the backup directory. Similarly, backup and restoration data is not stored in spbackup.xml or sprestore.xml files, neither are these site collection operations logged in spbackup.log or sprestore.log files.

    If you want to do any kind of logging of backups and restorations of site collection operations, you will have to program your own system. Writing to the system-created spbrtoc.xml, spbackup.xml, sprestore.xml, spbackup.log, and sprestore.log files is not supported in Windows SharePoint Services 3.0. Neither is moving them, deleting them, or renaming them. However, you can create files that merge data from the system-created files with data from your site collection backups and restorations.

    See Also

    Programming with the Windows SharePoint Services Backup/Restore Object Model

    How to: Programmatically Back Up Content

    How to: Programmatically Restore Content

    How to: Create a Content Class That Can Be Backed Up and Restored

     

     

  • Microsoft SharePoint Developer Documentation Team Blog

    How to: Programmatically Restore Content

    • 2 Comments

     

    Introduction

    This post explains how to create an application that restores from a backup a content component, including a custom content component, of a Windows SharePoint Services 3.0 farm. The post assumes that you are familiar with my previous posts Overview of Backing Up and Restoring Data in Windows SharePoint Services and Programming with the Windows SharePoint Services Backup/Restore Object Model.

    Note: Unless specified otherwise, all classes referred to in this post are in the Microsoft.SharePoint.Administration.Backup namespace. Classes that you create are in bold pink.

    Procedures

     

    To Restore a Content Component

    1.    Add a reference to Windows SharePoint Services to your Visual Studio project and add using statements for the Microsoft.SharePoint.Administration and Microsoft.SharePoint.Administration.Backup namespaces to you code file.

    2.    Inside the Main method, create a SPRestoreSettings object by using the static SPBackupRestoreSettings.GetRestoreSettings method. For the first parameter pass the path where the backup is stored. For the second parameter pass a string version of one of the values of SPRestoreMethodType.

    [C#]

    SPRestoreSettings settings = SPBackupRestoreSettings.GetRestoreSettings((@"\\Server\WSSBackups", "Overwrite");

    3.    Prompt the user to specify the content component that is to be restored and assign its name to the SPBackupRestoreSettings.IndividualItem property. To see an itemization of the names of the components on your farm that were included in the last full backup and that can be the objects of restore operations, you can either run the command stsadm -o restore -showtree at the server command line. To specify a different full backup package, use the -backupid parameter. Alternatively, you can visit Operations > Perform a Restore in the Central Administration application. To specify the whole farm, use "Farm" as the name. (Setting the property to null also selects the whole farm for backup assuming that you use SPBackupRestoreSettings.IndividualItem in all subsequent code to identify by name the component to be restored, as you should. For an example, see the use of the SPBackupRestoreConsole.FindItems method in step 9.)

    [C#]

    Console.Write("Enter name of component to restore (default is whole farm):");

    settings.IndividualItem = Console.ReadLine();

    4.    If you want to restore from a backup other than the most recent, identify the backup package by assigning its GUID to the SPRestoreSettings.BackupId property. A record of each backup operation for a particular backup location is stored in spbrtoc.xml in the root of the location. Each backup and restore operation is represented in the file by an <SPHistoryObject> element. If the operation is a backup, the <IsBackup> child of the <SPHistoryObject> element is "True". The <SPId> element of the <SPHistoryObject> element contains the GUID of the backup.

    Note: To programmatically obtain the list of all backup and restore operations, use the SPBackupRestoreConsole.GetHistory method. This method returns an SPBackupRestoreHistoryList object that contains SPBackupRestoreHistoryObject objects. Each of the latter represents an operation and holds its GUID in the SPBackupRestoreHistoryObject.SelfId property. 

    [C#]

    settings.BackupId = new Guid("GUID");

    5.    Optionally, set one or both of the SPBackupRestoreSettings.IsVerbose and SPBackupRestoreSettings.UpdateProgress properties. (For details about these properties, see the reference topics for them.)

    [C#]

    settings.IsVerbose = true;

    settings.UpdateProgress = 10;

    6.    If necessary, set the SPRestoreSettings.FarmAdminLoginName and SPRestoreSettings.FarmAdminLoginPassword properties.

    [C#]

    settings.FarmAdminLoginName = "Bob";

    settings.FarmAdminPassword = "7*j2U";

    7.    Create the restore operation with the SPBackupRestoreConsole.CreateBackupRestore method. (A history object for the operation is also created.)

    [C#]

    Guid restore = SPBackupRestoreConsole.CreateBackupRestore(settings);

    8.    If your UI has users type a component name instead of pick one from a list, you must make sure that the name entered matches exactly one component. Add the following line to your Main method.

    [C#]

    SPBackupRestoreObject node = EnsureUniqueValidComponentName(settings, ref restore);

    9.    Add the following declaration and implementation of your EnsureUniqueValidComponentName method. Use the SPBackupRestoreConsole.FindItems method to retrieve a collection of content objects whose names match the user-entered name. If there is no match, prompt the user to try again. If there is more than one, prompt the user to be more specific. If the component name that the user entered is valid and not ambiguous, get a reference to the SPBackupRestoreObject object that represents the component that the user wants to restore.

    [C#]

    private static SPBackupRestoreObject EnsureUniqueValidComponentName(SPBackupRestoreSettings settings, ref Guid operationGUID)

    {

        SPBackupRestoreObjectCollection list = SPBackupRestoreConsole.FindItems(operationGUID, settings.IndividualItem);

        SPBackupRestoreObject component = null;

     

        if (list.Count <= 0)

        {

            Console.WriteLine("There is no component with that name. Run again with a new name.");

            Console.WriteLine("Press Enter to continue.");

            Console.ReadLine();

        }

        else if (list.Count > 1)  // The component name specified is ambiguous. Prompt user to be more specific.

        {

            Console.WriteLine("More than one component matches the name you entered.");

            Console.WriteLine("Run again with one of the following:");

            for (int i = 0; i < list.Count; i++)

            {

                Console.WriteLine("\t{0}", list[i].ToString());

            }

            Console.WriteLine("Press Enter to continue.");

            Console.ReadLine();

        }

        else

        {

            component = list[0];

        }

     

        return component;

     

    }

    10. In the Main method, create a conditional structure that will run only if your EnsureUniqueValidComponentName method has returned a valid node.

    [C#]

    if (node != null)

    {

        // TODO: Set the restore operation as the active operation

        // and run it.

    }

    11. Replace the "TODO" line in the previous step with the following code. This sets the operation to be the active operation with the SPBackupRestoreConsole.SetActive method and tests to verify that it succeeded. If it fails, which it will if another backup or restore operation is already underway, report an error to the UI of your application.

    [C#]

    if (SPBackupRestoreConsole.SetActive(restore) == true)

    {

        // TODO: Run the operation. See next step.

    }

    else

    {

        // Report through your UI that another backup

        // or restore operation is underway.

        Console.WriteLine("Another backup or restore operation is already underway. Try again when it ends.");

    }

    12. In the code branch that runs if the SPBackupRestoreConsole.SetActive call succeeds, run the operation with the SPBackupRestoreConsole.Run method. Test that the operation succeeds. If it fails, report the operation's failure message to your UI. The following code replaces the "TODO" line in the previous step.

    [C#]

    if (SPBackupRestoreConsole.Run(restore, node) == false)

    {

        // Report "error" through your UI.

        String error = SPBackupRestoreConsole.Get(restore).FailureMessage;

        Console.WriteLine(error);

    }

    13. Clean up the restore with the SPBackupRestoreConsole.Remove method. Add the following code just before the closing brace you inserted in step 10.

    [C#]

    // Clean up the operation.

    SPBackupRestoreConsole.Remove(restore);

     

    Console.WriteLine("Restore attempt complete. Press Enter to continue.");

    Console.ReadLine();

     

     

     

    Example

    The following code shows how to program a restoration of a content component. Replace the placeholder \\Server\WSSBackups with the path of your backup location. The runtime will automatically find the most recent backup at that location.

     

    using System;

    using Microsoft.SharePoint.Administration;

    using Microsoft.SharePoint.Administration.Backup;

     

    namespace MyCompany.SharePoint.Administration.Backup

    {

        class Restore

        {

            static void Main(string[] args)

            {

                // Create the restore settings.

                SPRestoreSettings settings = SPBackupRestoreSettings.GetRestoreSettings(@"\\Server\WSSBackups", "Overwrite");

     

                // Identify the content component to restore.

                Console.Write("Enter name of component to restore (default is whole farm):");

                settings.IndividualItem = Console.ReadLine();

               

                // Set optional operation parameters.

                settings.IsVerbose = true;

                settings.UpdateProgress = 10;

               

                // Create the restore operation and return its ID.

                Guid restore = SPBackupRestoreConsole.CreateBackupRestore(settings);

     

                SPBackupRestoreObject node = EnsureUniqueValidComponentName(settings, ref restore);

     

                if (node != null)

                {

                    // Set the restore as the active job and run it.

                    if (SPBackupRestoreConsole.SetActive(restore) == true)

                    {

                        if (SPBackupRestoreConsole.Run(restore, node) == false)

                        {

                            // Report "error" through your UI.

                            String error = SPBackupRestoreConsole.Get(restore).FailureMessage;

                            Console.WriteLine(error);

                        }

                    }

                    else

                    {

                        // Report through your UI that another backup

                        // or restore operation is underway.

                        Console.WriteLine("Another backup or restore operation is already underway. Try again when it ends.");

                    }

     

                    // Clean up the operation.

                    SPBackupRestoreConsole.Remove(restore);

     

                    Console.WriteLine("Restore attempt complete. Press Enter to continue.");

                    Console.ReadLine();

                }

            }// end Main

     

            private static SPBackupRestoreObject EnsureUniqueValidComponentName(SPBackupRestoreSettings settings, ref Guid operationGUID)

            {

                SPBackupRestoreObjectCollection list = SPBackupRestoreConsole.FindItems(operationGUID, settings.IndividualItem);

                SPBackupRestoreObject component = null;

     

                if (list.Count <= 0)

                {

                    Console.WriteLine("There is no component with that name. Run again with a new name.");

                    Console.WriteLine("Press Enter to continue.");

                    Console.ReadLine();

                }

                else if (list.Count > 1)  // The component name specified is ambiguous. Prompt user to be more specific.

                {

                    Console.WriteLine("More than one component matches the name you entered.");

                    Console.WriteLine("Run again with one of the following:");

                    for (int i = 0; i < list.Count; i++)

                    {

                        Console.WriteLine("\t{0}", list[i].ToString());

                    }

                    Console.WriteLine("Press Enter to continue.");

                    Console.ReadLine();

                }

                else

                {

                    component = list[0];

                }

     

                return component;

     

            }// end EnsureUniqueValidComponentName

     

        }// end Restore class

    }// end namespace

     See Also

    Programming with the Windows SharePoint Services Backup/Restore Object Model

    How to: Programmatically Back Up Content

    How to: Create a Content Class That Can Be Backed Up and Restored

     

     

     

  • Microsoft SharePoint Developer Documentation Team Blog

    How to: Programmatically Back Up Content

    • 2 Comments

    Introduction

    This post explains how to program a backup of a content component, including custom components, in a Windows SharePoint Services 3.0 farm. The post assumes that you are familiar with my previous posts Overview of Backing Up and Restoring Data in Windows SharePoint Services and Programming with the Windows SharePoint Services Backup/Restore Object Model.

    Note: Unless specified otherwise, all classes referred to in this post are in the Microsoft.SharePoint.Administration.Backup namespace. Classes that you create are in bold pink.

    Procedures

     

    To Back Up a Content Component

    1.    Add a reference to Windows SharePoint Services to your Visual Studio project and add using statements for the Microsoft.SharePoint.Administration and Microsoft.SharePoint.Administration.Backup namespaces to you code file.

    2.    Inside the Main method, prompt the user to specify where the backup should be stored.

    [C#]

    Console.Write("Enter full UNC path to the directory where the backup will be stored:");

    String backupLocation = Console.ReadLine();

    3.    Inside the Main method, create a SPBackupSettings object by using the static SPBackupRestoreSettings.GetBackupSettings method. For the first parameter pass the path where the backup should be stored. For the second parameter pass a string version of one of the values of SPBackupMethodType.

    [C#]

    SPBackupSettings settings = SPBackupRestoreSettings.GetBackupSettings(backupLocation, "Full");

    4.    Prompt the user to specify the content component to back up and assign its name to the SPBackupRestoreSettings.IndividualItem property. To see an itemization of the names of the components on your farm that can be the objects of backup operations, you can either run the command stsadm -o backup -showtree at the server command line or visit Operations > Perform a Backup in the Central Administration application. To specify the whole farm, use "Farm" as the name. (Setting the property to null also selects the whole farm for backup assuming that you use SPBackupRestoreSettings.IndividualItem in all subsequent code to identify by name the component to be backed up, as you should. For an example, see the use of the SPBackupRestoreConsole.FindItems method in step 8.)

    [C#]

    Console.Write("Enter name of component to backup (default is whole farm):");

    settings.IndividualItem = Console.ReadLine();

    5.    Optionally, set one or more of the SPBackupRestoreSettings.IsVerbose, SPBackupRestoreSettings.UpdateProgress, and SPBackupSettings.BackupTheads properties. (For details about these properties, see the reference topics for them.)

    [C#]

    settings.IsVerbose = true;

    settings.UpdateProgress = 10;

    settings.BackupThreads = 2;

    6.    Create the backup operation with the SPBackupRestoreConsole.CreateBackupRestore method. (A history object for the operation is also created. For more information, see SPBackupRestoreHistoryObject and SPBackupRestoreHistoryList.)

    [C#]

    Guid backup = SPBackupRestoreConsole.CreateBackupRestore(settings);

    7.    If your UI has users type a component name instead of pick one from a list, you must make sure that the name entered matches exactly one component. Add the following line to your Main method.

    [C#]

    SPBackupRestoreObject node = EnsureUniqueValidComponentName(settings, ref backup);

    8.    Add the following declaration and implementation of your EnsureUniqueValidComponentName method. Use the SPBackupRestoreConsole.FindItems method to retrieve a collection of content objects whose names match the user-entered name. If there is no match, prompt the user to try again. If there is more than one, prompt the user to be more specific. If the component name that the user entered is valid and not ambiguous, get a reference to the SPBackupRestoreObject object that represents the component that the user wants to restore.

    [C#]

    private static SPBackupRestoreObject EnsureUniqueValidComponentName(SPBackupRestoreSettings settings, ref Guid operationGUID)

    {

        SPBackupRestoreObjectCollection list = SPBackupRestoreConsole.FindItems(operationGUID, settings.IndividualItem);

        SPBackupRestoreObject component = null;

     

        if (list.Count <= 0)

        {

            Console.WriteLine("There is no component with that name. Run again with a new name.");

            Console.WriteLine("Press Enter to continue.");

            Console.ReadLine();

        }

        else if (list.Count > 1)  // The component name specified is ambiguous. Prompt user to be more specific.

        {

            Console.WriteLine("More than one component matches the name you entered.");

            Console.WriteLine("Run again with one of the following:");

            for (int i = 0; i < list.Count; i++)

            {

                Console.WriteLine("\t{0}", list[i].ToString());

            }

            Console.WriteLine("Press Enter to continue.");

            Console.ReadLine();

        }

        else

        {

            component = list[0];

        }

     

        return component;

     

    }

    9.    In the Main method, create a Boolean flag that will signal whether there is sufficient space for the backup, and a conditional structure that will run only if your EnsureUniqueValidComponentName method has returned a valid node.

    [C#]

    Boolean targetHasEnoughSpace = false;

    if (node != null)

    {

        targetHasEnoughSpace = EnsureEnoughDiskSpace(backupLocation, backup, node);

    }

    10. Add the following declaration and implementation of your EnsureEnoughDiskSpace method. Use the SPBackupRestoreConsole.DiskSizeRequired method to obtain the amount of space that is needed, and the SPBackupRestoreConsole.DiskSize method to determine how much free space is available on the destination disk.

    [C#]

    private static Boolean EnsureEnoughDiskSpace(String location, Guid backup, SPBackupRestoreObject node)

    {

        UInt64 backupSize = SPBackupRestoreConsole.DiskSizeRequired(backup, node);

        UInt64 diskFreeSize = 0;

        UInt64 diskSize = 0;

        Boolean hasEnoughSpace = true;

     

        try

        {

            SPBackupRestoreConsole.DiskSize(location, out diskFreeSize, out diskSize);

        }

        catch

        {

            diskFreeSize = diskSize = UInt64.MaxValue;

        }

     

        if (backupSize > diskFreeSize)

        {

            // Report through your UI that there is not enough disk space.

            Console.WriteLine("{0} bytes of space is needed but the disk hosting {1} has only {2}.", backupSize, location, diskFreeSize);

            Console.WriteLine("Please try again with a different backup location or a smaller component.");

            hasEnoughSpace = false;

        }

        else if (backupSize == UInt64.MaxValue || diskFreeSize == 0)

        {

            // Report through your UI that it cannot be determined whether there is enough disk space.

            Console.WriteLine("Cannot determine if that location has enough disk space.");

            Console.WriteLine("Please try again with a different backup location or a smaller component.");

            hasEnoughSpace = false;

        }

        return hasEnoughSpace;

     

    }

    11. In the Main method, create a conditional structure that will run only if your EnsureEnoughDiskSpace returns true.

    [C#]

    if (targetHasEnoughSpace)

    {

        // TODO: Set the backup operation as the active operation

        // and run it.

    }

    12. Replace the "TODO" line in the previous step with the following code. This sets the operation to be the active operation with the SPBackupRestoreConsole.SetActive method and tests to verify that it succeeded. If it fails, which it will if another backup or restore operation is already underway, report an error to the UI of your application.

    [C#]

    if (SPBackupRestoreConsole.SetActive(backup) == true)

    {

        // TODO: Run the operation. See next step.

    }

    else

    {

        // Report through your UI that another backup

        // or restore operation is underway.

        Console.WriteLine("Another backup or restore operation is already underway. Try again when it ends.");

    }

    13. In the code branch that runs if the SPBackupRestoreConsole.SetActive call succeeds, run the operation with the SPBackupRestoreConsole.Run method. Test that the operation succeeds. If it fails, report the operation's failure message to your UI. The following code replaces the "TODO" line in the previous step.

    [C#]

    if (SPBackupRestoreConsole.Run(backup, node) == false)

    {

        // Report "error" through your UI.

        String error = SPBackupRestoreConsole.Get(backup).FailureMessage;

        Console.WriteLine(error);

    }

    14. Clean up the restore with the SPBackupRestoreConsole.Remove method. Add the following code just before the closing brace you inserted in step 11.

    [C#]

    // Clean up the operation.

    SPBackupRestoreConsole.Remove(backup);

     

    Console.WriteLine("Backup attempt complete. Press Enter to continue.");

    Console.ReadLine();

     

     

     

    Example

    The following code shows how to program a backup of a content component.

     

    using System;

    using Microsoft.SharePoint.Administration;

    using Microsoft.SharePoint.Administration.Backup;

     

    namespace MyCompany.SharePoint.Administration.Backup

    {

        class Backup

        {

            static void Main(string[] args)

            {

                // Identify the location for the backup storage.

                Console.Write("Enter full UNC path to the directory where the backup will be stored:");

                String backupLocation = Console.ReadLine();

               

                // Create the backup settings.

                SPBackupSettings settings = SPBackupRestoreSettings.GetBackupSettings(backupLocation, "Full");

     

                // Identify the content component to backup.

                Console.Write("Enter name of component to backup (default is whole farm):");

                settings.IndividualItem = Console.ReadLine();

               

                // Set optional operation parameters.

                settings.IsVerbose = true;

                settings.UpdateProgress = 10;

                settings.BackupThreads = 10;

     

                // Create the backup operation and return its ID.

                Guid backup = SPBackupRestoreConsole.CreateBackupRestore(settings);

     

                // Ensure that user has identified a valid and unique component.

                SPBackupRestoreObject node = EnsureUniqueValidComponentName(settings, ref backup);

     

                // Ensure that there is enough space.

                Boolean targetHasEnoughSpace = false;

                if (node != null)

                {

                    targetHasEnoughSpace = EnsureEnoughDiskSpace(backupLocation, backup, node);

                }

     

                // If there is enough space, attempt to run the backup.

                if (targetHasEnoughSpace)

                {

                    // Set the backup as the active job and run it.

                    if (SPBackupRestoreConsole.SetActive(backup) == true)

                    {

                        if (SPBackupRestoreConsole.Run(backup, node) == false)

                        {

                            // Report "error" through your UI.

                            String error = SPBackupRestoreConsole.Get(backup).FailureMessage;

                            Console.WriteLine(error);

                        }

                    }

                    else

                    {

                        // Report through your UI that another backup

                        // or restore operation is underway.

                        Console.WriteLine("Another backup or restore operation is already underway. Try again when it ends.");

                    }

     

                    // Clean up the operation.

                    SPBackupRestoreConsole.Remove(backup);

     

                    Console.WriteLine("Backup attempt complete. Press Enter to continue.");

                    Console.ReadLine();

                }

            }// end Main

     

            private static SPBackupRestoreObject EnsureUniqueValidComponentName(SPBackupRestoreSettings settings, ref Guid operationGUID)

            {

                SPBackupRestoreObjectCollection list = SPBackupRestoreConsole.FindItems(operationGUID, settings.IndividualItem);

                SPBackupRestoreObject component = null;

     

                if (list.Count <= 0)

                {

                    Console.WriteLine("There is no component with that name. Run again with a new name.");

                    Console.WriteLine("Press Enter to continue.");

                    Console.ReadLine();

                }

                else if (list.Count > 1)  // The component name specified is ambiguous. Prompt user to be more specific.

                {

                    Console.WriteLine("More than one component matches the name you entered.");

                    Console.WriteLine("Run again with one of the following:");

                    for (int i = 0; i < list.Count; i++)

                    {

                        Console.WriteLine("\t{0}", list[i].ToString());

                    }

                    Console.WriteLine("Press Enter to continue.");

                    Console.ReadLine();

                }

                else

                {

                    component = list[0];

                }

     

                return component;

     

            }// end EnsureUniqueValidComponentName

     

            private static Boolean EnsureEnoughDiskSpace(String location, Guid backup, SPBackupRestoreObject node)

            {

                UInt64 backupSize = SPBackupRestoreConsole.DiskSizeRequired(backup, node);

                UInt64 diskFreeSize = 0;

                UInt64 diskSize = 0;

                Boolean hasEnoughSpace = true;

     

                try

                {

                    SPBackupRestoreConsole.DiskSize(location, out diskFreeSize, out diskSize);

                }

                catch

                {

                    diskFreeSize = diskSize = UInt64.MaxValue;

                }

     

                if (backupSize > diskFreeSize)

                {

                    // Report through your UI that there is not enough disk space.

                    Console.WriteLine("{0} bytes of space is needed but the disk hosting {1} has only {2}.", backupSize, location, diskFreeSize);

                    Console.WriteLine("Please try again with a different backup location or a smaller component.");

                    hasEnoughSpace = false;

                }

                else if (backupSize == UInt64.MaxValue || diskFreeSize == 0)

                {

                    // Report through your UI that it cannot be determined whether there is enough disk space.

                    Console.WriteLine("Cannot determine if that location has enough disk space.");

                    Console.WriteLine("Please try again with a different backup location or a smaller component.");

                    hasEnoughSpace = false;

                }

                return hasEnoughSpace;

     

            }// end EnsureEnoughDiskSpace

     

        }// end Backup class

    }// end namespace

    See Also

    Programming with the Windows SharePoint Services Backup/Restore Object Model

    How to: Programmatically Restore Content

    How to: Create a Content Class That Can Be Backed Up and Restored

     

     

  • Microsoft SharePoint Developer Documentation Team Blog

    Programming with the Windows SharePoint Services Backup/Restore Object Model

    • 1 Comments

    Introduction

    This post describes the architecture of the backup and restore object model in Windows SharePoint Services 3.0 and provides some advice about how to program against it. Your backup application can be an independent application or an extension of the stsadm.exe command-line tool. For more information about how to extend stsadm, see How to: Extend the STSADM Utility.

    Note: All classes in this post are in the Microsoft.SharePoint.Administration.Backup namespace unless specified otherwise.

    The Backup and Restore Object Model

    At the top of the object model is the SPBackupRestoreConsole class. (See , in Figure 1.) It provides an umbrella operations manager responsible for queuing backup and restore jobs, starting jobs, and persisting a history of jobs in the form of xml files. An object of this class is "just underneath the surface" of the UI of a backup application. Its members are mainly static methods and properties that provide hooks for the UI of the backup application. Both the Central Administration application and the stsadm.exe command-line tool use these hooks.

    There is always just one object of this class and it is created the first time one of its members is called. It remains in memory until the next time Internet Information Server (IIS) is reset; however, its memory footprint is small.

    Figure 1: The primary objects in the backup/restore hierarchy.

    Primary Objects in WSS Backup Restore OM 

     

    Each particular backup or restore operation is represented by an object of the class SPBackupRestoreConsoleObject that is created by the SPBackupRestoreConsole.CreateBackupRestore method of the console object. (See , in Figure 1, the queued backup and restore operations.) The properties of one of these lightweight objects hold information about the operation such as whether it is a backup or a restore, the location of the backup files, the backup or restore method, the current stage of the operation, and the tree of content components that his being backed up or restored. These objects also have an SPBackupRestoreConsoleObject.Id property of type System.Guid that serves as a handle for the object that can be passed to the methods of SPBackupRestoreConsole. For example, SPBackupRestoreConsole.Run is passed the ID of the operation (that is; the SPBackupRestoreConsoleObject object) that the console is to run next. Finally, each SPBackupRestoreConsoleObject has a SPBackupRestoreConsoleObject.Settings property that holds a persisting object that contains a reusable pattern of backup (or restore) settings. This object also identifies the content component that the operation is to back up or restore. The settings objects are discussed in more detail near the end of this section.

    While the SPBackupRestoreConsoleObject objects represent operations, the content components themselves are represented by SPBackupRestoreObject objects. (See , in Figure 1.) These objects can be nested with the SPBackupRestoreObject.Children property. Therefore, each one represents a tree of one or more content components. For example, a Web application would be represented by a by SPBackupRestoreObject object that would have each of the Web application's content databases as child SPBackupRestoreObject objects. The tree of components that are the subject a particular backup or restore operation is internally linked to the SPBackupRestoreConsoleObject object that represents the operation. You can get a reference to the topmost SPBackupRestoreObject object in the tree by passing the ID of the SPBackupRestoreConsoleObject object to the SPBackupRestoreConsole.GetRoot method.

    A SPBackupRestoreObject object is a container for two critical types of objects:

    ·         In its SPBackupRestoreObject.Information property the SPBackupRestoreObject object holds either a SPBackupInformation or a SPRestoreInformation object. These kinds of objects hold information about how to back up or restore a particular component and methods that can be called internally by SPBackupRestoreConsoleObject and SPBackupRestoreObject as part of an operation. More specifically, these classes hold methods and properties whose implementation should never change regardless of what kind of content component is being represented. Hence, they are sealed and deriving a new class from their parent, SPBackupRestoreInformation, is not supported.

    ·         In its SPBackupRestoreObject.IBackupRestore property the SPBackupRestoreObject object holds an object that implements the IBackupRestore interface (and might also inherit from Microsoft.SharePoint.Administration.SPPersistedObject). (See , in Figure 1.) Implementation of the latter interface turns an object into something that can potentially be backed up and restored. Like an SPBackupRestoreInformation object, an IBackupRestore object contains members that provide information and methods needed for backups and restorations. But the members of IBackupRestore must be given different implementations depending on the kind of content component that is being represented. Most importantly, the implementation includes event handlers for an operation's events, such as IBackupRestore.OnBackup and IBackupRestore.OnRestore.

    Besides acting as a container, SPBackupRestoreObject is a helper class that provides easier interaction between the operation objects (SPBackupRestoreConsoleObject), on the one hand, and the component information objects (SPBackupRestoreInformation and IBackupRestore), on the other.

    The final major classes are SPBackupSettings and SPRestoreSettings. An object of one of these two types is passed to the SPBackupRestoreConsole.CreateBackupRestore method when an operation is created. (See , in Figure 1.) Each of these objects holds settings for use in operations; most importantly, they identify, in their SPBackupRestoreSettings.IndividualItem property, the content component that is the subject of the backup or restore operation. (See , in Figure 1.)

    Programming Advice

    Ways of Customization

    Most of the critical classes in the backup restore object model are sealed (NotInheritable in Visual Basic). Moreover, although the following classes are not sealed, deriving from them is not supported. In each case, you must use the existing derived classes:

    ·         SPBackupRestoreInformation. (Existing derived classes: SPBackupInformation and SPRestoreInformation.)

    ·         SPBackupRestoreSettings. (Existing derived classes: SPBackupSettings and SPRestoreSettings.)

    Accordingly, there are just two primary points of customization:

    ·         You can create your own high level application, and UI, that will use the static methods of the operations console — an SPBackupRestoreConsole object — to manage and run backup and restore jobs. For more information about how to do this see How to: Programmatically Back Up Content and How to: Programmatically Restore Content.

    ·         You can create a class that implements the IBackupRestore interface and might or might not also derive the Microsoft.SharePoint.Administration.SPPersistedObject class. For more information about how to create a custom content class, see How to: Create a Content Class That Can Be Backed Up and Restored.

    Permissions

    Code that backs up content must run in the user context of a farm administrator. Code that restores must run in the context of a user who is both a farm administrator and an administrator on all the front-end servers. The user should also have read and write permissions for the backup location.

    Failure Logging

    If a backup or restore operation fails, details about the failure will be logged in spbackup.log or sprestore.log in the backup location.

    Backups and Restores of Site Collections

    Aside from custom content types that you create by implementing IBackupRestore, the smallest content object that you can back up and restore with the classes in the Microsoft.SharePoint.Administration.Backup namespace is a content database. To programmatically backup or restore individual site collections, use Microsoft.SharePoint.Administration.SPSiteCollection.Backup(System.String,System.String,System.Boolean) and Microsoft.SharePoint.Administration.SPSiteCollection.Restore(System.String,System.String,System.Boolean). For more information on backing up and restoring site collections, see How to: Programmatically Backup and Restore a Single Site Collection.

     

  • Microsoft SharePoint Developer Documentation Team Blog

    Extending the Connect To menu item

    • 2 Comments

    Introduction

    In my last two posts I discussed how third party clients can most efficiently synchronize with Windows SharePoint Services 3.0 In this article I look into extending the “Connect To…” menu item. The “Connect To…” menu item is extensible so that any client can make use of it.

    Extending the “Connect To” menu item

    Client applications must do two things in order for the Connect To menu item to be displayed:

    1.      Register the stssync:// protocol handler

    2.      Install an ActiveX control that returns the application name and an icon filename

     

    More information about registering protocol handlers is available from http://msdn.microsoft.com/workshop/networking/pluggable/overview/appendix_a.asp.

    The ActiveX control must have a ProgID of SharePoint.Stssynchandler.3 and implement the following methods:

     

    HRESULT GetStssyncAppNameForType([in] BSTR pbstrType,  [out, retval] BSTR *pbstrAppName);

    HRESULT GetStssyncIconName([out, retval] BSTR *pbstrIconName);

     

    Before displaying the menu item, SharePoint calls the GetStssyncAppNameForType() method in the ActiveX control and passes in the current list’s sync type.  Each list has a default sync type (accessed in the object model at SPList.SyncType) based on its base type, base template, and whether it allows content types. This type can be overridden as an attribute of the list template definition in a feature.

    Typically, the ActiveX control checks the sync type against a list of supported types and returns the name of the application to display in the menu item, or null if the type is not supported – in which case the menu item is not displayed.

     

    If a non-null application name is returned, SharePoint then calls the control’s GetStssyncIconName() method to get the filename of an icon to display in the menu item.  The filename returned is used in the context menu for document library folders, while the “menu” prefix is added to the filename to get the image used in the toolbar menu item.  Thus, clients should install two images in the images path of each SharePoint web front end – foo.gif and menufoo.gif.

     

    If the browser does not support Active X, (Windows Internet Explorer 5 and later), we display the “Connect To…” menu with a default icon and assume that the stssync protocol is supported.

     

    When the button is clicked, JavaScript redirects the browser to an stssync:// URL with the right context parameters.  The URL is formatted as follows:

     

    stssync://sts/?ver=1.1&type=Type&cmd=add-folder&base-url=WebUrl&list-url=ListUrl&guid=ListId&site-name=SiteName&list-name=ListName

     

    Parameter Descriptions

    Type

    The sync type for this list

    WebUrl

    an absolute, encoded URL to the web on which the list is found

    ViewUrl

    a web-relative, encoded URL (starting with /) to the list’s default view page

    ListUrl

    a web-relative, encoded URL (starting and ending with /) to the list

    ListId

    the list’s GUID

    SiteName

    the title of the web on which the list is found, up to 20 characters long

    ListName

    the title of the list, up to 20 characters long

     

    Document libraries may add two parameters to the end of the stssync:// URL when syncing a folder:

     

    &folder-url=FolderUrl&folder-id=FolderId

     

    Type

    The sync type for this list

    FolderUrl

    a web-relative, unencoded URL (starting with /) to the context folder

    FolderId

    the item ID (an integer) of the context folder

     

    Acknowledgements

    Once again, I would like to acknowledge Matt Swann (Microsoft Corporation) and Bill Snead (Microsoft Corporation) for their gracious help in technical reviews of this material.

     See Also

    http://blogs.msdn.com/sharepointdeveloperdocs/archive/2008/01/21/synchronizing-with-windows-sharepoint-services-part-1.aspx

    http://blogs.msdn.com/sharepointdeveloperdocs/archive/2008/01/22/synchronizing-with-windows-sharepoint-services-part-2.aspx

Page 1 of 1 (6 items)