Freigeben über


Gewusst wie: Erstellen einer Inhaltsklasse, die gesichert und wiederhergestellt werden kann

Letzte Änderung: Donnerstag, 6. Mai 2010

Gilt für: SharePoint Foundation 2010

Wenn Sie eine benutzerdefinierte Inhaltskomponente in Microsoft SharePoint Foundation-Sicherungen und -Wiederherstellungen einschließen möchten, müssen Sie die Komponente durch eine Klasse darstellen, mit der die IBackupRestore-Schnittstelle implementiert wird. Die Vorgehensweise wird in diesem Thema erläutert. Im Anschluss an die Verfahren finden Sie ein vollständiges Beispiel. (Wenn es sich bei der Komponente um einen Webdienst handelt, durch den das Service Application Framework implementiert wird, gibt es eine Alternative zum Implementieren von IBackupRestore. Weitere Informationen finden Sie unter Sicherung und Wiederherstellen in Service Application Framework.)

HinweisHinweis

Wenn es sich bei der Komponente um eine in den Enterprise- oder Developer-Editionen von Microsoft SQL Server gehostete Datenbank handelt, deren Wiederherstellung über die Benutzeroberfläche oder das Objektmodell von SharePoint Foundation aus einer Momentaufnahme möglich sein soll, muss von der Klasse auch die IDatabaseSnapshotRestore-Schnittstelle implementiert werden. Weitere Informationen zum Implementieren dieser Schnittstelle finden Sie unter Gewusst wie: Erstellen einer Datenbankklasse, die aus einem Snapshot wiederhergestellt werden kann.

Wenn die Komponente aus Konfigurationsinformationen besteht, die Farmadministratoren wahlweise in Sicherungen und Wiederherstellungen nur der Konfiguration einschließen können sollen, lesen Sie das Thema Gewusst wie: Erstellen einer Klasse, die in reine Konfigurationssicherungen und -wiederherstellungen einbezogen wird, und führen Sie gegebenenfalls das dort beschriebene Verfahren aus.

Die Klasse muss nicht von SPPersistedObject abgeleitet werden. Wenn es sich beim Inhalt jedoch um eine Datenbank handelt, wird empfohlen, die Klasse von SPDatabase oder von SPContentDatabase abzuleiten. Diese beiden Klassen werden von SPPersistedObject abgeleitet und implementieren IBackupRestore. Daher erhalten Sie Standardimplementierungen von Membern von IBackupRestore, die Sie gegebenenfalls verwenden können.

Sie können beliebig viele Typen von IBackupRestore-Klassen erstellen, die bei Bedarf als Struktur aus Komponentenklassen geschachtelt werden können. Die höchste Klasse in einer solchen Struktur muss jedoch (direkt oder indirekt) vom SPPersistedObject-Objekt abgeleitet werden und muss eine untergeordnete Klasse von SPFarm sein. Wenn es sich bei der Inhaltsklasse nicht um eine untergeordnete Klasse einer anderen benutzerdefinierten Inhaltsklasse handelt, muss die Klasse (direkt oder indirekt) vom SPPersistedObject-Objekt abgeleitet werden und muss eine untergeordnete Klasse von SPFarm sein.

Wenn die Klasse von einer Klasse abgeleitet wird, von der das IBackupRestore-Objekt bereits implementiert wird (unabhängig davon, ob dieses von SPPersistedObject abgeleitet wird), und Sie eine geerbte Implementierung eines IBackupRestore-Members ersetzen möchten, sollte die Klassendeklaration explizit wie hier gezeigt auf IBackupRestore verweisen:

[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
HinweisHinweis

Auf die Deklaration jeder benutzerdefinierten Klasse, die direkt oder indirekt von SPPersistedObject erbt, muss GuidAttribute angewendet werden.

Die Außerkraftsetzung eines IBackupRestore-Members sollte explizit "IBackupRestore" im Membernamen enthalten und sollte nicht das public-Schlüsselwort enthalten. Der folgende Code ist ein Beispiel dafür.

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

Alternativ können Sie, wenn für die Implementierung des Members in der übergeordneten Klasse die Schlüsselwörter virtual oder override verwendet wurden, wie hier gezeigt in der Implementierung das override-Schlüsselwort verwenden:

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

Blenden Sie die geerbte Memberimplementierung nicht aus, indem Sie den Member mit oder ohne dem new-Schlüsselwort ([new] public UInt64 DiskSizeRequired { ... }) erneut deklarieren. Im unten gezeigten Verfahren werden die Membersignaturen so geschrieben wie für eine Klasse, die nicht von einer Klasse abgeleitet wird, von der IBackupRestore bereits implementiert wird. Ändern Sie die Membersignaturen unbedingt in das erforderliche Muster, wenn die Klasse nicht von einer solchen übergeordneten Klasse abgeleitet wird.

Wenn die Klasse von SPPersistedObject abgeleitet wird, verwenden Sie die Eigenschaften SPPersistedObject.Id und SPPersistedObject.Name dieser Klasse als Implementierung der Eigenschaften IBackupRestore.Id und IBackupRestore.Name. Sie können die Eigenschaften außer Kraft setzen, erstellen Sie aber keine zweite Implementierung der Eigenschaften. Die Klasse sollte nur eine Name-Eigenschaft und eine Id-Eigenschaft haben.

So implementieren Sie die Member von "IBackupRestore"

  1. Beginnen Sie ein neues Klassenprojekt in Visual Studio.

  2. Fügen Sie dem Visual Studio-Projekt einen Verweis auf Microsoft.SharePoint hinzu, und fügen Sie der Klassendatei using-Anweisungen für die Namespaces Microsoft.SharePoint.Administration und Microsoft.SharePoint.Administration.Backup hinzu.

  3. Wenn die Klasse nicht von SPPersistedObject abgeleitet wird, implementieren Sie die Name-Eigenschaft. Diese wird als Name der Inhaltskomponente auf der Benutzeroberfläche von stsadm.exe, in der Zentraladministrationsanwendung und auf der Benutzeroberfläche aller benutzerdefinierten Sicherungs- und Wiederherstellungsanwendungen verwendet. In den meisten Fällen implementieren Sie die Eigenschaft, indem Sie ein privates Feld für den Namenswert erstellen und die öffentliche Eigenschaft als Wrapper für das Feld implementieren. Weitere Informationen zu möglichen Variantenimplementierungen finden Sie im Referenzthema zur Eigenschaft.

    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. Wenn die Klasse nicht von SPPersistedObject abgeleitet wird, implementieren Sie die Id-Eigenschaft. In den meisten Fällen implementieren Sie die Eigenschaft, indem Sie ein privates Feld für den Namenswert erstellen und die öffentliche Eigenschaft als Wrapper für das Feld implementieren. Weitere Informationen zu möglichen Variantenimplementierungen finden Sie im Referenzthema zur Eigenschaft.

    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. Implementieren Sie die DiskSizeRequired-Eigenschaft. Wenn die Klasse nur ein Container für untergeordnete IBackupRestore-Klassen ist, sollte von der Eigenschaft 0 zurückgegeben werden. Anderenfalls sollte von der Eigenschaft die Größe des Inhalts berechnet werden. Schließen Sie die Größe aller untergeordneten Nicht-IBackupRestore-Objekte ein, jedoch nicht die Größe untergeordneter IBackupRestore-Objekte. Diese Objekte haben jeweils eine eigene DiskSizeRequired-Eigenschaft, und diese Werte werden von SharePoint Foundation automatisch hinzugefügt.) Im folgenden Beispiel werden die Größen aller Dateien summiert, deren Pfade in einer Auflistung mit dem Namen FrontEndFilePaths enthalten sind.

    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. Implementieren Sie die CanSelectForBackup-Eigenschaft. Wenn Benutzer nie in der Lage sein sollen, Objekte der Klasse unabhängig von einer Sicherung des übergeordneten Objekts zu sichern, sollte vom get-Accessor false zurückgegeben werden. Wenn Benutzer immer in der Lage sein sollen, ein beliebiges Objekt der Klasse für eine unabhängige Sicherung auszuwählen, sollte vom get-Accessor true zurückgegeben werden. In jedem Fall sollte der set-Accessor aus einem leeren Paar geschweifter Klammern ("{ }") bestehen. Wenn einige Objekte der Klasse unabhängig vom übergeordneten Objekt gesichert werden können, andere dagegen nicht, implementieren Sie die Eigenschaft als Wrapper für ein privates Boolean-Feld.

  7. Implementieren Sie die CanSelectForRestore-Eigenschaft. Wenn Benutzer nie in der Lage sein sollen, Objekte der benutzerdefinierten Komponentenklasse unabhängig von einer Wiederherstellung des übergeordneten Objekts wiederherzustellen, sollte vom get-Accessor false zurückgegeben werden. Wenn Benutzer immer in der Lage sein sollen, ein beliebiges Objekt der Klasse für eine unabhängige Wiederherstellung auszuwählen, sollte vom get-Accessor true zurückgegeben werden. In jedem Fall sollte der set-Accessor aus einem leeren Paar geschweifter Klammern ("{ }") bestehen. Wenn einige Objekte der Klasse unabhängig vom übergeordneten Objekt wiederhergestellt werden können, andere dagegen nicht, implementieren Sie die Eigenschaft als Wrapper für ein privates Boolean-Feld.

  8. Implementieren Sie die CanRenameOnRestore-Eigenschaft. Wenn Benutzer nie in der Lage sein sollen, Objekte der benutzerdefinierten Komponentenklasse an einem neuen Speicherort wiederherzustellen, sollte vom get-Accessor false zurückgegeben werden. Wenn Benutzer in der Lage sein sollen, beliebige Objekte der Klasse zu migrieren, sollte vom get-Accessor true zurückgegeben werden. Wenn Objekte der Klasse manchmal, aber nicht immer migriert werden können, implementieren Sie die Eigenschaft als Wrapper für ein privates Boolean-Feld.

  9. Implementieren Sie die AddBackupObjects(SPBackupRestoreObject)-Methode.

    1. Der Implementierungscode sollte immer mit dem Auslösen einer Ausnahme beginnen, wenn kein gültiges übergeordnetes Element vorhanden ist, dem die Komponente hinzugefügt werden kann.

    2. Verwenden Sie die AddChild-Methode, um die Komponente der Objektstruktur hinzuzufügen, die beim Sicherungs- oder Wiederherstellungsvorgang verarbeitet werden soll.

    3. Verwenden Sie die SetParameter(String, Object)-Methode, um einen Typnamen und eine Beschreibung der Komponente anzugeben, die von der Benutzeroberfläche von Sicherungs- und Wiederherstellungsanwendungen verwendet werden kann.

    4. Wenn die Komponente untergeordnete IBackupRestore-Objekte hat, sollten diese von der Implementierung durchlaufen werden. Außerdem sollte die AddBackupObjects(SPBackupRestoreObject)-Methode der einzelnen untergeordneten Objekte rekursiv aufgerufen werden.

    5. Weitere Informationen zur Implementierung dieser Methode finden Sie im Referenzthema zur AddBackupObjects(SPBackupRestoreObject)-Methode.

    Im folgenden Codebeispiel wird angenommen, dass die Inhaltsklasse ein ChildContentCollection-Objekt aus untergeordneten IBackupRestore-Objekten hat. Wenn die Klasse mehrere untergeordnete Komponententypen hat, können Sie separate Auflistungen für die einzelnen Typen verwenden und die einzelnen Auflistungen durchlaufen.

    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. Implementieren Sie die OnAbort(Object, SPBackupRestoreInformation)-Methode. Dadurch sollte immer true zurückgegeben werden. In den meisten Fällen sollte darüber hinaus nichts geschehen. Weitere Informationen zu Ausnahmen von dieser allgemeinen Regel finden Sie im Referenzthema zu OnAbort(Object, SPBackupRestoreInformation).

  11. Implementieren Sie die OnPrepareBackup(Object, SPBackupInformation)-Methode. Sie sollten mindestens die SetParameter(String, Object)-Methode verwenden, um einen Namen für das Inhaltsobjekt anzugeben. Darüber hinaus können wenige Generalisierungen vorgenommen werden. Weitere Informationen finden Sie im Referenzthema zu OnPrepareBackup(Object, SPBackupInformation). Im folgenden Beispiel wird eine minimale Implementierung der Methode gezeigt, die in vielen Fällen ausreicht.

    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. Implementieren Sie die OnBackup(Object, SPBackupInformation)-Methode. Wenn die Inhaltsklasse keine Inhalte außerhalb möglicherweise vorhandener untergeordneter IBackupRestore-Objekte enthält, sollte durch die Implementierung einfach CurrentProgress auf einen Wert festgelegt werden, der ungefähr den Prozentsatz der Gesamtdauer des Sicherungsvorgangs darstellt, der von den Methoden OnBackup(Object, SPBackupInformation) und OnPrepareBackup(Object, SPBackupInformation) beansprucht wird. Anschließend sollte wie im folgenden Beispiel true zurückgegeben werden. Rufen Sie nicht die OnBackup-Methode untergeordneter IBackupRestore-Objekte auf.

    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
    

    Wenn die Klasse Inhalte außerhalb möglicherweise vorhandener untergeordneter IBackupRestore-Objekte enthält, müssen diese Inhalte von der Implementierung nach args.Location kopiert werden. Wenn beim Kopieren Fehler auftreten, muss false zurückgegeben werden. Schließen Sie Logik zum Sichern aller untergeordneten Objekte ein, durch die nichtIBackupRestore implementiert wird. Sichern Sie jedoch nicht explizit untergeordnete Objekte, durch die IBackupRestore implementiert wird. Diese Objekte werden durch die eigene OnBackup(Object, SPBackupInformation)-Methode gesichert, die von der Laufzeit aufgerufen wird. Rufen Sie nicht die OnBackup(Object, SPBackupInformation)-Methoden der untergeordneten Objekte in Ihrem eigenen Code auf. Im folgenden Beispiel wird die allgemeine Struktur einer eigenständigen Implementierung von OnBackup(Object, SPBackupInformation) gezeigt:

    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. Implementieren Sie die OnBackupComplete(Object, SPBackupInformation)-Methode. Von der Implementierung sollte mindestens wie im folgenden Beispiel gezeigt CurrentProgress auf 100 Prozent festgelegt und true zurückgegeben werden. Mehr ist normalerweise nicht erforderlich. Weitere Informationen zu anderen Aktionen, die möglicherweise von der Implementierung ausgeführt werden müssen, finden Sie im Referenzthema zu 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. Implementieren Sie die OnPreRestore-Methode. In den meisten Situationen ist für einen Wiederherstellungsvorgang keine Vorbereitung erforderlich, und von der Implementierung von OnPreRestore sollte nur true zurückgegeben werden. Weitere Informationen zu anderen Aktionen, die möglicherweise von der Implementierung ausgeführt werden müssen, finden Sie im Referenzthema zu OnPreRestore.

  15. Implementieren Sie die OnRestore-Methode.

    • Wenn die Inhaltsklasse migriert werden kann, sollte vom Code überprüft werden, welche Wiederherstellungsmethode verwendet wird. Wenn die New-Methode verwendet wird, sollte Rename() aufgerufen werden.

    • Wenn die Inhaltsklasse außerhalb möglicherweise vorhandener untergeordneter IBackupRestore-Objekt keine Inhalte enthält, sollte durch die Implementierung einfach CurrentProgress auf einen Wert festgelegt werden, der ungefähr den Prozentsatz der Gesamtdauer des Wiederherstellungsvorgangs darstellt, der von den Methoden OnRestore und OnPreRestore beansprucht wird. Dann sollte wie im folgenden Beispiel gezeigt true zurückgegeben werden. Rufen Sie nicht die OnRestore-Methode untergeordneter IBackupRestore-Objekte auf.

    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
    
    • Wenn die Klasse Inhalte außerhalb möglicherweise vorhandener untergeordneter IBackupRestore-Objekte enthält, müssen diese Inhalte durch die Implementierung in das Wiederherstellungsziel kopiert werden. Geben Sie false zurück, wenn beim Kopieren der Inhalte Fehler auftreten.

    Im folgenden Beispiel wird die allgemeine Struktur einer eigenständigen Implementierung von OnRestore gezeigt:

    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. Implementieren Sie die OnPostRestore-Methode. Von der Implementierung sollte mindestens wie im folgenden Beispiel gezeigt CurrentProgress auf 100 Prozent festgelegt und true zurückgegeben werden. Mehr ist normalerweise nicht erforderlich. Weitere Informationen zu anderen Aktionen, die möglicherweise von der Implementierung ausgeführt werden müssen, finden Sie im Referenzthema zu 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
    

Hinzufügen weiterer Member zur Klasse bei Bedarf

  1. Fügen Sie nach Bedarf Felder, Eigenschaften und Hilfsmethoden hinzu, um die Klasse zu vervollständigen. Beachten Sie dabei Folgendes:

    • Verwenden Sie Felder und Eigenschaften, um darin untergeordnete Inhaltsobjekte zu speichern.

    • Wenn die Klasse von SPPersistedObject abgeleitet wird, muss der Deklaration der Felder, die dauerhaft in der Konfigurationsdatenbank gespeichert werden sollen, das [Persisted]-Attribut vorangestellt werden. Sie können jedoch nur die folgenden Feldtypen auf diese Weise kennzeichnen: einfache Typen wie beispielsweise Zeichenfolgen, Ganzzahlen und GUIDs, andere SPPersistedObject-Objekte oder SPAutoserializingObject-Objekte oder Auflistungen dieser Objekte. Die Klasse kann beispielsweise kein FileInfo-Feld haben, das mit dem [Persisted]-Attribut gekennzeichnet ist. Wenn die Daten, die dauerhaft gespeichert werden sollen, nicht zu einer dauerhaften Klasse gehören, verwenden Sie einen dauerhaften Ersatz. In der oben gezeigten Beispielimplementierung der DiskSizeRequired-Eigenschaft wird eine Klasse verwendet, von der eine Auflistung von Dateinamen dauerhaft gespeichert und zur Laufzeit zum Erstellen einer temporären Auflistung von FileInfo-Objekten verwendet wird.

    • Wenn die Klasse mehrere untergeordnete Klassen des gleichen Typs haben kann, erstellen Sie eine Eigenschaft oder ein Feld eines Auflistungstyps oder eines anderen aufzählbaren Typs, um darin eine Auflistung aller untergeordneten Klassen eines bestimmten Typs zu speichern. Dies ist besonders wichtig, wenn vom untergeordneten Typ selbst IBackupRestore implementiert wird. Der Grund ist, dass von der Implementierung der AddBackupObjects(SPBackupRestoreObject)-Methode solche untergeordneten Klassen durchlaufen werden und die AddBackupObjects(SPBackupRestoreObject)-Methoden der einzelnen untergeordneten Klassen aufgerufen werden sollten. Weitere Informationen finden Sie weiter oben im Verfahrensschritt für das Implementieren der AddBackupObjects(SPBackupRestoreObject)-Methode.

  2. Fügen Sie der Klasse Konstruktoren hinzu, um die Felder und Eigenschaften der Klasse nach Bedarf zu initialisieren. Wenn die Klasse von SPPersistedObject abgeleitet wird, muss mindestens ein Konstruktor vorhanden sein, von dem das Objekt benannt und einem übergeordneten Objekt zugewiesen wird. Normalerweise werden für einen solchen Konstruktor mindestens diese beiden Argumente verwendet:

    • Ein String-Argument, das dem Namen des Inhaltsobjekts entspricht.

    • Ein SPPersistedObject-Argument, das das übergeordnete Objekt des Inhaltsobjekts darstellt.

    Von diesem Konstruktor muss der Basiskonstruktor aufgerufen werden, für den die gleichen zwei Argumente verwendet werden können. Der folgende Code ist ein Beispiel dafür.

    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
    

    Sie müssen SPFarm.Local als übergeordnetes Objekt übergeben, wenn das Inhaltsobjekt das oberste Objekt in einer Struktur aus benutzerdefinierten IBackupRestore-Objekten ist. Wenn der benutzerdefinierte Komponententyp immer das oberste Objekt ist, lassen Sie das SPPersistedObject-Argument weg, und codieren Sie im Aufruf des Basiskonstruktors einen festen Verweis auf SPFarm.Local. Der folgende Code ist ein Beispiel dafür:

    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
    

    Wenn Objekte der Klasse immer den gleichen Namen haben, können Sie das String-Argument weglassen und den Namen im Aufruf des Basiskonstruktors fest codieren. (Wenn alle Objekte eines bestimmten Typs den gleichen Namen haben, sollte für ein bestimmtes übergeordnetes Objekt nie mehr als ein untergeordnetes Objekt dieses Typs vorhanden sein. Entsprechend sollte in der gesamten Farm nie mehr als ein Objekt dieses Typ vorhanden sein, wenn das Objekt ein untergeordnetes Objekt der Farm ist.)

  3. Kompilieren Sie das Klassenprojekt.

    VorsichtVorsicht

    Geben Sie der Assembly einen starken Namen, und platzieren Sie die Assembly im globalen Assemblycache (Global Assembly Cache, GAC).

So erstellen Sie ein Objekt der Klasse und legen dieses als untergeordnetes Objekt der Farm fest

  1. Starten Sie ein neues Konsolenanwendungsprojekt in Visual Studio.

  2. Fügen Sie dem Projekt einen Verweis auf die DLL der benutzerdefinierten Komponentenklasse hinzu.

  3. Fügen Sie eine using-Anweisung für Microsoft.SharePoint.Administration hinzu.

  4. Fügen Sie eine using-Anweisung für den Namespace hinzu, den Sie in der benutzerdefinierten Komponentenklasse verwendet haben (oder verwenden Sie einfach in der Konsolenanwendung den gleichen Namespace).

  5. Fügen Sie der Main-Methode des Projekts einen Aufruf des Konstruktors der benutzerdefinierten Komponentenklasse hinzu. Wenn Sie eine Hierarchie aus benutzerdefinierten Typen erstellt haben, rufen Sie den Konstruktor der obersten Klasse auf.

  6. Stellen Sie bei Bedarf dem Aufruf des Konstruktors der Komponente Code voran, mit dem Parameter für den Konstruktor erstellt werden.

  7. Nach dem Aufruf des Konstruktors der Komponente sollte die Update-Methode des Komponentenobjekts aufgerufen werden. Im folgenden Beispiel wird gezeigt, was in der Main-Methode enthalten sein sollte:

    MyContentComponent myContentObject = new MyContentComponent("component name", SPFarm.Local);
    myContentObject.Update();
    
    Dim myContentObject As New MyContentComponent("component name", SPFarm.Local)
    myContentObject.Update()
    
  8. Kompilieren Sie die Anwendung, und führen Sie sie aus.

  9. Navigieren Sie in der Zentraladministrationsanwendung zu Vorgänge | Sicherung durchführen. Das Objekt sollte auf der Seite Sicherung ausführen als untergeordnetes Objekt der Farm angezeigt werden.

    HinweisHinweis

    Im Abschnitt Beispiel weiter unten finden Sie ein Beispiel für eine Konsolenanwendung zum Erstellen und Löschen benutzerdefinierter Inhaltsobjekte.

Ratschläge für die Entwicklung

Die folgenden Tipps können beim Entwickeln benutzerdefinierter Inhaltsklassen hilfreich sein, insbesondere da Sie dabei wahrscheinlich mehrfach Objekte erstellen und der Farm hinzufügen.

Zu berücksichtigende Punkte

  1. Wenn Sie das Objekt aus der Konfigurationsdatenbank löschen möchten, verwenden Sie Delete().

  2. Wenn Sie obj.Update() aufrufen und bereits ein Objekt der gleichen Klasse als obj mit dem gleichen Name-Eigenschaftswert und dem gleichen übergeordneten Objekt in der Konfigurationsdatenbank vorhanden ist, wird eine Ausnahme ausgelöst. Es gibt eine überladene Version von Update, die möglicherweise besser geeignet ist.

  3. Im zweiten Abschnitt Beispiel weiter unten finden Sie ein Beispiel für eine Konsolenanwendung, mit der benutzerdefinierte Objekte in der Konfigurationsdatenbank hinzugefügt oder gelöscht werden können.

  4. Führen Sie nach jeder erneuten Kompilierung der IBackupRestore-Klasse iisreset auf der Befehlszeile aus. Möglicherweise müssen Sie auch den Server neu starten.

  5. Für die verschiedenen IBackupRestore.On*-Methoden kann ein SPBackupInformation-Parameter oder ein SPRestoreInformation-Parameter verwendet werden. Sie können die Member der Methoden zu Debuggingzwecken verwenden. Besonders hilfreich ist die LogLog-Methode.

Beispiel

Im folgenden Code wird eine benutzerdefinierte Komponente implementiert, die eine einzelne Datei Web.config auf einem Front-End-Server darstellt. Ersetzen Sie TestSite im Dateipfad in der Konstruktorimplementierung durch einen Verzeichnisnamen auf dem Testserver. Die kompilierte Assembly muss einen starken Namen haben und im GAC installiert sein.

Das Beispiel nach der Klassenimplementierung enthält Code für eine einfache Konsolenanwendung, mit der die Komponente als untergeordnete Komponente der Farm registriert oder aus der Farm gelöscht wird.

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

Mit der folgenden Konsolenanwendung wird das Inhaltsobjekt in der Konfigurationsdatenbank hinzugefügt oder gelöscht.

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

Siehe auch

Aufgaben

Gewusst wie: Programmgesteuertes Sichern von Inhalten

Gewusst wie: Programmgesteuertes Wiederherstellen von Inhalten

Gewusst wie: Programmgesteuerte Sicherung und Wiederherstellung einer einzelnen Websitesammlung

Gewusst wie: Erstellen einer Datenbankklasse, die aus einem Snapshot wiederhergestellt werden kann

Gewusst wie: Erstellen einer Klasse, die in reine Konfigurationssicherungen und -wiederherstellungen einbezogen wird

Referenz

Microsoft.SharePoint.Administration.Backup

Backup

Restore

Konzepte

Programmieren mit dem Sicherungs-/Wiederherstellungsobjektmodell von SharePoint Foundation