このスクリプトを開発して、GUI を手動でクリックしなくても Sitecore ワークフローを一連のアイテム全体に適用できるようにしました。うまく機能することにかなり満足していますが、ただ遅いだけです。スクリプトは次のとおりです。
Import-Module 'C:\Subversion\CMS Build\branches\1.2\sitecorepowershell\Sitecore.psd1'
# Hardcoded IDs of workflows and states
$ContentApprovalWfId = "{7005647C-2DAC-4C32-8A09-318000556325}";
$ContentNoApprovalWfId = "{BCBE4080-496F-4DCB-8A3F-6682F303F3B4}";
$SettingsWfId = "{7D2BA7BE-6A0A-445D-AED7-686385145340}";
#new-psdrive *REDACTED*
set-location m-rocks:
function ApplyWorkflows([string]$path, [string]$WfId) {
Write-Host "ApplyWorkflows called: " $path " - " $wfId;
$items = Get-ChildItem -Path $path;
$items | foreach-object {
if($_ -and $_.Name) {
$newPath = $path + '\' + $_.Name;
$newPath;
} else {
Write-host "Name is empty.";
return;
}
if($_.TemplateName -eq "Folder" -or $_TemplateName -eq "Template Folder") {
# don't apply workflows to pure folders, just recurse
Write-Host $_.Name " is a folder, recursing.";
ApplyWorkflows $newPath $wfId;
}
elseif($_.TemplateName -eq "Siteroot" -or $_.TemplateName -eq "InboundSiteroot") {
# Apply content-approval workflow
Set-ItemProperty $newPath -name "__Workflow" $ContentApprovalWfId;
Set-ItemProperty $newPath -name "__Default workflow" $ContentApprovalWfId;
# Apply content-no-approval workflow to children
Write-Host $_.Name " is a siteroot, applying approval workflow and recursing.";
ApplyWorkflows $newPath $ContentNoApprovalWfId;
}
elseif($_.TemplateName -eq "QuotesHomePage") {
# Apply settings workflow to item and children
Write-Host $_.Name " is a quotes item, applying settings worfklow recursing.";
Set-ItemProperty $newPath -name "__Workflow" $SettingsWfId;
Set-ItemProperty $newPath -name "__Default workflow" $SettingsWfId;
ApplyWorkflows $newPath $SettingsWfId;
}
elseif($_.TemplateName -eq "Wildcard")
{
Write-Host $_.Name " is a wildcard, applying workflow (and halting).";
Set-ItemProperty $newPath -name "__Workflow" $ContentApprovalWfId;
Set-ItemProperty $newPath -name "__Default workflow" $ContentApprovalWfId;
}
elseif($_ -and $_.Name) {
# Apply passed in workflow and recurse with passed in workflow
Write-Host $_.Name " is a something else, applying workflow and recursing.";
Set-ItemProperty $newPath -name "__Workflow" $WfId;
Set-ItemProperty $newPath -name "__Default workflow" $WfId;
ApplyWorkflows $newPath $wfId;
}
}
}
ApplyWorkflows "sitecore\Content\" $ContentNoApprovalWfId;
1 秒弱で 1 つのアイテムを処理します。その進行にはいくつかの一時停止があります - 証拠は、これがGet-ChildItem
多くのアイテムを返すときであることを示唆しています. 試してみたいことがたくさんありますが、サイトの 1 つに対してまだ実行中です。約 50 分が経過しましたが、おそらく 50% 完了しているように見えます。幅優先で動作しているように見えるため、何が行われ、何が行われていないかを正確に把握するのは困難です。
では、何が私を遅くしているのでしょうか?
パスの構築と検索ですか?$_
またはを介して現在のアイテムの子を取得しようとしました$_.Name
が、常にルートである現在の作業ディレクトリを検索し、アイテムを見つけることができません。再帰ごとにディレクトリを変更すると、より高速になりますか?
それを行き詰まらせているのは出力ですか?出力がなければ、それがどこにあるのか、まだ機能しているのかわかりません。それがどこにあるのか、何回実行されたのかなどを示す他の方法はありますか?
Get-ChildItem -r
フィルターセットを使用してそれらをループするより良いアプローチはありますか? もしそうなら、最初のスクリプトのいくつかの条件をフィルター セットに組み込む最初の試みは非常に高く評価されます。私は PowerShell を初めて使用するので、コードに 1 つまたは 2 つ以上の改善が必要であると確信しています。
子供がいない場合でも、常に再帰ビットを呼び出すということですか? ここのコンテンツ ツリーは非常に幅広く、子を持たない非常に多くのリーフがあります。子アイテムが存在するかどうかを確認するにはどうすればよいでしょうか?
最後に、私たちが持っている PowerShell プロバイダー (PSP) は完全ではありません。Get-Item の実装が機能していないように見えるため、代わりにすべてが Get-ChildItem でほぼ完全に記述されています。私たちの Sitecore.Powershell.dll は、バージョン 0.1.0.0 であると言っています。アップグレードは役に立ちますか?より新しいものはありますか?
編集:ついに完成しました。出力を数えたところ、1857 個のアイテムがあり、1 分あたり平均 21 個のアイテムで、実行に約 85 分かかりました。思ったより遅くても…
編集:私の最初の実行は、Windows PowerShell ISEを使用した PowerShell 2.0 でした。Sitecore PowerShell プラグイン モジュールまたはコミュニティを試したことはありません。昨日まで存在すら知らなかった(-_-;)
PowerShell 3.0 にアップグレードした後、別の実行を試みました。ローカルで開始して、ラップトップからスクリプトを実行し、リモート サーバーに接続しても、顕著な違いはありませんでした。ホスティング ボックスに PowerShell 3.0 をインストールし、そこからスクリプトを実行したところ、おそらく 20 ~ 30% の速度向上が見られました。だから、それは私が望んでいた特効薬ではありません.これをベビーシッターしてバッチで実行する必要がないようにするには、1桁または2桁の改善が必要です. 私は現在、以下の素晴らしい回答で提案されている実際のスクリプトの改善のいくつかをいじっています。私は自分に合ったものを投稿します。