Partilhar via


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

Applies to: SharePoint Foundation 2010

If you have a custom content component that you want to be included in Microsoft SharePoint Foundation backups and restores, you must represent the component with a class that implements the IBackupRestore interface. This topic explains how to do that. There is a complete example following the procedures. (If your component is a Web service that implements the Service Application Framework, there is an alternative to implementing IBackupRestore. For more information, see Backing Up and Restoring in the Service Application Framework.)

Note

If your component is a database hosted in either the Enterprise or Developer editions of Microsoft SQL Server that you want to be restorable from a snapshot through the SharePoint Foundation UI or object model, your class must also implement the IDatabaseSnapshotRestore interface. For information on how to implement that interface, see How to: Create a Database Class That Can Be Restored From a Snapshot.

If your component consists of configuration information that farm administrators should have the option of including in configuration-only backups and restorations, review the topic How to: Create a Class That Is Included in Configuration-Only Backups and Restorations and carry out the procedure in it, if appropriate.

Your class does not have to derive from SPPersistedObject but if your content is a database, we recommend that you derive your class from either SPDatabase or from 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 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:

[GUID("9573FAD9-ED89-45E8-BD8B-6A5034E03895")]
public class MyClass : SPPersistedObject, IBackupRestore
<System.Runtime.InteropServices.Guid("9573FAD9-ED89-45E8-BD8B-6A5034E03895")>
Public Class [MyClass]
    Inherits SPPersistedObject
    Implements IBackupRestore

End Class

Note

Any custom class that inherits directly or indirectly from SPPersistedObject must have a GuidAttribute applied to its declaration.

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:

UInt64 IBackupRestore.DiskSizeRequired { ... }
Public ReadOnly Property DiskSizeRequired As UInt64 Implements IBackupRestore.DiskSizeRequired
    Get
        ... 
    End Get
End Property

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:

public override UInt64 DiskSizeRequired { ... }
Public Overrides ReadOnly Property DiskSizeRequired() As UInt64
    Get
        ...
    End Get
End Property

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 SPPersistedObject.Id and SPPersistedObject.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.

To Implement the Members of IBackupRestore

  1. Begin a new Class project in Visual Studio.

  2. Add a reference to Microsoft.SharePoint 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 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.

    private String name;
    public String Name
    {
    get {return name;}
    set {name = value;}
    }
    
     Private _name As String
    Public Property Name() As String
        Get
            Return _name
        End Get
        Set(ByVal value As String)
            _name = value
        End Set
    End Property
    
  4. If your class does not derive from SPPersistedObject, implement the 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.

    private Guid id;
    public Guid Id
    {
    get {return id;}
    set {id = value;}
    }
    
    Private _Id As Guid
    Public Property Id() As Guid
        Get
            Return _Id 
        End Get
        Set(ByVal value As Guid)
            _Id = value
        End Set
    End Property
    
  5. Implement the 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 DiskSizeRequired property and SharePoint Foundation 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.

    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 ReadOnly Property DiskSizeRequired() As UInt64 Implements IBackupRestore.DiskSizeRequired
        Get
            Dim total As UInt64 = 0
            Dim FrontEndFiles As New List(Of FileInfo)(NUMBER_OF_FILES_TO_BACK_UP)
    
            For Each path As String In FrontEndFilePaths
                Dim file As New FileInfo(path)
                FrontEndFiles.Add(file)
            Next path
    
            For Each file As FileInfo In FrontEndFiles
                total = total + CULng(file.Length)
            Next file
    
            Return total
        End Get
    End Property
    
  6. Implement the 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 Boolean field.

  7. Implement the 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 Boolean field.

  8. Implement the 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 Boolean field.

  9. Implement the AddBackupObjects(SPBackupRestoreObject) method.

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

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

    3. Use the SetParameter(String, Object) method to specify a type name and description of the component that can be used by the UI of backup/restore applications.

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

    5. See the reference topic for the AddBackupObjects(SPBackupRestoreObject) 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.

    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);
        }
    }
    
    Public Sub AddBackupObjects(ByVal parent As SPBackupRestoreObject) Implements IBackupRestore.AddBackupObjects
        If parent Is Nothing Then
            Throw New ArgumentNullException("parent")
        End If
    
        Dim self As SPBackupRestoreObject = parent.AddChild(Me)
        self.Information.SetParameter(SPBackupRestoreObject.SPTypeName, Me.GetType())
        self.Information.SetParameter(SPBackupRestoreObject.SPDescription, "Description of custom content component")
    
        For Each child As ChildContent In ChildContentCollection
            Dim childIBR As IBackupRestore = TryCast(child, IBackupRestore)
            childIBR.AddBackupObjects(self)
        Next child
    End Sub
    
  10. Implement the OnAbort(Object, SPBackupRestoreInformation) method. It should always return true. In most cases it should do nothing more, but see the reference topic for OnAbort(Object, SPBackupRestoreInformation) for information about exceptions to this general rule.

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

    public Boolean OnPrepareBackup(Object sender, SPBackupInformation args)
    {
        if (args == null)
        {
            throw new ArgumentNullException("args");
        }
        args.SetParameter(SPBackupRestoreObject.SPName, this.Name);
        return true;
    }
    
    Public Function OnPrepareBackup(ByVal sender As Object, ByVal args As SPBackupInformation) As Boolean implements IBackupRestore.OnPrepareBackup 
        If args Is Nothing Then
            Throw New ArgumentNullException("args")
        End If
        args.SetParameter(SPBackupRestoreObject.SPName, Me.Name)
        Return True
    End Function
    
  12. Implement the OnBackup(Object, SPBackupInformation) method. If your content class has no content outside of any IBackupRestore child objects it may have, your implementation should simply set the CurrentProgress to a value that approximately represents the percentage of the total backup operation time that is consumed by the OnBackup(Object, SPBackupInformation) and OnPrepareBackup(Object, SPBackupInformation) methods. It should then return true as seen in the following example. Do not call the OnBackup method of any IBackupRestore child objects.

    public Boolean OnBackup(Object sender, SPBackupInformation args)
    {
        if (args == null)
        {
            throw new ArgumentNullException("args");
        }
        args.CurrentProgress = 50;
        return true;
    }
    
    Public Function OnBackup(ByVal sender As Object, ByVal args As SPBackupInformation) As Boolean implements IBackupRestore.OnBackup 
        If args Is Nothing Then
            Throw New ArgumentNullException("args")
        End If
        args.CurrentProgress = 50
        Return True
    End Function
    

    If your class does have content outside of any IBackupRestore child objects it may have, your implementation must copy this content to args.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 OnBackup(Object, SPBackupInformation) method, which the runtime will call. You should not call the OnBackup(Object, SPBackupInformation) methods of the child objects in your own code. The following example shows the overall structure of a substantive implementation of OnBackup(Object, SPBackupInformation):

    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;
    }
    
    Public Function OnBackup(ByVal sender As Object, ByVal args As SPBackupInformation) As Boolean implements IBackupRestore.OnBackup 
        If args Is Nothing Then
            Throw New ArgumentNullException("args")
        End If
        args.CurrentProgress = 50
        Dim successSignal As Boolean = True
    
        ' TODO: Implement copying your content to args.Location
        '       If the copy fails, set successSignal to false.
    
        Return successSignal
    End Function
    
  13. Implement the OnBackupComplete(Object, SPBackupInformation) method. At a minimum, your implementation should set CurrentProgress 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 OnBackupComplete.

    public Boolean OnBackupComplete(Object sender, SPBackupInformation args)
    {
        if (args == null)
        {
            throw new ArgumentNullException("args");
        }
        args.CurrentProgress = 100;
        return true;
    }
    
    Public Function OnBackupComplete(ByVal sender As Object, ByVal args As SPBackupInformation) As Boolean implements IBackupRestore.OnBackupComplete 
        If args Is Nothing Then
            Throw New ArgumentNullException("args")
        End If
        args.CurrentProgress = 100
        Return True
    End Function
    
  14. Implement the OnPreRestore method. In most situations, a restoration operation requires no preparation and your implementation of OnPreRestore should just return true. For information about other work your implementation may need to perform, see the reference topic for OnPreRestore.

  15. Implement the OnRestore method.

    • If your content class can be migrated, your code should check to see what the restore method is and call 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 CurrentProgress to a value that approximately represents the percentage of the total restore operation time that is consumed by the OnRestore and the OnPreRestore methods. It should then return true as seen in the following example. Do not call the OnRestore method of any IBackupRestore child objects.

    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;
    }
    
    Public Function OnRestore(ByVal sender As Object, ByVal args As SPRestoreInformation) As Boolean implements IBackupRestore.OnRestore 
        If args Is Nothing Then
            Throw New ArgumentNullException("args")
        End If
        If args.RestoreMethod = SPRestoreMethodType.New Then
            args.Rename()
        End If
        args.CurrentProgress = 50
        Return True
    End Function
    
    • 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 OnRestore:

    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;
    }
    
    Public Function OnRestore(ByVal sender As Object, ByVal args As SPRestoreInformation) As Boolean implements IBackupRestore.OnRestore 
        If args Is Nothing Then
            Throw New ArgumentNullException("args")
        End If
        If args.RestoreMethod = SPRestoreMethodType.New Then
            args.Rename()
        End If
        args.CurrentProgress = 50
        Dim successSignal As Boolean = True
    
        ' TODO: Implement copying your content to the destination.
        '       If the copy fails, set successSignal to false.
    
        Return successSignal
    End Function
    
  16. Implement the OnPostRestore method. At a minimum, your implementation should set CurrentProgress 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 OnPostRestore.

    public Boolean OnPostRestore(Object sender, SPRestoreInformation args)
    {
        if (args == null)
        {
            throw new ArgumentNullException("args");
        }
        args.CurrentProgress = 100;
        return true;
    }
    
    Public Function OnPostRestore(ByVal sender As Object, ByVal args As SPRestoreInformation) As Boolean implements IBackupRestore.OnPostRestore 
        If args Is Nothing Then
            Throw New ArgumentNullException("args")
        End If
        args.CurrentProgress = 100
        Return True
    End Function
    

Add other Members to Your Class As Needed

  1. 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 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 SPPersistedObject objects or SPAutoserializingObject objects; or collections of any of the above. For example, the class cannot have a 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 DiskSizeRequired property envisions a class that persists a collection of file names and uses them to create a temporary collection of 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 AddBackupObjects(SPBackupRestoreObject) method should iterate through such children and call the AddBackupObjects(SPBackupRestoreObject) method of each child. See the procedure step for implementing the AddBackupObjects(SPBackupRestoreObject) method above, for more information.

  2. 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:

    public MyContentComponent(String componentName, SPPersistedObject parent, SomeTypesomeOtherArgument, ... ) 
                       : base(componentName, parent)
    {
        somePrivateField = someOtherArgument;
        ...
    }
    
    Public Sub New(ByVal componentName As String, ByVal parent As SPPersistedObject, ByVal someOtherArgument As SomeType, . ByVal .. As )
        MyBase.New(componentName, parent)
        somePrivateField = someOtherArgument
       ...
    End Sub
    

    You must pass 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:

    public MyContentComponent(String componentName, SomeTypesomeOtherArgument, ... ) 
                       : base(componentName, SPFarm.Local)
    {
        somePrivateField = someOtherArgument;
        ...
    }
    
    Public Sub New(ByVal componentName As String, ByVal someOtherArgument As SomeType, . ByVal .. As )
        MyBase.New(componentName, SPFarm.Local)
        somePrivateField = someOtherArgument
       ...
    End Sub
    

    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.)

  3. Compile your class project.

    Warning

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

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

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

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

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

  4. 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).

  5. 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.

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

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

    MyContentComponent myContentObject = new MyContentComponent("component name", SPFarm.Local);
    myContentObject.Update();
    
    Dim myContentObject As New MyContentComponent("component name", SPFarm.Local)
    myContentObject.Update()
    
  8. Compile and run the application.

  9. 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 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 Name property value and the same parent in the configuration database. There is an overloaded version of 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 Log 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 up: " + 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;
        }

    }
}
Imports System
Imports System.IO
Imports System.Collections.Generic
Imports Microsoft.SharePoint.Administration
Imports Microsoft.SharePoint.Administration.Backup


Namespace MyCompany.SharePoint.Administration
    Public Class CriticalFiles
        Inherits SPPersistedObject
        Implements IBackupRestore

        Public Sub New()
        End Sub

        Public Sub New(ByVal componentName As String, ByVal parent As SPPersistedObject)
            MyBase.New(componentName, parent)
            Dim pathOfFile As String = "C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\LAYOUTS\TestSite\Web.config"
            FrontEndFilePaths.Add(pathOfFile)
        End Sub

        <Persisted()>
        Private Const NUMBER_OF_FILES_TO_BACK_UP As Int32 = 1

        <Persisted()>
        Private FrontEndFilePaths As New List(Of String)(NUMBER_OF_FILES_TO_BACK_UP)

        Public Property CanSelectForBackup() As Boolean Implements IBackupRestore.CanSelectForBackup
            Get
                Return True
            End Get
            Set(ByVal value As Boolean)
            End Set
        End Property

        Public Property CanSelectForRestore() As Boolean Implements IBackupRestore.CanSelectForRestore
            Get
                Return True
            End Get
            Set(ByVal value As Boolean)
            End Set
        End Property

        Public ReadOnly Property CanRenameOnRestore() As Boolean Implements IBackupRestore.CanRenameOnRestore
            Get
                Return False
            End Get
        End Property

        Public ReadOnly Property DiskSizeRequired() As UInt64 Implements IBackupRestore.DiskSizeRequired
            Get
                Dim total As UInt64 = 0
                Dim FrontEndFiles As New List(Of FileInfo)(NUMBER_OF_FILES_TO_BACK_UP)

                For Each path As String In FrontEndFilePaths
                    Dim file As New FileInfo(path)
                    FrontEndFiles.Add(file)
                Next path

                For Each file As FileInfo In FrontEndFiles
                    total = total + CULng(file.Length)
                Next file

                Return total
            End Get
        End Property

        Public Sub AddBackupObjects(ByVal parent As SPBackupRestoreObject) Implements IBackupRestore.AddBackupObjects
            If parent Is Nothing Then
                Throw New ArgumentNullException("parent")
            End If

            Dim self As SPBackupRestoreObject = parent.AddChild(Me)
            self.Information.SetParameter(SPBackupRestoreObject.SPTypeName, Me.GetType())
            self.Information.SetParameter(SPBackupRestoreObject.SPDescription, "The critical files on all front end servers.")
        End Sub

        Public Function OnAbort(ByVal sender As Object, ByVal args As SPBackupRestoreInformation) As Boolean Implements IBackupRestore.OnAbort
            Return True
        End Function

        Public Function OnPrepareBackup(ByVal sender As Object, ByVal args As SPBackupInformation) As Boolean Implements IBackupRestore.OnPrepareBackup
            If args Is Nothing Then
                Throw New ArgumentNullException("args")
            End If
            args.SetParameter(SPBackupRestoreObject.SPName, Me.Name)
            Return True
        End Function

        Public Function OnBackup(ByVal sender As Object, ByVal args As SPBackupInformation) As Boolean Implements IBackupRestore.OnBackup
            If args Is Nothing Then
                Throw New ArgumentNullException("args")
            End If

            Dim successSignal As Boolean = True

            For Each path As String In FrontEndFilePaths
                Dim file As New FileInfo(path)
                Try
                    Dim mappedFileName As String = args.GenerateFileMapping(file.Name)
                    file.CopyTo(args.Location & "\" & mappedFileName, True)
                    args.Log(SPBackupRestoreLogSeverity.Verbose, "Backed up " & file.Name & " in (" & mappedFileName & ")")
                Catch e As Exception
                    args.Log(SPBackupRestoreLogSeverity.Verbose, file.Name & " not backed up: " & e.Message)
                    successSignal = False
                End Try
            Next path

            args.CurrentProgress = 50
            Return successSignal
        End Function

        Public Function OnBackupComplete(ByVal sender As Object, ByVal args As SPBackupInformation) As Boolean Implements IBackupRestore.OnBackupComplete
            If args Is Nothing Then
                Throw New ArgumentNullException("args")
            End If
            args.CurrentProgress = 100
            Return True
        End Function

        Public Function OnPreRestore(ByVal sender As Object, ByVal args As SPRestoreInformation) As Boolean
            If args Is Nothing Then
                Throw New ArgumentNullException("args")
            End If
            Return True
        End Function

        Public Function OnRestore(ByVal sender As Object, ByVal args As SPRestoreInformation) As Boolean Implements IBackupRestore.OnRestore
            If args Is Nothing Then
                Throw New ArgumentNullException("args")
            End If

            ' If the CriticalFiles object was deleted from the farm after it was
            ' backed up, restore it to the configuration database.
            Dim cf As CriticalFiles = SPFarm.Local.GetChild(Of CriticalFiles)(Me.Name)
            If cf Is Nothing Then
                Me.Update()
                args.Log(SPBackupRestoreLogSeverity.Verbose, Me.Name & " added back to configuration database.")
            End If

            Dim successSignal As Boolean = 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

            For Each path As String In FrontEndFilePaths
                Dim backupCopy As New FileInfo(path)
                Dim mappedFileName As String = args.ReverseFileMapping(backupCopy.Name)
                Dim file As New FileInfo(args.Location & "\" & mappedFileName)

                Try
                    file.CopyTo(path, True)
                    args.Log(SPBackupRestoreLogSeverity.Verbose, "Restored " & backupCopy.Name)
                Catch e As Exception
                    args.Log(SPBackupRestoreLogSeverity.Verbose, file.Name & " not restored: " & e.Message)
                    successSignal = False
                End Try
            Next path

            args.CurrentProgress = 50
            Return successSignal
        End Function

        Public Function OnPostRestore(ByVal sender As Object, ByVal args As SPRestoreInformation) As Boolean Implements IBackupRestore.OnPostRestore
            If args Is Nothing Then
                Throw New ArgumentNullException("args")
            End If

            args.CurrentProgress = 100
            Return True
        End Function

    End Class
End Namespace

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
} 
Imports System
Imports System.Collections.Generic
Imports System.Text
Imports Microsoft.SharePoint.Administration
Imports Microsoft.SharePoint.Administration.Backup

Namespace MyCompany.SharePoint.Administration
    Module Program
        Sub Main(ByVal args() As String)
            Dim cf As CriticalFiles = SPFarm.Local.GetChild(Of CriticalFiles)("Critical Front End Files")
            If cf Is Nothing Then
                Console.WriteLine("There is no CriticalFiles object in the configuration database.")
                Console.Write("Enter 'A' to add it. Press Return to do nothing:")
                Dim response As String = Console.ReadLine()
                If response = "A" Then
                    Dim myCriticalFiles As New CriticalFiles("Critical Front End Files", SPFarm.Local)
                    myCriticalFiles.Update()
                End If
            Else
                Console.WriteLine("There is a CriticalFiles object in the configuration database.")
                Console.Write("Enter 'D' to delete it. Press Return to do nothing:")
                Dim response As String = Console.ReadLine()
                If response = "D" Then
                    cf.Delete()
                End If
            End If
        End Sub ' end Main
    End Module  ' end Program
End Namespace

See Also

Tasks

How to: Programmatically Back Up Content

How to: Programmatically Restore Content

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

How to: Create a Database Class That Can Be Restored From a Snapshot

How to: Create a Class That Is Included in Configuration-Only Backups and Restorations

Reference

Microsoft.SharePoint.Administration.Backup

Backup

Restore

Concepts

Programming with the SharePoint Foundation Backup/Restore Object Model