Procedimiento para crear una clase de contenido que se pueda restaurar y de la que se pueda hacer una copia de seguridad

Última modificación: jueves, 06 de mayo de 2010

Hace referencia a: SharePoint Foundation 2010

Si tiene un componente de contenido personalizado que desea incluir en las copias de seguridad y restauraciones de Microsoft SharePoint Foundation, debe representar el componente con una clase que implemente la interfaz IBackupRestore. En este tema se explica cómo hacerlo. Hay un ejemplo completo de los procedimientos. (Si el componente es un servicio web que implementa Service Application Framework, hay una alternativa a la implementación de IBackupRestore. Para obtener más información, vea el tema sobre copia de seguridad y restauración en Service Application Framework.)

Nota

Si el componente es una base de datos hospedada en las ediciones Enterprise o Developer de Microsoft SQL Server que desea que se restaure a partir de una instantánea mediante el modelo de objetos o la interfaz de usuario de SharePoint Foundation, la clase también debe implementar la interfaz IDatabaseSnapshotRestore. Para obtener información acerca de cómo implementar esa interfaz, vea el tema Procedimiento para crear una clase de base de datos que se puede restaurar desde una instantánea.

Si el componente consta de información de configuración que los administradores del conjunto o granja de servidores deben tener la opción de incluir en copias de seguridad y restauraciones de solo configuración, revise el tema Procedimiento para crear una clase que se incluye en restauraciones y copias de seguridad de solo configuración y lleve a cabo el procedimiento incluido, si corresponde.

No es necesario que su clase se derive de SPPersistedObject, pero si su contenido es una base de datos, se recomienda que la derive de SPDatabase, o bien de SPContentDatabase. Las dos clases anteriores se derivan de SPPersistedObject e implementan IBackupRestore. Por lo tanto, dispondrá de implementaciones predeterminadas de miembros de IBackupRestore que podrá utilizar cuando sea conveniente.

Puede crear tantos tipos de clases de IBackupRestore como quiera y, si lo desea, se pueden anidar como un árbol de clases de componentes. Sin embargo, la clase superior de cualquiera de esos árboles debe derivarse (directa o indirectamente) del objeto de SPPersistedObject y debe ser un elemento secundario de SPFarm. Si la clase de contenido no es un elemento secundario de otra clase de contenido personalizada, debe derivarse (directa o indirectamente) del objeto de SPPersistedObject y debe ser un elemento secundario de SPFarm.

Si la clase deriva de una clase que ya implementa el objeto IBackupRestore (tanto si deriva de SPPersistedObject como si no) y desea reemplazar una implementación heredada de un miembro IBackupRestore, la declaración de clase debe hacer referencia explícitamente a IBackupRestore de este modo:

[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

Nota

Cualquier clase personalizada que herede directa o indirectamente de SPPersistedObject debe tener un GuidAttribute aplicado en su declaración.

La "invalidación" de cualquier miembro de IBackupRestore debe incluir explícitamente "IBackupRestore" en el nombre del miembro y no debe incluir la palabra clave public. A continuación se muestra un ejemplo:

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

Como alternativa, si la implementación del miembro en la clase principal utilizó las palabras clave virtual o override, puede utilizar la palabra clave override en la implementación de este modo:

public override UInt64 DiskSizeRequired { ... }
Public Overrides ReadOnly Property DiskSizeRequired() As UInt64
    Get
        ...
    End Get
End Property
Nota de precauciónPrecaución

No oculte la implementación de miembro heredado declarando de nuevo el miembro con o sin la palabra clave new ([new] public UInt64 DiskSizeRequired { ... }). En el procedimiento siguiente, las firmas de miembro se escriben como serían para una clase que no deriva de una clase que ya implementa IBackupRestore. Asegúrese de modificarlas con el modelo necesario si la clase deriva de este elemento principal.

Si la clase se deriva de SPPersistedObject, permita que las propiedades SPPersistedObject.Id y SPPersistedObject.Name de dicha clase sirvan de implementación de las propiedades IBackupRestore.Id y IBackupRestore.Name. Puede invalidar las propiedades, pero no crear una segunda implementación de ninguna de ellas. Su clase debe tener una única propiedad Name y una sola propiedad Id.

Para implementar los miembros de IBackupRestore

  1. Comience un nuevo proyecto de clase en Visual Studio.

  2. Agregue una referencia a Microsoft.SharePoint al proyecto de Visual Studio y agregue instrucciones using para los espacios de nombres Microsoft.SharePoint.Administration y Microsoft.SharePoint.Administration.Backup a su archivo de clase.

  3. Si la clase no deriva de SPPersistedObject, implemente la propiedad Name. Eso servirá de nombre del componente de contenido en la interfaz de usuario de stsadm.exe, la aplicación Administración central y la interfaz de usuario de cualquier aplicación de copia de seguridad y restauración personalizadas. En la mayoría de los casos se implementa la propiedad creando un campo privado para el valor del nombre e implementando la propiedad pública como contenedor alrededor del campo. Para obtener información sobre las posibles variantes de la implementación, vea el tema de referencia para la propiedad.

    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. Si la clase no deriva de SPPersistedObject, implemente la propiedad Id. En la mayoría de los casos, se implementa la propiedad creando un campo privado para el valor del nombre y se implementa la propiedad pública como contenedor alrededor del campo. Para obtener información sobre las posibles variantes de la implementación, vea el tema de referencia para la propiedad.

    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. Implemente la propiedad DiskSizeRequired. Si la clase es sólo un contenedor para algunas clases IBackupRestore secundarias, la propiedad debe devolver 0. De lo contrario, la propiedad debe calcular el tamaño del contenido. (Incluya el tamaño de cualquier objeto IBackupRestore que no sea secundario, pero no incluya el tamaño de objetos IBackupRestore secundarios. Cada uno de ellos tiene su propia propiedad DiskSizeRequired y SharePoint Foundation agregará esos valores automáticamente). En el ejemplo siguiente se suman los tamaños de todos los archivos cuyas rutas de acceso están incluidas en una colección denominada 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. Implemente la propiedad CanSelectForBackup. Si los usuarios nunca deberían ser capaces de hacer copias de seguridad de objetos de su clase independientemente de una copia de seguridad del objeto principal, el descriptor de acceso get debería devolver false. Si los usuarios deberían ser siempre capaces de seleccionar cualquier objeto de su clase para la copia de seguridad independiente, el descriptor de acceso get debería devolver true. En cualquier caso, el descriptor de acceso set debe ser un par de llaves "{}" vacío. Si se puede hacer una copia de seguridad de algunos objetos de la clase independientemente de su objeto principal, pero otros no, implemente la propiedad como contenedor alrededor de un campo privado Boolean.

  7. Implemente la propiedad CanSelectForRestore. Si los usuarios nunca debeberían ser capaces de restaurar objetos de su clase de componente personalizado independientemente de una restauración del objeto principal, el descriptor de acceso get debería devolver false. Si los usuarios deberían ser siempre capaces de seleccionar cualquier objeto de su clase para la restauración independiente, el descriptor de acceso get debería devolver true. En cualquier caso, el descriptor de acceso set debe ser un par de llaves "{}" vacío. Si se pueden restaurar algunos objetos de la clase independientemente de su objeto principal, pero otros no, implemente la propiedad como contenedor alrededor de un campo privado Boolean.

  8. Implemente la propiedad CanRenameOnRestore. Si los usuarios nunca deberían ser capaces de restaurar objetos de la clase de componente personalizado en una nueva ubicación, el descriptor de acceso get debería devolver false. Si los usuarios deberían ser capaces de migrar cualquier objeto de la clase, el descriptor de acceso get debería devolver true. Si los objetos de la clase se pueden migrar en algunas ocasiones, pero no siempre, implemente la propiedad como contenedor alrededor de un campo Boolean privado.

  9. Implemente el método AddBackupObjects(SPBackupRestoreObject).

    1. El código de implementación debe empezar por producir una excepción si no hay ningún elemento principal válido al que se pueda agregar el componente.

    2. Use el método AddChild para agregar el componente al árbol de objetos que la operación de copia de seguridad o restauración procesará.

    3. Use el método SetParameter(String, Object) para especificar un nombre de tipo y una descripción del componente que pueda utilizar la interfaz de usuario de las aplicaciones de copia de seguridad y restauración.

    4. Si el componente tiene objetos IBackupRestore secundarios, la implementación debería recorrerlos en iteración y llamar de forma recursiva al método AddBackupObjects(SPBackupRestoreObject) de cada objeto secundario.

    5. Vea el tema de referencia del método AddBackupObjects(SPBackupRestoreObject) para obtener más ideas sobre sus implementaciones.

    En el ejemplo de código siguiente se supone que la clase de contenido tiene una ChildContentCollection de objetos IBackupRestore secundarios. Si la clase tiene más de un tipo de componente secundario, puede tener colecciones independientes para cada tipo y recorrer en iteración cada colección.

    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. Implemente el método OnAbort(Object, SPBackupRestoreInformation). Debería devolver siempre true. En la mayoría de los casos no debe hacer nada más, pero vea el tema de referencia de OnAbort(Object, SPBackupRestoreInformation) para obtener información acerca de las excepciones a esta regla general.

  11. Implemente el método OnPrepareBackup(Object, SPBackupInformation). Como mínimo, debe usar el método SetParameter(String, Object) para especificar un nombre para el objeto de contenido. Aparte de eso, se pueden realizar pocas generalizaciones. Vea el tema de referencia de OnPrepareBackup(Object, SPBackupInformation) para obtener más información. En el ejemplo siguiente se muestra una implementación mínima del método, que a menudo es todo lo necesario.

    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. Implemente el método OnBackup. Si la clase de contenido no tiene contenido aparte de los objetos secundarios IBackupRestore que pueda tener, la implementación debe establecer simplemente el CurrentProgress en un valor que represente aproximadamente el porcentaje del tiempo total de la operación de copia de seguridad que se consume en los métodos OnBackup(Object, SPBackupInformation) y OnPrepareBackup(Object, SPBackupInformation). A continuación, debe devolver true, como se ve en el ejemplo siguiente. No llame al método OnBackup(Object, SPBackupInformation) de ningún objeto secundario IBackupRestore.

    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
    

    Si la clase tiene contenido aparte de los objetos secundarios IBackupRestore que pueda tener, la implementación debe copiar este contenido en args.Location y devolver false si se produce un error en la copia. Se debe incluir lógica para realizar una copia de seguridad de cualquier objeto secundario que no implemente IBackupRestore, pero no debe realizar explícitamente una copia de seguridad de objetos secundarios que implementen IBackupRestore. Su propio método OnBackup(Object, SPBackupInformation) realizará las respectivas copias de seguridad, llamado por el tiempo de ejecución. No se debe llamar a los métodos OnBackup(Object, SPBackupInformation) de los objetos secundarios de su propio código. En el ejemplo siguiente se muestra la estructura general de una implementación sustancial de 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. Implemente el método OnBackupComplete. Como mínimo, la implementación debería establecer CurrentProgress al 100% y devolver true, como se muestra en el ejemplo siguiente. Normalmente eso es todo lo que se necesita. Para obtener información sobre otras operaciones que podría ser necesario realizar mediante la implementación, vea el tema de referencia de OnBackupComplete(Object, SPBackupInformation).

    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. Implemente el método OnPreRestore. En la mayoría de las situaciones, una operación de restauración no requiere preparación y la implementación de OnPreRestore debería devolver simplemente true. Para obtener información sobre otras operaciones que podría ser necesario realizar mediante la implementación, consulte el tema de referencia de OnPreRestore.

  15. Implemente el método OnRestore.

    • Si se puede migrar la clase de contenido, el código debe comprobar cuál es el método de restauración y llamar a Rename() si el método es New.

    • Si la clase de contenido no tiene contenido aparte de los objetos secundarios IBackupRestore que pueda tener, la implementación debe establecer simplemente el CurrentProgress en un valor que represente aproximadamente el porcentaje del tiempo total de la operación de restauración que consumen los métodos OnRestore y OnPreRestore. A continuación, debe devolver true como se ve en el ejemplo siguiente. No llame al método OnRestore de ningún objeto secundario IBackupRestore.

    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
    
    • Si la clase tiene contenido aparte de los objetos secundarios IBackupRestore que pueda tener, la implementación debe copiar dicho contenido en el destino de la restauración. Devuelva false, si por cualquier motivo se produce un error en la copia del contenido.

    En el ejemplo siguiente se muestra la estructura general de una implementación sustancial de 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. Implemente el método OnPostRestore. Como mínimo, la implementación debería establecer CurrentProgress en el 100% y devolver true, como se muestra en el ejemplo siguiente. Normalmente no hace falta nada más. Para obtener información sobre otras acciones que podría ser necesario realizar mediante la implementación, consulte el tema de referencia de 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
    

Agregar otros miembros a la clase según sea necesario

  1. Agregar campos, propiedades y métodos auxiliares según sea necesario para completar la clase. Mientras trabaja, tenga en cuenta los siguientes puntos:

    • Utilice campos y propiedades para contener objetos de contenido secundarios.

    • Si la clase deriva de SPPersistedObject, la declaración de campos que desea conservar en la base de datos de configuración debe ir precedida del atributo [Persisted]. Sin embargo, sólo puede marcar los siguientes tipos de campos de esta forma: tipos primitivos, como por ejemplo cadenas, números enteros y los GUID; otros objetos SPPersistedObject u objetos SPAutoserializingObject; o colecciones de cualquiera de las opciones anteriores. Por ejemplo, la clase no puede tener un campo FileInfo marcado con el atributo [Persisted]. Si los datos que le gustaría conservar no son de una clase con persistencia, utilice un sustituto con persistencia. La implementación de ejemplo encima de la propiedad DiskSizeRequired prevé una clase que mantiene una colección de nombres de archivo y los utiliza para crear una colección temporal de objetos FileInfo en tiempo de ejecución.

    • Si la clase puede tener varios elementos secundarios del mismo tipo, cree una propiedad o un campo de un tipo de colección u otro tipo enumerable para contener una colección de todos los elementos secundarios de un tipo determinado. Esto es especialmente importante si el propio tipo secundario implementa IBackupRestore, ya que la implementación del método AddBackupObjects(SPBackupRestoreObject) debe recorrer en iteración estos elementos secundarios y llamar al método AddBackupObjects(SPBackupRestoreObject) de cada elemento secundario. Consulte más arriba el paso para implementar el método AddBackupObjects(SPBackupRestoreObject).

  2. Agregue constructores a la clase para inicializar sus campos y propiedades según sea necesario. Si la clase deriva de SPPersistedObject, debe haber al menos un constructor que dé nombre al objeto y lo asigne a un objeto principal. Normalmente dicho constructor toma al menos estos dos argumentos:

    • Un argumento String que será el nombre del objeto de contenido.

    • Un argumento SPPersistedObject que representa el elemento principal del objeto de contenido.

    Este constructor debe llamar al constructor base que toma los mismos argumentos. Éste es un ejemplo:

    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
    

    Debe pasar SPFarm.Local como elemento principal cuando el objeto de contenido sea el objeto superior de un árbol personalizado de objetos IBackupRestore. Si el tipo de componente personalizado siempre es el objeto superior, omita el argumento SPPersistedObject e incluya en el código una referencia a SPFarm.Local en la llamada al constructor base. Éste es un ejemplo:

    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
    

    Si algunos objetos de la clase siempre tienen el mismo nombre, puede omitir el argumento String e incluir en el código el nombre en la llamada al constructor base. (Si todos los objetos de un tipo determinado tienen el mismo nombre, nunca debería haber más de un elemento secundario de ese tipo para un elemento principal concreto y, por lo tanto, no más de un objeto de ese tipo en toda la granja de servidores si el objeto es un elemento secundario de la granja).

  3. Compile el proyecto de clase.

    Nota de precauciónPrecaución

    Debe asignar un nombre seguro al ensamblado y colocar el ensamblado en la memoria caché global de ensamblados (GAC).

Para crear un objeto de la clase y convertirlo en secundario de la granja de servidores

  1. Inicie un nuevo proyecto de aplicación de consola en Visual Studio.

  2. Agregue una referencia a la DLL de la clase de componente personalizado al proyecto.

  3. Agregue una instrucción using para Microsoft.SharePoint.Administration.

  4. Agregue una instrucción using para el espacio de nombres que utilizó en la clase de componente personalizado (o simplemente utilice el mismo espacio de nombres en la aplicación de consola).

  5. Agregue al método Main de su proyecto una llamada al constructor de la clase de componente personalizado. Si ha creado una jerarquía de tipos personalizados, llame al constructor de la clase superior.

  6. Si es necesario, preceda la llamada al constructor del componente con código que cree parámetros para el constructor.

  7. Después de la llamada al constructor del componente, el código debe llamar al método Update del objeto de componente. Éste es un ejemplo de lo que debe tener en el método Main:

    MyContentComponent myContentObject = new MyContentComponent("component name", SPFarm.Local);
    myContentObject.Update();
    
    Dim myContentObject As New MyContentComponent("component name", SPFarm.Local)
    myContentObject.Update()
    
  8. Compile y ejecute la aplicación.

  9. En la aplicación Administración central, vaya a Operaciones | Realizar copia de seguridad. El objeto debe aparecer como elemento secundario de la granja en la página Realizar copia de seguridad.

    Nota

    Hay una aplicación de consola de ejemplo para crear y eliminar objetos de contenido personalizado en la sección Ejemplo siguiente.

Consejo de desarrollo

Las siguientes sugerencias pueden resultar útiles a medida que desarrolla las clases de contenido personalizado, especialmente porque probablemente creará objetos y los agregará a la granja varias veces mientras trabaja.

Cuestiones a tener en cuenta

  1. Si necesita eliminar el objeto de la base de datos de configuración, use Delete().

  2. Se produce una excepción si se llama a obj. Update() y ya hay un objeto de la misma clase que obj con el mismo valor de la propiedad Name y el mismo elemento principal en la base de datos de configuración. Hay una versión sobrecargada de Update que puede ser preferible.

  3. Hay una aplicación de consola de ejemplo en la segunda sección Ejemplo siguiente que se puede utilizar para agregar o eliminar los objetos personalizados de la base de datos de configuración.

  4. Ejecute iisreset en la línea de comandos cada vez que termine de compilar la clase IBackupRestore. Es posible que también deba reiniciar el servidor.

  5. Los diversos métodos IBackupRestore.On* deben tomar un parámetro SPBackupInformation o un parámetro SPRestoreInformation. Puede usar sus miembros para fines de depuración. El método Log Log es especialmente útil.

Ejemplo

El código siguiente implementa un componente de contenido personalizado que representa un único archivo Web.config en un servidor front-end. Reemplace la parte TestSite de la ruta de acceso al archivo en la implementación del constructor con el nombre de un directorio del servidor de prueba. El ensamblado compilado debe tener un nombre seguro y estar instalado en la GAC.

En el ejemplo que sigue a la implementación de la clase, hay un código para una aplicación de consola simple que registrará el componente como un elemento secundario de la granja o lo eliminará de ésta.

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

Ésta es una aplicación de consola que agregará o eliminará el objeto de contenido de la base de datos de configuración.

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

Vea también

Tareas

Cómo: Hacer copias de seguridad de contenido mediante programación

Procedimiento para restaurar contenido mediante programación

Procedimiento para realizar la copia de seguridad y restaurar una única colección de sitios mediante programación

Procedimiento para crear una clase de base de datos que se puede restaurar desde una instantánea

Procedimiento para crear una clase que se incluye en restauraciones y copias de seguridad de solo configuración

Referencia

Microsoft.SharePoint.Administration.Backup

Backup

Restore

Conceptos

Programación con el modelo de objetos de copia de seguridad y restauración de SharePoint Foundation