3

このスクリプトを開発して、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桁の改善が必要です. 私は現在、以下の素晴らしい回答で提案されている実際のスクリプトの改善のいくつかをいじっています。私は自分に合ったものを投稿します。

4

3 に答える 3

5

個人的には、Rocks の PowerShell 実装よりもコミュニティの PowerShell 実装を使い始めた場合に得られる最大のブーストだと思います。

理由を説明しましょう。

ツリー全体をトラバースしているため、ブランチ内のすべてのノードにアクセスする必要があります。つまり、少なくとも 1 回は Rocks Web サービスを読み取って移動する必要があります。次に、プロパティを保存するたびに、別の Web サービス呼び出しが行われます。

コミュニティ コンソールでスクリプトを実行しましたが、3724 個のアイテムに対して約 25 秒かかりました。(値が私のシステムに関連していなかったので、変更を削除しました)。

シンプルな

Get-ChildItem -recurse

私の 3724 アイテム ツリーでは、コミュニティ コンソールでは 11 秒かかりましたが、Rocks 実装では 48 秒かかりました。

スクリプトのコミュニティ実装で使用できる追加の微調整は、次のような Sitecore クエリを使用することです。

get-item . -Query '/sitecore/content/wireframe//*[@@TemplateName="Template Folder"]'

それらのアイテムのみを関数に送信します

それは Rocks コンソールが正しく書かれていないことを意味するものではなく、Rocks コンソールの設計上の選択とそのターゲットが異なることを意味するだけです。

コミュニティ コンソールはこちらにあります: http://bit.ly/PsConScMplc

于 2013-08-02T09:19:14.827 に答える
0

私が目にする最も明らかな問題は、関数の呼び出しごとにファイルを2 回繰り返し処理していることです。

function ApplyWorkflows([string]$path, [string]$WfId) {
    Write-Host "ApplyWorkflows called: " $path " - " $wfId;


    # this iterates through all files and assigns to $items
    $items = Get-ChildItem -Path $path;

    # this iterates through $items for a second time
    $items | foreach-object {  # foreach-object is slower than for (...)

また、 foreach-object へのパイプは、従来のforキーワードを使用するよりも遅くなります。

于 2013-08-02T00:39:36.587 に答える