Microsoft 365 評価ツールはクラシック ページをインベントリしますが、変更は行いません。 評価出力を使用してページ ウェーブを承認し、PnP PowerShell ConvertTo-PnPPage を使用してモダン ページを作成します。
注:
PnP PowerShell はオープン ソース ソリューションであり、アクティブなコミュニティでサポートが提供されています。 Microsoft からのオープン ソース ツールのサポート SLA はありません。
ページ変換ワークフロー
- 完了した評価カバレッジから代表的なページ ウェーブを選択します。
- ブロックしている Web パーツを解決し、インプレース ターゲットまたはクロスサイト ターゲットを選択します。
- テナント所有の PnP PowerShell アプリケーションと必要なアクセス許可を準備します。
- ソースを保持する既定値とログを使用して、代表的なウェーブを変換します。
- ウェーブを展開する前に、生成されたすべてのページを検証します。
開始する前に
次の前提条件を満たします。
- クラシック ページ評価を実行して解釈します。
- スキャンカバレッジの成功から代表的なウェーブを選択します。
- PowerShell 7.4.0 以降と現在の安定した PnP PowerShell リリースをインストールします。
- 対話型 PnP PowerShell 用のテナント所有のMicrosoft Entra アプリケーションを登録します。
- サインインしているユーザーがソース Web とターゲット Web のページを編集できることを確認します。
2024 年 9 月 9 日以降、対話型 PnP PowerShell 認証には、独自のアプリケーション登録とクライアント ID が必要です。
アプリケーションを登録するアカウントは、アプリ登録の作成を許可する必要があります。 テナントの同意ポリシーは、管理者が同意を付与する必要があるかどうかを決定します。
アクセス許可
読み取り専用の Assessment アプリケーションとは別の委任されたアプリケーションを使用します。
| 変換要件 | 委任された SharePoint スコープ |
|---|---|
| ソースを読み取り、モダン ページを作成、保存、発行する | AllSites.Manage |
| また、アイテム レベルの一意のアクセス許可もコピーします | AllSites.FullControl |
サインインしているユーザーのサイトのアクセス許可も適用されます。 アプリケーションの委任されたスコープでは、アクセスできなかったサイトへのアクセス権はユーザーに付与されません。
AllSites.Manageを使用して、生成されたページがそのライブラリからアクセス許可を継承するように-SkipItemLevelPermissionCopyToClientSidePageを追加します。
AllSites.FullControlは、ページの一意のアクセス許可を保持する必要がある場合にのみ使用します。
可能な限り最小限のアクセス許可を持つクラシック ページの移行に関するページを参照してください。
PnP PowerShell をインストールまたは更新する
PnP PowerShell には、PowerShell 7.4.0 以降が必要です。
$PSVersionTable.PSVersion
Install-Module PnP.PowerShell -Scope CurrentUser
PnP PowerShell が既にインストールされている場合は、PowerShell 7.4.0 以降から Update-Module PnP.PowerShell を実行します。
「PnP PowerShell をインストールする」を参照してください。
対話型変換アプリケーションを登録する
次のコマンドは、対話型サインイン用のパブリック クライアント アプリケーションを作成します。
Register-PnPEntraIDAppForInteractiveLogin `
-ApplicationName "Classic Page Transformation" `
-Tenant "<tenant>.onmicrosoft.com" `
-SharePointDelegatePermissions AllSites.Manage `
-SignInAudience AzureADMyOrg
返されたアプリケーション ID をコピーします。 テナントの同意ポリシーによっては、管理者が最初の接続の前に同意を付与する必要がある場合があります。
このパブリック クライアントの登録は、委任された対話型ログインまたはデバイス ログイン用です。 無人認証に必要なアプリケーションのアクセス許可や証明書は提供されません。
手動登録とその他の認証方法については、「PnP PowerShell のEntra ID アプリケーションを登録する」を参照してください。
21Vianet によって動作する GCC High、DoD、または Microsoft 365 の場合は、アプリケーションを登録して接続するときに、一致する -AzureEnvironment 値を指定します。
Register-PnPEntraIDAppForInteractiveLogin コマンドレットと Connect-PnPOnline コマンドレットのリファレンスを参照してください。
評価行を PnP PowerShell にマップする
| 評価フィールド | PnP PowerShell の使用 |
|---|---|
SiteUrl + WebUrl |
Connect-PnPOnlineのソース URL。 |
ListUrl, ListId, PageUrl |
ライブラリとソース ファイルの正確な SitePages ID。 |
PageType |
このワークフローの WikiPage または WebPartPage する必要があります。 |
Layout |
代表的なパターンのグループ化と検証。 |
最初のウェーブ ページを変換する前に、次のものが必要です。
- 成功したサイトと Web カバレッジ。
-
PageTypeは、WikiPageまたはWebPartPageと等しくなります。 - 未解決のマップされていない Web パーツはありません。
-
WebPartCount0 より大きい。 手動レビューの後、この自動化された例の外側にある 0 部構成のページを処理します。 - ライブラリからアクセス許可を継承するソース ページ。
- 検証用に記録されたコンテンツとレイアウトベースライン。
代表的なページ グループを構築する
次のスクリプトは、候補インベントリを作成します。 ページは変換されません。
対象となる Wiki ページと Web パーツ ページは、ページの種類、レイアウト、順序付けされた Web パーツの署名によってグループ化されます。 署名には、Web パーツの種類、マッピング結果、非表示状態、閉じた状態が含まれます。
$pages = Import-Csv .\classicpages.csv
$webParts = Import-Csv .\classicpagewebparts.csv
$partsByPage = @{}
function Get-PageKey {
param($Row)
'{0}|{1}|{2}|{3}' -f $Row.ScanId, $Row.SiteUrl, $Row.WebUrl, $Row.PageUrl
}
foreach ($part in $webParts) {
$key = Get-PageKey $part
if (-not $partsByPage.ContainsKey($key)) {
$partsByPage[$key] = [Collections.Generic.List[object]]::new()
}
$partsByPage[$key].Add($part)
}
$candidates = foreach ($page in $pages) {
$fileName = [IO.Path]::GetFileName($page.PageUrl)
if ($page.PageType -notin @('WikiPage', 'WebPartPage') -or
$page.HomePage -eq 'True' -or
-not $page.ListUrl.EndsWith('/SitePages', [StringComparison]::OrdinalIgnoreCase) -or
$page.WebPartCount -eq '0' -or
$page.MappingPercentage -ne '100' -or
-not [string]::IsNullOrWhiteSpace($page.UnmappedWebParts) -or
$fileName.StartsWith('Migrated_', [StringComparison]::OrdinalIgnoreCase) -or
$fileName.StartsWith('Previous_', [StringComparison]::OrdinalIgnoreCase)) {
continue
}
$key = Get-PageKey $page
if (-not $partsByPage.ContainsKey($key)) {
throw "Web Part rows are missing for $($page.PageUrl)."
}
$signature = (
$partsByPage[$key] |
Sort-Object { [int]$_.WebPartIndex } |
ForEach-Object {
'{0}|Mappable={1}|Hidden={2}|Closed={3}' -f
$_.WebPartTypeShort, $_.IsMappable, $_.Hidden, $_.IsClosed
}
) -join ';'
[pscustomobject]@{
PatternKey = '{0}|{1}|{2}' -f $page.PageType, $page.Layout, $signature
ScanId = $page.ScanId
SiteUrl = $page.SiteUrl
WebUrl = $page.WebUrl
PageUrl = $page.PageUrl
PageType = $page.PageType
ListUrl = $page.ListUrl
ListId = $page.ListId
AssessmentTimeZoneId = [TimeZoneInfo]::Local.Id
Layout = $page.Layout
HomePage = $page.HomePage
WebPartCount = [int]$page.WebPartCount
MappingPercentage = $page.MappingPercentage
UnmappedWebParts = $page.UnmappedWebParts
ModifiedAt = $page.ModifiedAt
WebPartSignature = $signature
IncludePattern = 'True'
Selected = 'False'
ExpectedVisibleContent = ''
ValidationOwner = ''
}
}
$groups = $candidates | Group-Object PatternKey -AsHashTable -AsString
$candidateInventory = foreach ($candidate in $candidates) {
$candidate | Select-Object *,
@{ Name = 'PatternPageCount'; Expression = { $groups[$candidate.PatternKey].Count } }
}
$candidateInventory |
Sort-Object PatternKey, PageUrl |
Export-Csv .\representative-page-groups.csv -NoTypeInformation
representative-page-groups.csv確認し、移行ウェーブに含まれるすべてのPatternKeyから少なくとも 1 つのページを選択します。 Web パーツのプロパティ、リンクされたコンテンツ、またはビジネス動作がパターン内で大きく異なる場合は、追加のページを選択します。
計画移行外のパターンの IncludePattern=False を設定します。 選択したページごとに、 Selected=True を設定し、 ExpectedVisibleContent と ValidationOwnerを入力します。
Assessment CSV を生成したのと同じコンピューターでグループ化手順を実行します。
AssessmentTimeZoneId は、オフセットフリーの ModifiedAt 値を解釈するために使用されるタイムゾーンを記録します。
0 部構成のページ、ホーム ページ、発行ページ、および未解決のマッピングを含むページは、個別のレビュー キューに保持します。
既定の SitePages ライブラリの外側のページも、個別に確認された単一ページ パスに残ります。
ソースを保持する既定値を理解する
注意
-TakeSourcePageName はクラシック ソース ページの名前を変更し、既存のターゲット ページ -Overwrite 置き換えます。 生成されたページが承認され、ロールバック 計画が存在するまで、どちらのオプションも使用しないでください。
| オプション | 第 1 波ガイダンス |
|---|---|
| 既定の名前付け | ソース名を保持し、 Migrated_<source-page>.aspxを作成します。 |
-TakeSourcePageName |
最初は使用しないでください。 クラシック ソースの名前は、 Previous_ プレフィックスで変更されます。 |
-Overwrite |
最初は使用しないでください。 既存のターゲットを自動的に置き換えるのではなく、確認します。 |
-ReplaceHomePageWithDefault |
代表的なウェーブでは使用しないでください。 |
-DontPublish |
最初のウェーブに使用して、生成されたページが検証中に下書きのままになるようにします。 |
-SkipItemLevelPermissionCopyToClientSidePage |
一意のアクセス許可をコピーする必要がない限り、 AllSites.Manage アプリケーションでを使用します。 |
第 1 ウェーブドラフトをロールバックする
バッチ ワークフローでは、クラシック ソース ページの名前が変更または上書きされません。 生成されたドラフトが検証に失敗した場合:
- クラシック ソース ページをサービスに保持します。
-
TransformationStatus=Createdを保持し、ValidationStatus=Failedを設定し、ValidationNotes、ValidatedBy、およびValidatedAtを入力します。 - 失敗した検証証拠を使用して、
TargetPageUrlとLogPathを保持します。 - 調査のために不要になり、organizationのアイテム保持ポリシーで削除が許可されている場合は、Site Pages ライブラリから生成された
Migrated_ドラフトをリサイクルします。 - 候補ルールまたは修復を修正し、ウェーブを再開する前に 1 つの代表的なページを再試行します。
-Overwrite と -TakeSourcePageName はバッチ ワークフローの外部にあります。 別の手順でいずれかのオプションを使用する前に、ページのバージョンと URL を保持し、現在のホーム ページ設定を記録し、非運用サイトで逆の名前変更または復元プロセスをテストし、明示的な承認を取得します。
選択した 1 つの Wiki または Web パーツ ページを変換する
Selected=Trueとマークされた 1 行の代表ページ スクリプトを使用します。 これにより、1 ページのテストは、より大きなウェーブと同じ検証、認証、および結果コントラクトに保持されます。
バッチ スクリプトは、既定の SitePages ライブラリの Wiki ページと Web パーツ ページをサポートします。 ホーム ページ、0 部構成のページ、一意のアクセス許可を持つページ、評価後に変更されたページは除外されます。 個別に確認されたパスを使用して、これらのページを処理します。
すべての代表的なページを変換する
Page wave スクリプト参照の 3 つの埋め込みファイルを同じフォルダーに保存します。
representative-page-groups.csv:
- 計画移行の各変換パターンに
IncludePattern=Trueを設定します。 - 含まれるすべてのパターンの少なくとも 1 つのページに
Selected=Trueを設定します。 - 選択したページごとに
ExpectedVisibleContentとValidationOwnerを入力します。
SharePoint ページを認証または書き込まずに、完全なウェーブをプレビューします。
.\Convert-RepresentativePages.ps1 `
-ManifestPath .\representative-page-groups.csv `
-ClientId "<application-id>" `
-AuthenticationMode Interactive `
-WhatIf `
-Force
プレビュー CSV レコードの PlannedAction と PlannedTargetPageUrl。
-WhatIfは認証されないため、TargetExistsはNotChecked。
認証された読み取り専用プレフライトを実行して、現在のソース、ホーム ページ、アクセス許可、タイムスタンプ、およびターゲットの不在を確認します。
.\Convert-RepresentativePages.ps1 `
-ManifestPath .\representative-page-groups.csv `
-ClientId "<application-id>" `
-AuthenticationMode Interactive `
-PreflightOnly `
-Confirm:$false `
-Force
すべての行は、ライブコンバージョンの前に TransformationStatus=PreflightPassed を報告する必要があります。
影響の大きい確認を使用して対話形式で実行します。
.\Convert-RepresentativePages.ps1 `
-ManifestPath .\representative-page-groups.csv `
-ClientId "<application-id>" `
-AuthenticationMode Interactive `
-Confirm
スクリプトは、各結果をすぐに representative-page-results.csvに書き込みます。 生成されたページは下書きのままであり、作成された各行は ValidationStatus=Pendingで始まります。
[変換されたクラシック ページの検証] に従います。
ValidationStatus=Passed、ValidationNotes、ValidatedBy、およびValidatedAtは、ページがすべての受け入れ条件を満たした後にのみ設定します。
ユーザー指定のすべてのページに展開する
ユーザーが元のrepresentative-page-groups.csvから承認した追加の含まれる行をコピーして、approved-pages.csvを作成します。 生成されたすべてのフィールドを保持し、 ExpectedVisibleContent と ValidationOwnerを入力します。
最初に -PreflightOnly -Confirm:$false -Force を使用して、選択したページ スクリプトを実行します。 すべての行は PreflightPassedを報告する必要があります。
拡張スクリプトを実行します。
.\Convert-SelectedPages.ps1 `
-PagesPath .\approved-pages.csv `
-RepresentativeManifestPath .\representative-page-groups.csv `
-RepresentativeResultsPath .\representative-page-results.csv `
-ClientId "<application-id>" `
-AuthenticationMode Interactive `
-Confirm
スクリプトは、次の場合に展開を拒否します。
- 代表的なマニフェストと結果が一致しません。
- 代表ページは
CreatedとPassedではありません。 - 検証メモ、検証ツール、または検証タイムスタンプがありません。
- PnP PowerShell バージョンまたは 3 つのスクリプト ファイルのいずれかが、代表的な実行とは異なります。
- 承認されたページは、元のマニフェストの変更されていない含まれる行ではありません。
- 承認されたページは、渡された担当者なしでパターンに属します。
展開されたウェーブでは、下書きページも作成され、 selected-page-results.csvが書き込まれます。 発行する前に、これらのページを検証します。
明示的なレビューを必要とするオプション
完全なパラメーター コントラクトに対して生成された ConvertTo-PnPPage コマンドレット リファレンス を使用します。
バッチ スクリプトでは、カスタム Web パーツ マッピング、発行ページ、またはクロスサイト ターゲットはサポートされていません。 個別に確認された単一ページまたは高度な手順を使用して、これらのシナリオを処理します。
これらのオプションは、バッチ ワークフローの外部でのみ確認します。
-
-CopyPageMetadataおよび-CopyPageMetadata。 -
-UrlMappingFile、-UserMappingFile、および-TermMappingFile。 -
-Overwrite承認とロールバック計画後に-TakeSourcePageNameします。
モダン ページ機能のトラブルシューティング
ページウェーブ スクリプトでは、SharePoint 機能は有効になりません。 このトラブルシューティング パスは、サポートされているクラシック チーム サイトにのみ適用されます。 クラシック 発行ポータルでこの機能を有効にしないでください。発行ページを別のクロスサイト発行バックログとモデルにルーティングします。 モダン ページのサポートされるカスタマイズに関するページを参照してください。
Web を管理する権限を持つアカウントに接続し、アクティブ化された Web 機能を一覧表示します。
$source = Connect-PnPOnline `
-Url "https://<tenant>.sharepoint.com/sites/<site>" `
-Interactive `
-ClientId "<application-id>" `
-ReturnConnection
$modernPageFeatureId = [guid]'B6917CB1-93A0-4B97-A84D-7CF49975D4EC'
$modernPageFeature = Get-PnPFeature `
-Scope Web `
-Connection $source |
Where-Object DefinitionId -eq $modernPageFeatureId
if ($modernPageFeature) {
Write-Host "Modern pages feature is active."
}
else {
Write-Host "Modern pages feature is not active."
}
バッチ スクリプトによって使用される委任された AllSites.Manage アプリケーションでは、Web 機能をアクティブ化するのに十分ではありません。 サポートされているクラシック チーム サイトで機能がアクティブでない場合は、サイト所有者の承認を取得し、次の方法で接続します。
- SharePoint
AllSites.FullControlを使用した別の委任されたアプリケーション。 - Web 上のフル コントロールを使用したサインイン アカウント。
$adminConnection = Connect-PnPOnline `
-Url "https://<tenant>.sharepoint.com/sites/<site>" `
-Interactive `
-ClientId "<full-control-application-id>" `
-ReturnConnection
Enable-PnPFeature `
-Identity $modernPageFeatureId `
-Scope Web `
-Connection $adminConnection
機能を有効にした後、認証されたプレフライトを再実行します。
無人認証とその他のページの種類
先ほど作成した委任されたパブリック クライアント アプリケーションは、アプリ専用アクセス用に個別に構成されていない限り、証明書アプリ専用認証では再利用できません。
無人実行の前:
- アプリ専用アクセス用のEntra ID アプリケーションの登録に関するページに従って、アプリ専用の登録と証明書を個別に作成します。
- [必要な PnP PowerShell のアクセス許可を決定する] に従って、すべてのソース サイトの SharePoint アプリケーションのアクセス許可またはサイト割り当てを構成します。
- 必要な管理者の同意を付与します。
-
-PreflightOnly -Confirm:$falseと証明書認証モードでバッチ スクリプトを実行します。 - 認証されたプレフライトがテスト テナントに合格した後にのみ、
-PreflightOnlyを削除します。
重要
証明書パラメーター パスは Pester でテストされますが、ステージ 2 のライブ テナントでは、検証された委任された対話型認証が実行されます。 無人書き込みの前に、テナントで選択したアプリ専用アクセス許可プロファイルを検証します。
発行ページ、ブログ ページ、 SitePages外のページ、ホーム ページ、カスタム Web パーツ マッピング、および SharePoint Server ソースは、バッチ スクリプトではサポートされていません。 次の高度な参照を使用します。
- インプレース変換とクロスサイト変換
- 発行ページの準備
- ページ変換モデルの発行
- ページ変換モデルとカスタム Web パーツ マッピング
- 従来のブログ ページを最新化する
- SharePoint Server からページを変換する
次の手順
- 変換された各ページを検証します。
- すべての代表ページが検証に合格した後にのみ、
Convert-SelectedPages.ps1を実行します。