I have always struggled with SPMT PowerShell because the use is not really intuitive and comparing to UI tool it does not offer so many options. One of the things that really bothered me was hot to migrate a SharePoint web or sub web to a new site collection and I found out that only option is to use JSON tasks to be able to achieve this.

# Path to the CSV file with source-target pairs
$csvPath = "C:\temp\Allwebs.csv"
# Import CSV and specify column headers
$pairs = Import-Csv -Path $csvPath -Delimiter ";"

# Define common settings for each task
$settings = @{
    MigrateFileVersionHistory = $true
    KeepAllVersions = $true
    MigrateHiddenItems = $true
    PreservePermission = $true
    EnableIncremental = $true
    MigrateOneNoteNotebook = $true    
}


# Initialize task list
$tasks = @()

# Build tasks from CSV input
foreach ($pair in $pairs) {
    $task = @{
        SourcePath = $pair.SourcePath
        TargetPath = $pair.TargetPath
        Settings = $settings
		Items=@{ SubSites = @() }
    }
    $tasks += $task
}

# Wrap in the main JSON structure
$jsonObject = @{ Tasks = $tasks }

# Convert to JSON string with depth for nested objects
$jsonOutput = $jsonObject | ConvertTo-Json -Depth 5

# Output JSON to file
$outputPath = "C:\temp\migration_tasks-1.json"
$jsonOutput | Out-File -Encoding UTF8 -FilePath $outputPath

Write-Host "Migration JSON file created: $outputPath"

This code goes through a list of SharePoint webs that you intent to migrate and creates a JSON task to initiate the migration.

After you have the JSON file created, you can actually use SPMT PowerShell module and start you migration. The script is as follows:

Import-Module Microsoft.SharePoint.MigrationTool.PowerShell


$onpremCred=Get-Credential -Message "Enter On-prem creds"
$spoCred=Get-Credential -Message "Enter SPO Creds"


#Register the SPMT session with SPO credentials#
Register-SPMTMigration -SPOCredential $spoCred -Force -MigrateAllSiteFieldsAndContentTypes $true -MigrateFileVersionHistory $true -KeepAllVersions $true `
        -AutomaticUserMapping $true -PreserveUserPermissionsForSharePointSource $true -MigrateSiteSettings ONLY_TITLE_LOGO -WorkingFolder C:\SPMT -LookupReferencePolicy FIND_ALL_REFERENCE `
        -DisableNoScriptDuringMigration $true -MigrateNavigation $true


$jsonItems = Get-Content -Raw -Path  "C:\temp\migration_tasks-1.json" | ConvertFrom-Json

ForEach ($taskItem in $jsonItems.Tasks)
{
    $jsonString = ConvertTo-Json $taskItem -Depth 100
    Add-SPMTTask -JsonDefinition $jsonString -SharePointSourceCredential $onpremCred
}


$timer=[System.Diagnostics.Stopwatch]::StartNew()
$timer.Start()


Start-SPMTMigration -NoShow

$session = Get-SPMTMigration



# Query migration status every 5 seconds until migration is finished
while ($session.Status -ne "Finished")
{
    Write-Host "Session status: $($session.Status) | Task count: $i" -BackgroundColor Yellow -ForegroundColor Black
    $i=1
    # Query migration progress of each tasks
    Foreach ($taskStatus in $session.StatusOfTasks)
    {  
        if($($taskStatus.MigratingProgressPercentage) -ne 100){
          
            Write-Host "$($taskStatus.SourceURI ) => $($taskStatus.TargetURI) Complete: $($taskStatus.MigratingProgressPercentage)% | Scanned: $($taskStatus.NumScannedTotalFiles) | ToMig: $($taskStatus.NumFileWillBeMigrated) | ActualMig: $($taskStatus.NumActuallyMigratedFiles)"
            Add-Content -Value "$($taskStatus.SourceURI ) => $($taskStatus.TargetURI) Complete: $($taskStatus.MigratingProgressPercentage)% | Scanned: $($taskStatus.NumScannedTotalFiles) | ToMig: $($taskStatus.NumFileWillBeMigrated) | ActualMig: $($taskStatus.NumActuallyMigratedFiles)" `
                        -Path "C:\SPMTLog\MigLog-$(Get-Date -uformat "%Y-%m-%d").txt"
            $i++
       }

    }
    Write-Host "$("-"*50)" -BackgroundColor Yellow -ForegroundColor Black
    Start-Sleep -Seconds 60
}
$timer.Stop()

$timer.Elapsed

Hope it helps someone with SPMT migrations.

Posted in

Leave a comment