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
Precaució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
Comience un nuevo proyecto de clase en Visual Studio.
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.
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
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
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
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.
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.
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.
Implemente el método AddBackupObjects(SPBackupRestoreObject).
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.
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á.
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.
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.
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
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.
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
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 sí 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 sí 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
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
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.
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 sí 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
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
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).
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).
Compile el proyecto de clase.
Precaució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
Inicie un nuevo proyecto de aplicación de consola en Visual Studio.
Agregue una referencia a la DLL de la clase de componente personalizado al proyecto.
Agregue una instrucción using para Microsoft.SharePoint.Administration.
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).
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.
Si es necesario, preceda la llamada al constructor del componente con código que cree parámetros para el constructor.
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()
Compile y ejecute la aplicación.
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
Si necesita eliminar el objeto de la base de datos de configuración, use Delete().
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.
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.
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.
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 crear una clase de base de datos que se puede restaurar desde una instantánea
Referencia
Microsoft.SharePoint.Administration.Backup
Conceptos
Programación con el modelo de objetos de copia de seguridad y restauración de SharePoint Foundation