Start-SPMigration

PowerShell-Skript fuer die Migration von SharePoint On-Premise Inhalten ueber das serverseitige Objektmodell.

Das Skript kann:

  • Dokumentbibliotheken exportieren
  • Dateien inklusive Metadaten exportieren
  • normale SharePoint-Listen und deren Eintraege exportieren
  • exportierte Inhalte wieder in ein Ziel-Web importieren
  • beim Export automatisch eine JSON-MappingTable fuer Feld-, Listen- und Bibliotheks-Mappings erzeugen
  • beim Import dieselbe MappingTable fuer Container- und Metadaten-Mappings verwenden

Voraussetzungen

  • SharePoint On-Premise Server
  • Ausfuehrung auf einem Server mit installiertem SharePoint PowerShell-Modul
  • Berechtigungen auf Quell- und Ziel-Web
  • PowerShell mit Zugriff auf SharePointServer

Das Skript laedt intern:

Import-Module SharePointServer

Dateien im Projekt

  • Start-SPMigration.ps1: Hauptskript fuer Export und optionalen Import
  • FieldMapping.sample.csv: altes CSV-Beispiel fuer Feldmapping, weiterhin als Fallback lesbar
  • column-mapping-defaults.sample.json: Beispiel fuer wiederverwendbare Column-Mapping-Defaults

Exportierte Struktur

Beim Export entsteht unter -OutputPath folgende Struktur:

OutputPath
|-- Files
|   |-- <Bibliothek>
|   |   |-- Unterordner
|   |   |   |-- Dokument.pdf
|   |   |   |-- Dokument.pdf.properties.json
|-- Lists
|   |-- ListeA.json
|-- MappingTable.json
|-- manifest.csv

Dateien

  • Die Originaldatei wird in Files\<Bibliothek>\... gespeichert.
  • Die Metadaten liegen direkt daneben als Sidecar-Datei: Dateiname.ext.properties.json
  • manifest.csv enthaelt ausserdem Container-Eintraege fuer Listen und Dokumentbibliotheken

Listen

  • Pro Liste wird genau eine JSON-Datei unter Lists\ erzeugt.
  • Die Eintraege enthalten insbesondere:
    • ContentTypeId
    • FieldValues
    • FieldTextValues
    • Fields

Wichtige Metadaten

Fuer den Import sind vor allem diese Informationen relevant:

  • FieldValues
  • FieldTextValues
  • ContentTypeId
  • interne Feldnamen (InternalName)

Der Name des Inhaltstyps wird bewusst nicht als fuehrende Importinformation verwendet, da er sich im Zielsystem unterscheiden kann.

MappingTable.json

Beim Export wird automatisch eine MappingTable.json erzeugt. Diese Datei enthaelt:

  • LibraryMappings: Mapping von Quellbibliothek auf Zielbibliothek
  • ListMappings: Mapping von Quellliste auf Zielliste
  • MetadataColumnMappings.SystemColumns: erkannte Systemspalten
  • MetadataColumnMappings.CustomColumns: erkannte eigene Fachspalten

Beispiel:

{
  "SchemaVersion": 1,
  "GeneratedAtUtc": "2026-04-15T08:00:00.0000000Z",
  "SourceWebUrl": "http://sharepoint/sites/Quelle",
  "LibraryMappings": [
    {
      "ObjectType": "DocumentLibrary",
      "SourceTitle": "Documents",
      "TargetTitle": "Dokumente",
      "BaseType": "DocumentLibrary",
      "BaseTemplate": 101,
      "RootFolderUrl": "/Documents",
      "Hidden": false
    }
  ],
  "ListMappings": [
    {
      "ObjectType": "List",
      "SourceTitle": "TestListe",
      "TargetTitle": "ZielTestListe",
      "BaseType": "GenericList",
      "BaseTemplate": 100,
      "RootFolderUrl": "/Lists/TestListe",
      "Hidden": false
    }
  ],
  "MetadataColumnMappings": {
    "SystemColumns": [
      {
        "ObjectType": "List",
        "ContainerSourceTitle": "Kalender",
        "SourceInternalName": "EventDate",
        "SourceCanonicalInternalName": "EventDate",
        "SourceSupportingInternalNames": [],
        "TargetInternalName": "EventDate",
        "DisplayName": "Beginnt",
        "TypeAsString": "DateTime",
        "Hidden": false,
        "ReadOnly": false,
        "Sealed": true,
        "IsSystemColumn": true,
        "ImportSupported": true
      }
    ],
    "CustomColumns": [
      {
        "ObjectType": "DocumentLibrary",
        "ContainerSourceTitle": "Documents",
        "SourceInternalName": "SecurityClearance",
        "SourceCanonicalInternalName": "SecurityClearance",
        "SourceSupportingInternalNames": [
          "SecurityClearance_0"
        ],
        "TargetInternalName": "GMNSecurityClearance",
        "DisplayName": "Security Clearance",
        "TypeAsString": "TaxonomyFieldType",
        "Hidden": false,
        "ReadOnly": false,
        "Sealed": false,
        "IsSystemColumn": false,
        "ImportSupported": true
      }
    ]
  }
}

Fuer das Mapping ist vor allem relevant:

  • TargetTitle: Zielname von Liste oder Bibliothek
  • TargetInternalName: Zielfeld fuer die exportierte Metadatenspalte
  • SystemColumns: SharePoint-Standardfelder wie EventDate, EndDate, Title oder Created
  • CustomColumns: eigene Fachspalten, die im Ziel oft umbenannt oder anders aufgebaut sind
  • SourceSupportingInternalNames: technische Begleitspalten wie _0 werden nur noch informativ aufgefuehrt und nicht separat gemappt
  • ImportSupported: steuert, ob eine Spalte beim Import ueberhaupt beruecksichtigt wird
  • Taxonomy-Felder werden beim Import ueber den exportierten TermGuid gesetzt; dabei wird angenommen, dass derselbe Term im Ziel bereits mit identischer GUID existiert
  • Die exportierte WssId wird bewusst nicht uebernommen: Sie ist nur innerhalb der Quell-SiteCollection gueltig. SharePoint loest beim Setzen des Feldwerts die zielseitige WssId auf und legt den Eintrag in der TaxonomyHiddenList bei Bedarf selbst an. Die Hidden List soll deshalb nicht separat migriert oder vorab befuellt werden.

Wenn eine Ziel-Liste oder Ziel-Bibliothek nicht existiert, gibt das Skript eine Warnung aus, dass dieser Container manuell angelegt werden soll.

Column Mapping Defaults

Wenn Bibliotheks- und Listen-Mappings je Migration unterschiedlich sind, die Spalten-Mappings aber gleich bleiben, kann die GUI eine separate Column-Defaults-Datei verwenden.

  • Die MappingTable.json bleibt migrationsspezifisch und enthaelt weiterhin LibraryMappings, ListMappings und die konkret angewendeten MetadataColumnMappings.
  • Die Defaults-Datei enthaelt nur wiederverwendbare Spaltenregeln unter Rules.
  • In der GUI kann ein Defaults-Pfad im Feld ColumnDefaults gepflegt werden. Nach einem Export werden vorhandene Defaults automatisch auf die frisch geladene MappingTable.json angewendet und gespeichert.
  • Mit Anwenden koennen Defaults erneut auf die aktuelle MappingTable gelegt werden. Danach bleiben manuelle Anpassungen pro Migration weiterhin moeglich.
  • Mit Speichern erzeugt die GUI aus den aktuellen Column-Mappings ein Defaults-Template. Gleichartige Spalten werden dabei auf ContainerSourceTitle = "*" generalisiert; widerspruechliche Regeln bleiben container-spezifisch.

Regeln werden von spezifisch nach allgemein angewendet:

  • ObjectType + ContainerSourceTitle + SourceInternalName
  • ObjectType + * + SourceInternalName
  • * + ContainerSourceTitle + SourceInternalName
  • * + * + SourceInternalName

Beispiel:

{
  "SchemaVersion": 1,
  "TemplateType": "ColumnMappings",
  "Rules": [
    {
      "ObjectType": "*",
      "ContainerSourceTitle": "*",
      "SourceInternalName": "SecurityClearance",
      "TargetInternalName": "GMNSecurityClearance",
      "ImportSupported": true
    }
  ]
}

Parameter

Pflichtparameter

  • SourceUrl: Quell-Web fuer den Export
  • TargetUrl: Ziel-Web fuer den Import

OutputPath ist optional. Standard ist .\SPMigrationOutput im aktuellen Verzeichnis.

Exportparameter

  • Export: fuehrt den Export aus
  • IncludeHiddenLibraries: exportiert auch versteckte Bibliotheken
  • IncludeHiddenLists: exportiert auch versteckte Listen

Importparameter

  • Import: fuehrt den Import aus einem vorhandenen Exportordner aus
  • MappingTable: JSON-Datei mit Listen-, Bibliotheks- und Spalten-Mappings
  • ImportFiles: importiert nur Dateien/Bibliotheken
  • ImportLists: importiert nur Listen
  • Overwrite: ueberschreibt vorhandene Dateien beim Import

Hinweis:

  • Wenn weder ImportFiles noch ImportLists gesetzt sind, werden beim Import beide Bereiche verarbeitet.
  • Wird MappingTable nicht angegeben, verwendet das Skript standardmaessig OutputPath\MappingTable.json.
  • Die alte CSV-Variante wird fuer reines Feldmapping weiterhin als Fallback gelesen.
  • Werden keine Schalter gesetzt, leitet das Skript den Modus weiterhin aus SourceUrl und TargetUrl ab.
  • Wenn Overwrite nicht gesetzt ist und eine Datei bereits existiert, wird bei aktiver Versionierung eine neue Version geschrieben; ohne Versionierung wird die Datei uebersprungen.
  • Nicht importierbare Systemfelder wie Attachments, Created, Modified, Author oder Editor werden automatisch aus der MappingTable herausgehalten bzw. beim Import uebersprungen.
  • Vor dem Speichern prueft das Skript fehlende Pflichtfelder. Wenn ein einzelnes Listen- oder Datei-Metadatenobjekt trotzdem nicht gespeichert werden kann, wird es mit Kontext-Warnung uebersprungen und der Import laeuft weiter.
  • Beim Listenimport legt das Skript bei Bedarf ein verstecktes Textfeld StartSPMigrationSourceUniqueId in der Zielliste an. Wiederholte Imports aktualisieren damit vorhandene Elemente anhand der exportierten Source-UniqueId statt sie erneut anzulegen.

Beispiele

Nur Export

.\Start-SPMigration.ps1 `
  -SourceUrl "http://sharepoint/sites/Quelle" `
  -Export `
  -IncludeHiddenLists `
  -IncludeHiddenLibraries

Nur Import

.\Start-SPMigration.ps1 `
  -TargetUrl "http://sharepoint/sites/Ziel" `
  -Import `
  -MappingTable "C:\Temp\SP-Export\MappingTable.json"

Export, MappingTable anpassen, dann Import

.\Start-SPMigration.ps1 `
  -SourceUrl "http://sharepoint/sites/Quelle" `
  -OutputPath "C:\Temp\SP-Export" `
  -Export

Danach MappingTable.json bearbeiten und dort TargetTitle sowie TargetInternalName anpassen.

Anschliessend:

.\Start-SPMigration.ps1 `
  -OutputPath "C:\Temp\SP-Export" `
  -TargetUrl "http://sharepoint/sites/Ziel" `
  -Import `
  -MappingTable "C:\Temp\SP-Export\MappingTable.json"

Nur Dateien importrelevant ausfuehren

.\Start-SPMigration.ps1 `
  -TargetUrl "http://sharepoint/sites/Ziel" `
  -Import `
  -MappingTable "C:\Temp\SP-Export\MappingTable.json" `
  -ImportFiles `
  -Overwrite

Nur Listen importrelevant ausfuehren

.\Start-SPMigration.ps1 `
  -TargetUrl "http://sharepoint/sites/Ziel" `
  -Import `
  -MappingTable "C:\Temp\SP-Export\MappingTable.json" `
  -ImportLists

Aktuelles Verhalten beim Import

Dokumentbibliotheken

  • Dateien werden in die per MappingTable.json aufgeloeste Zielbibliothek importiert.
  • Unterordner werden bei Bedarf angelegt.
  • Metadaten werden anschliessend ueber die MetadataColumnMappings gesetzt.

Listen

  • Listeneintraege werden neu angelegt oder bei erneutem Import ueber StartSPMigrationSourceUniqueId wiedergefunden und aktualisiert.
  • Feldwerte werden ueber FieldValues, FieldTextValues und MetadataColumnMappings gemappt.

GUI-Logging und Mapping-Bearbeitung

  • Beim Import protokolliert die GUI fuer jeden verarbeiteten Columnwert, ob die Zuweisung am Item erfolgreich war oder mit welchem Fehler sie uebersprungen wurde. Das Log nennt Container bzw. Item sowie Quell- und Zielspalte, schreibt aber nicht den eigentlichen Feldinhalt mit.
  • In den Mapping-Tabs Bibliotheken, Listen, System Columns und Custom Columns kann eine Zeile per Rechtsklick und Zeile loeschen vollstaendig entfernt werden. Beim Speichern wird sie entsprechend nicht mehr in die MappingTable.json geschrieben.

Bekannte Einschraenkungen

  • Die Zielaufloesung kann ueber MappingTable.json mit TargetTitle ueberschrieben werden.
  • Listenanhaenge werden derzeit noch nicht physisch mit importiert.
  • Ordner in normalen Listen werden beim Import derzeit uebersprungen.
  • Fehlende Ziellisten oder Zielbibliotheken werden derzeit nicht automatisch angelegt; das Skript gibt stattdessen eine Warnung zur manuellen Anlage aus.
  • Sehr spezielle Feldtypen koennen je nach Farm-Konfiguration zusaetzliche Anpassungen benoetigen.
  • Das Skript ist fuer SharePoint On-Premise mit serverseitigem Objektmodell gedacht, nicht fuer SharePoint Online.

Empfehlung

Zuerst immer mit -Export testen und die exportierten *.properties.json, Listen-JSONs und die MappingTable.json pruefen. Danach die Zielnamen und Feldmappings vervollstaendigen und erst dann den Import gegen das Zielsystem laufen lassen.

Description
No description provided
Readme 336 KiB
Languages
PowerShell 100%