PnP タイマー ジョブ フレームワークPnP remote timer job framework

PnP タイマー ジョブ フレームワークは、SharePoint サイトに対して動作するバック グラウンド プロセスの作成を容易にするために設計されたクラスのセットです。The PnP Timer Job Framework is a set of classes designed to ease the creation of background processes that operate against SharePoint sites. タイマー ジョブ フレームワークは、オンプレミスの完全信頼コード タイマー ジョブ (SPJobDefinition) に似ています。The timer job framework is similar to on-premises full trust code timer jobs (SPJobDefinition). タイマー ジョブ フレームワークと完全信頼コード タイマー ジョブの主な相違点は、タイマー ジョブ フレームワークはクライアント側 API のみを使用するため、SharePoint の外部で実行できる (かつ実行する必要がある) ことです。The primary difference between the timer job framework and the full trust code timer job is that the timer job framework only uses client-side APIs and therefore can (and should) be run outside of SharePoint. タイマー ジョブ フレームワークを使用することで、SharePoint Online に対して動作するタイマー ジョブの作成が可能になります。The timer job framework makes it possible to build timer jobs that operate against SharePoint Online.

タイマー ジョブを作成したら、スケジュールを設定して実行する必要があります。After a timer job has been created, it needs to be scheduled and executed. 2 つの最も一般的なオプションは、次のとおりです。The two most common options are:

  • ホスティング プラットフォームが Microsoft Azure の場合、タイマー ジョブを Azure WebJobs として展開して実行できます。When Microsoft Azure is the hosting platform, Timer Jobs can be deployed and run as Azure WebJobs.
  • ホスティング プラットフォームが Windows Server の場合 (オンプレミスの SharePoint の場合など)、タイマー ジョブは Windows スケジューラで展開して実行できます。When Windows Server is the hosting platform (e.g. for on-premises SharePoint) Timer Jobs can be deployed and run in Windows scheduler.

タイマー ジョブの概要については、「PnP タイマー ジョブ フレームワークの概要」というビデオを参照してください。このビデオでは、タイマー ジョブ フレームワークを紹介し、タイマー ジョブの単純な例を示します。For a video introduction to timer jobs, see the video Introduction to the PnP timer job framework, which introduces the timer job framework and demonstrates the simple timer job example.

タイマー ジョブの単純な例Simple Timer Job example

このセクションでは、非常に単純なタイマー ジョブを作成する方法を示します。In this section, you will learn how to create a very simple timer job. このサンプルの目的は読者にクイック ビューを提供することです。タイマー ジョブ フレームワークの詳細な説明については後述します。The goal of this sample is to provide the reader a quick view; later on we provide a more detailed explanation of the timer job framework.

注意

「Hello world」サンプルから実際のコンテンツ有効期限ジョブまで、10 種類のタイマー ジョブの例を使用した、より広範な PnP ソリューションについては、「Core.TimerJobs.Samples」を参照してください。Note: For a more extensive PnP solution with ten individual Timer Job examples, from "Hello world" samples to actual content expiration jobs, see https://github.com/SharePoint/PnP/tree/dev/Solutions/Core.TimerJobs.Samples

以降の手順で、単純なタイマー ジョブを作成する方法を示します。The following steps describe how to create a simple timer job.

手順 1: コンソール プロジェクトを作成し、PnP コアを参照するStep 1: Create a Console project and reference PnP Core

「コンソール」タイプの新しいプロジェクトを作成し、次のいずれかの方法で PnP コア ライブラリを参照します。In this first step, create a new project of the type "console" and reference the PnP core library by doing one of the following:

  • Office 365 Developer パターンおよびプラクティスのコア Nuget パッケージをプロジェクトに追加します。Add the Office 365 Developer Patterns and Practices Core NuGet package to your project. v15 (オンプレミス) 用と v16 (Office 365) 用の Nuget パッケージがあります。There's a NuGet package for v15 (on-premises) and for v16 (Office 365). これは優先オプションです。This is the preferred option.
  • 既存の PnP コア ソース プロジェクトを自分のプロジェクトに追加します。Add the existing PnP Core source project to your project. これにより、デバッグ時に PnP コア コードにステップインできるようになります。This will allow you to step into the PnP core code when debugging.

    注意

    ユーザーは、常にこのコードを PnP に追加された最新の変更内容に更新する必要があります。You will be responsible for keeping this code updated with the latest changes added to PnP.

手順 2: タイマー ジョブ クラスを作成し、タイマー ジョブ ロジックを追加するStep 2: Create a Timer Job class and add your Timer Job logic

  1. SimpleJob という名前のタイマー ジョブのクラスを追加します。Add a class for the timer job named SimpleJob.

  2. このクラスに TimerJob 抽象基本クラスを継承させます。Have the class inherit the **** abstract base class.

  3. コンストラクターで、タイマー ジョブに名前 (base("SimpleJob")) を付け、TimerJobRun イベント ハンドラーを接続します。In the constructor give the Timer Job a name (base("SimpleJob")) and connect the **** event handler.

  4. タイマー ジョブ ロジックを TimerJobRun イベント ハンドラーに追加します。Add your timer job logic to the TimerJobRun event handler.

結果は、次のようになります。The result will be similar to the following:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.SharePoint.Client;
using OfficeDevPnP.Core.Framework.TimerJobs;

namespace Core.TimerJobs.Samples.SimpleJob
{
    public class SimpleJob: TimerJob
    {
        public SimpleJob() : base("SimpleJob")
        {
            TimerJobRun += SimpleJob_TimerJobRun;
        }

        void SimpleJob_TimerJobRun(object sender, TimerJobRunEventArgs e)
        {
            e.WebClientContext.Load(e.WebClientContext.Web, p => p.Title);
            e.WebClientContext.ExecuteQueryRetry();
            Console.WriteLine("Site {0} has title {1}", e.Url, e.WebClientContext.Web.Title);
        }
    }
}

手順 3: タイマー ジョブを使用するように Program.cs を更新するStep 3: Update Program.cs to use the Timer Job

前の手順で作成したタイマー ジョブは、実行する必要があります。The timer job created in the previous step still needs to be executed. これを行うには、次の手順で Program.cs を更新します。To do so, update Program.cs by using the following steps:

  1. タイマー ジョブ クラスをインスタンス化します。Instantiate your Timer Job class.

  2. タイマー ジョブの認証の詳細を提供します。Provide the authentication details for the timer job. 次の例では、SharePoint Online に対する認証にユーザー名とパスワードを使用します。Provide the authentication details for the Timer Job. This example uses the user name and password to authenticate against SharePoint Online.

  3. タイマー ジョブ プログラムがアクセスする 1 つ以上のサイトを追加します。Add one or more sites for the timer job program to access. この例では、URL にワイルドカード文字を使用します。This example uses a wild card character in the URL. タイマー ジョブは、このワイルド カード URL と一致するすべてのサイトで動作します。The timer job runs on all sites that match this wild card URL.

  4. Run メソッドを呼び出すことにより、タイマー ジョブを開始します。Start the timer job by calling the Run method.

static void Main(string[] args)
{
    // Instantiate the timer job class
    SimpleJob simpleJob = new SimpleJob();

    // The provided credentials need access to the site collections you want to use
    simpleJob.UseOffice365Authentication("user@tenant.onmicrosoft.com", "pwd");

    // Add one or more sites to operate on
    simpleJob.AddSite("https://<tenant>.sharepoint.com/sites/d*");

    // Run the job
    simpleJob.Run();
}

タイマー ジョブの展開オプションTimer Job deployment options

前の手順は、単純なタイマー ジョブを示しています。The previous step demonstrates a simple timer job. 次の手順では、タイマー ジョブを展開します。The next step is to deploy the timer job.

タイマー ジョブは、ホスティング プラットフォーム上でスケジュールを設定する必要がある .exe ファイルです。A timer job is an .exe file that must be scheduled on a hosting platform. 選択されたホスティング プラットフォームによって、展開が異なります。Depending on the chosen hosting platform, the deployment differs. 次のセクションでは、2 つの最も一般的なホスティング プラットフォーム オプションについて説明します。The following sections describe the two most common hosting platform options:

  • ホスティング プラットフォームとして Azure を使用する。Using Microsoft Azure as the hosting platform
  • ホスティング プラットフォームとして Windows Server を使用する。Using Windows Server as the hosting platform

Azure WebJobs を使用して Azure にタイマー ジョブを展開するDeploy timer jobs to Azure using Azure WebJobs

タイマー ジョブを展開する前に、ユーザーの介入なしにジョブを実行できることを確認します。Before deploying a timer job, ensure that the job can run without user interaction. この記事のサンプルでは、ユーザーにパスワードまたはクライアント シークレットの入力を求めるメッセージが表示されます (詳細は「認証」を参照してください)。これはテスト時は機能しますが、展開時は機能しません。The sample in this article prompts the user to provide a password or client secret (see more in the Authentication section), which works while testing but does not work when deployed. すべての既存のサンプルでは、ユーザーに対して、app.config ファイルを使用したパスワードまたはクライアント シークレットの入力を許可します。The existing samples all allow the user to provide a password or client secret by using the app.config file:

  <appSettings>
    <add key="user" value="user@tenant.onmicrosoft.com"/>
    <add key="password" value="your password goes here!"/>
    <add key="domain" value="Contoso"/>
    <add key="clientid" value="a4cdf20c-3385-4664-8302-5eab57ee6f14"/>
    <add key="clientsecret" value="your clientsecret goes here!"/>
  </appSettings>

app.config ファイルにこれらの変更を追加したら、Visual Studio からタイマー ジョブを実行し、ユーザーの介入なしで動作することを確認します。After these changes are added to the file, run the Timer Job from Visual Studio to confirm that it runs without user interaction.

Azure への実際の展開は、Azure WebJobs に基づきます。The actual deployment to Azure is based on Azure WebJobs. このタイマー ジョブの例を展開するには、次の手順を実行します。To deploy this timer job example, follow these steps:

  1. Visual Studio でプロジェクトを右クリックし、[Azure WebJob として発行] を選択します。Right click the project in Visual Studio and choose Publish as Azure WebJob...

  2. タイマー ジョブのスケジュールを指定してから、[OK] を選択しますProvide a schedule for the timer job, and then choose OK.

  3. 発行先として [Microsoft Azure Websites] を選択します。Choose Microsoft Azure Websites as a publish target. Azure にサインインして、タイマー ジョブをホストする Azure Web サイトを選択するように求められます (必要に応じて新しく作成することもできます)。Select Microsoft Azure Websites as a publish target. You'll be asked to login to Azure and select the Azure Web Site that will host the Timer Job (you can also create a new one if that would be needed)

  4. [発行] を選択し、WebJob を Azure にプッシュします。Press Publish to push the WebJob to Azure

  5. タイマー ジョブが発行されたら、Visual Studio または Azure portal からジョブをトリガーしてその実行を確認できます。Once the Timer Job has been published you can trigger the job and check the job execution from Visual Studio or the Azure management portal.

    Azure portal

  6. また、新しい Azure portal からジョブを選択して、[実行] を選択することにより、タイマー ジョブを実行することもできます。Also, the timer job can be run from the new Azure portal by selecting the job and choosing Run. More details about how to work with WebJobs from the new portal can be found in the article, Run Background tasks with WebJobs. 新しいポータルから WebJobs と連動する方法の詳細については、「Azure App Service で WebJobs を使用してバック グラウンド タスクを実行する」の記事を参照してください。Also, the timer job can be run from the new Azure portal by selecting the job and choosing Run. More details about how to work with WebJobs from the new portal can be found in the article, Run Background tasks with WebJobs.

    Azure portal

注意

Azure WebJob の展開に関する詳細なガイダンスについては、「Office 365 サイト用の Azure WebJobs ("タイマー ジョブ") の使用の開始」を参照してください。For in-depth guidance about deploying an Azure WebJob, see Getting started with Azure WebJobs (timer jobs) for your Office 365 sites.

Windows スケジューラを使用して Windows Server にタイマー ジョブを展開するDeploy timer jobs to Windows Server by using the Windows Scheduler

Windows Server に展開する場合、ユーザーの介入なしにタイマー ジョブを実行する必要があります。When deployed to Windows Server, the timer job must run without user interaction.

  1. 前のセクション「Azure WebJobs を使用して Azure にタイマー ジョブを展開する」で説明したように app.config ファイルを変更します。Modify the app.config file as described in the previous section Deploy timer jobs to Azure using Azure WebJobs.

  2. ジョブのリリース バージョンを、実行するサーバーにコピーします。Copy the release version of your job to the server you want it to run on.

    重要

    サーバー上に追加のファイルまたはプログラムをインストールしなくてもジョブを実行できるよう、関連するアセンブリ、.exe ファイル、および .config ファイルのすべてをコピーします。Copy the release version of your job to the server you want it to run on. Important: Copy all the relevant assemblies, the .exe file and the .config file to ensure the job can run on the server without installing any additional files or programs on the server.

  3. タイマー ジョブの実行をスケジュールします。Schedule the execution of the timer job. 組み込みの Windows タスク スケジューラを使用することをお勧めします。We recommend that you use the built-in Windows Task Scheduler. Windows タスク スケジューラを使用するには、次の手順を実行します。To use the Windows Task Scheduler:

    1. タスク スケジューラを開きます ([コントロール パネル] > [タスク スケジューラ])。Open the Task Scheduler (Control Panel > Task Scheduler).
    2. [タスクの作成] を選択し、タスクを実行する名前とアカウントを指定します。Click on Create Task and specify a name and an account that will execute the task.
    3. [トリガー] を選択して、新しいトリガーを追加します。Choose Triggers and add a new trigger. タイマー ジョブのスケジュールを指定します。Specify the schedule you want for the timer job.
    4. [アクション] を選択して、[プログラムの開始] アクションを選択し、タイマー ジョブの .exe ファイルを選択してから、フォルダーで開始を設定します。Choose Actions and choose the action Start a program, select the timer job .exe file, and then set the start in folder.
    5. [OK] を選択して、タスクを保存します。Click on OK to save the task.

Windows タスク スケジューラ

タイマー ジョブ フレームワークの詳細Timer Job Framework in-depth

このセクションでは、タイマー ジョブ フレームワークの機能と動作について詳しく説明します。This section details the timer job framework features and how they work.

構造Structure

TimerJob クラスは、次のパブリック プロパティ、メソッド、およびイベントが含まれている抽象基本クラスです。The **** class is an abstract base class which contains the following public properties, methods and events:

TimerJob クラスの構造

ほとんどのプロパティとメソッドについては、以降のセクションで詳しく説明します。Most properties and methods will be explained in more detail in the coming sections. The rest of the properties and methods are described here: ここでは、それ以外のプロパティとメソッドについて説明します。Most properties and methods will be explained in more detail in the coming sections. The rest of the properties and methods are described here:

  • IsRunning プロパティ: タイマー ジョブが実行中かどうかを示す値を取得します。IsRunning property: Gets a value indicating whether the timer job is executing. 実行中の場合は true の値に、実行中でない場合は false の値になります。IsRunning property: Gets a value indicating whether the Timer Job is executing. Value of true if executing; false if not executing.
  • Name プロパティ: タイマー ジョブの名前を取得します。Name property: Gets the name of the timer job. 名前は、タイマー ジョブのコンストラクターで最初に設定されます。The name is initially set in the timer job constructor.
  • SharePointVersionプロパティ: SharePoint のバージョンを取得または設定します。SharePointVersion property: Gets or sets the SharePoint version. このプロパティは、読み込まれている Microsoft.SharePoint.Client.dll のバージョンに基づいて自動的に設定されます。通常は変更しないでください。This property is automatically set based on the version of the loaded Microsoft.SharePoint.Client.dll and in general should not change. ただし、v16 CSOM ライブラリを v15 (オンプレミス) 展開で使用する場合はこのプロパティを変更できます。You can, however, change this property in case you want to use the v16 CSOM libraries in a v15 (on-premises) deployment.
  • Version プロパティ: このタイマー ジョブのバージョンを取得します。Version property: Gets the version of this timer job. バージョンは最初、タイマー ジョブのコンストラクターで設定されるか、コンストラクターで設定されない場合は既定値の 1.0 に設定されます。Version property: Gets the version of this Timer Job. The version is initially set in the Timer Job constructor or defaults to 1.0 when not set via the constructor.

タイマー ジョブの実行を準備するには、最初にそれを構成する必要があります。To prepare for a Timer Job run you must first configure it:

  1. 認証設定を提供します。Provide authentication settings.
  2. 範囲 (サイトのリスト) を提供します。Provide a scope, which is a list of sites.
  3. オプションとして、タイマー ジョブのプロパティを設定します。Optionally set Timer Job properties.

タイマー ジョブの実行が開始されると、実行の観点から次の全体的な手順が実行されます。From an execution perspective the following overall steps are taken when a Timer Job run is started:

  1. サイトを解決する: ワイルド カードのサイト URL (https://tenant.sharepoint.com/sites/d* など) が既存のサイトの実際のリストに解決されます。Resolve sites: Wild card site URLs (for example, https://tenant.sharepoint.com/sites/d*) are resolved into an actual list of existing sites. サブサイトの展開が要求された場合は、解決済みのサイト リストがすべてのサブサイトを使用して展開されます。If subsite expanding was requested, the resolved sites list is expanded with all subsites.
  2. 現在のスレッド設定に基づいて作業バッチを作成し、バッチごとに 1 つのスレッドを作成します。Create batches of work based on the current treading settings and create one thread per batch.
  3. スレッドが作業バッチを実行し、リスト内の各サイトに対して TimerJobRun イベントを呼び出します。The threads execute work batches and call the **** event for each site in the list.

各手順の詳細については、次のセクションをご覧ください。Further details on each step can be found in the next sections.

認証Authentication

タイマー ジョブを使用する前に、タイマー ジョブに SharePoint への認証方法を指示する必要があります。Before a timer job can be used, the timer job needs to know how to authenticate back to SharePoint. フレームワークが現在サポートしているのは、AuthenticationType 列挙型、Office365NetworkCredentials、および AppOnly を使用したアプローチです。The framework currently supports the approaches in the AuthenticationType enum: Office365, NetworkCredentials, and AppOnly. また、次のメソッドを使用した場合も、AuthenticationType プロパティが Office365NetworkCredentials、および AppOnly に適切な値に自動的に設定されます。Using the following methods also automatically sets the AuthenticationType property to the appropriate value of Office365, NetworkCredentials, and AppOnly.

次のフローチャートでは、実行する手順の後ろに、それぞれのアプローチの詳細な説明が続きます。The following flowchart shows the steps to take, followed by detailed explanations of each approach.

認証手順のフローチャート

ユーザー資格情報User credentials

Office 365 に対して実行するためのユーザー資格情報を指定するには、次の 2 つのメソッドを使用できます。To specify user credentials for running against Office 365 you can use these 2 methods:

public void UseOffice365Authentication(string userUPN, string password)
public void UseOffice365Authentication(string credentialName)

最初のメソッドは、ユーザー名とパスワードを受け取ります。The first method accepts a user name and password. 2 番目のメソッドでは、Windows 資格情報マネージャーに保存されている汎用の資格情報を指定できます。The second one allows you to specify a generic credential stored in the Windows Credential Manager. 次のスクリーンショットは、bertonline 汎用資格情報を示しています。The following screenshot shows the bertonline generic credential. これを使用してタイマー ジョブを認証するために、2 つ目のメソッドのパラメーターとして bertonline を指定します。To use that to authenticate the timer job, provide bertonline as the parameter of the second method.

Windows 資格情報マネージャー


SharePoint オンプレミスに対して実行するための同様のメソッドがあります。There are similar methods for running against SharePoint on-premises:

public void UseNetworkCredentialsAuthentication(string samAccountName, string password, string domain)
public void UseNetworkCredentialsAuthentication(string credentialName)

アプリ専用App Only

アプリ専用の認証は、テナント スコープ アクセス許可を付与できるため、優先メソッドです。App-only authentication is the preferred method because you can grant tenant-scoped permissions. ユーザー資格情報の場合は、ユーザー アカウントに必要なアクセス許可が付与されている必要があります。App only is the preferred method as you can grant tenant scoped permissions. For user credentials the user account must have the needed permissions.

注意

特定のサイト解決ロジックがアプリ専用の認証で動作しない場合があります。Certain site resolving logic wont work with App-only authentication. 詳細は、次のセクションで説明します。Details can be found in the next section.

アプリ専用の認証用にジョブを構成するには、次のいずれかのメソッドを使用します。To configure the job for app-only authentication, use one of the following methods:

public void UseAppOnlyAuthentication(string clientId, string clientSecret)
public void UseAzureADAppOnlyAuthentication(string clientId, string clientSecret)

Office 365 または SharePoint オンプレミスのいずれかで同じメソッドを使用し、アプリ専用の認証を使用したタイマー ジョブを環境間で容易に移動することができます。The same method can be used for either Office 365 or SharePoint on-premises which makes Timer Jobs using app-only authentication easily transportable between environments.

注意

アプリ専用の認証を使用する場合は、AuthenticationType.AppOnly で動作しない API が使用されていると、タイマー ジョブ ロジックが失敗します。When you use app-only your Timer Job logic will fail when APIs are used that do not work with AuthenticationType.AppOnly. 一般的な例として、検索 API、分類ストアへの書き込み、およびユーザー プロファイル API の使用があります。Typical samples are the Search API, writing to the taxonomy store, and using the user profile API.

実行するサイトSites to operate on

タイマー ジョブを実行する場合は、それを実行する 1 つ以上のサイトが必要です。When a timer job runs, it needs one or more sites to run against.

タイマー ジョブにサイトを追加するAdd sites to a timer job

タイマー ジョブにサイトを追加するには、次のメソッドのセットを使用します。To add sites to a timer job, use the following set of methods:

public void AddSite(string site)
public void ClearAddedSites()

サイトを追加するには、完全修飾 URL (https://tenant.sharepoint.com/sites/dev など) とワイルドカード URL のどちらかを指定します。To add a site, specify either a fully qualified URL (for example, https://tenant.sharepoint.com/sites/dev) or a wild card URL.

ワイルドカード URL は、アスタリスク (*) で終わる URL です。A wild card URL is a URL that ends with an asterisk (*). * は 1 つしか使用できず、URL の最後の文字にする必要があります。Only one single * is allowed and it must be the last character of the URL. ワイルドカード URL のサンプルが https://tenant.sharepoint.com/sites/* です。この URL は、そのサイトの管理対象パスの下のすべてのサイト コレクションを返します。A sample wild card URL is https://tenant.sharepoint.com/sites/*, which returns all the site collections under the managed path of that site. 別の例として、https://tenant.sharepoint.com/sites/dev* は、URL に dev が含まれるすべてのサイト コレクションを返します。For another example, https://tenant.sharepoint.com/sites/dev* returns all site collections where the URL contains dev.

通常、サイトは、タイマー ジョブ オブジェクトをインスタンス化するプログラムによって追加されますが、必要に応じて、タイマー ジョブで渡されたサイトのリストを制御することもできます。Typically the sites are added by the program that instantiates the Timer Job object, but if needed the Timer Job can take control over the passed list of sites. Do this by adding a method override for the virtual method as shown in sample below: 次のサンプルに示すように、UpdateAddedSites 仮想メソッドのメソッド上書きを追加してこれを実行します。Do this by adding a method override for the UpdateAddedSitesvirtual method as shown in the following sample:

public override List<string> UpdateAddedSites(List<string> addedSites)
{
    // Let's assume we're not happy with the provided list of sites, so first clear it
    addedSites.Clear();

    // Manually adding a new wildcard Url, without an added URL the timer job will do...nothing
    addedSites.Add("https://bertonline.sharepoint.com/sites/d*");

    // Return the updated list of sites
    return addedSites;
}

列挙型の資格情報を指定するSpecify enumeration credentials

ワイルド カード URL を追加して認証をアプリ専用に設定したら、列挙型の資格情報を指定します。After adding a wild card URL and setting authentication to app-only, specify the enumeration credentials. 列挙型の資格情報は、実際のサイトのリストを返すサイト照合アルゴリズムで使用されるサイト コレクションのリストを取得するために使用されます。Enumeration credentials are used to fetch a list of site collections that are used in the site matching algorithm to return a real list of sites.

サイト コレクションのリストを取得するためのタイマー フレームワークの動作は Office 365 (v16) とオンプレミス (v15) で異なります。To acquire a list of site collections, the timer framework behaves differently between Office 365 (v16) and on-premises (v15):

  • Office 365: Tenant.GetSiteProperties メソッドが「標準」のサイト コレクションの読み取りに使用され、検索 API が OneDrive for Business サイト コレクションの読み取りに使用されます。Office 365: The method is used to read the 'regular' site collections, the search API is used to read the OneDrive for Business site collections.
  • SharePoint オンプレミス:すべてのサイト コレクションを読み取るために検索 API が使用されます。On-Premises: The search API is used to read all site collections.

検索 API がユーザー コンテキストと連動しない場合は、タイマー ジョブが指定された列挙型の資格情報にフォールバックします。Given that the search API doesn't work with a user context, the Timer Job falls back to the specified enumeration credentials.

Office 365 に対して実行するためのユーザー資格情報を指定するには、次の 2 つのメソッドを使用できます。To specify user credentials for running against Office 365 you can use these 2 methods:

public void SetEnumerationCredentials(string userUPN, string password)
public void SetEnumerationCredentials(string credentialName)

SharePoint オンプレミスに対して実行するための同様のメソッドがあります。There are similar methods for running against SharePoint on-premises:

public void SetEnumerationCredentials(string samAccountName, string password, string domain)
public void SetEnumerationCredentials(string credentialName)

最初のメソッドは、ユーザー名、パスワード、およびオプションでドメイン (オンプレミスの場合) を受け取るだけです。The first method simply accepts a user name, password, and optionally domain (when in on-premises). 2 つ目のメソッドは、Windows 資格情報マネージャーに保存されている汎用の資格情報を指定します。The second specifies a generic credential stored in the Windows Credential Manager. 資格情報マネージャーの詳細については、「認証」を参照してください。See the Authentication section to learn more about the Credential Manager.

サブサイトの展開Subsite expanding

多くの場合、タイマー ジョブ コードは、サイト コレクションのルート サイトおよびそのサイト コレクションのすべてのサブサイトに対して実行されます。Often you want the Timer Job code to be executed against the root site of the site collection and against all the sub sites of that site collection. これを行うには、ExpandSubSites プロパティを true に設定します。To do this, set the ExpandSubSites property to true. これにより、サイト解決手順の一部として、タイマー ジョブがサブサイトに展開されます。This causes the timer job to expand the subsites as part of the site resolving step.

解決されたサイトおよび展開されたサイトを上書きするOverride resolved and/or expanded sites

タイマー フレームワークでワイルド カード サイトが解決され、オプションでサブサイトが展開されたら、次の手順はサイトのリストの処理です。After the timer framework resolves the wild card sites, and optionally expands the subsites, the next step is to process the list of sites. サイトのリストを処理する前に、サイトのリストの変更が必要となる場合があります。Prior to processing the list of sites, you might want to modify the list of sites. たとえば、特定のサイトを削除したり、リストにサイトを追加したりする場合があります。For example, you may want to remove specific sites or add more sites to the list. この手順は、ResolveAddedSites 仮想メソッドを上書きすることで実現できます。This can be accomplished by overriding the ResolveAddedSites virtual method. 次のサンプルは、ResolveAddedSites メソッドを上書きして、リストから 1 つのサイトを削除する方法を示しています。The following sample shows how to override the ResolveAddedSites method to remove one site from the list.

public override List<string> ResolveAddedSites(List<string> addedSites)
{
    // Use default TimerJob base class site resolving
    addedSites = base.ResolveAddedSites(addedSites);

    //Delete the first one from the list...simple change. A real life case could be reading the site scope 
    //from a SQL (Azure) DB to prevent the whole site resolving. 
    addedSites.RemoveAt(0);

    //Return the updated list of resolved sites...this list will be processed by the timer job
    return addedSites;
}

TimerJobRun イベントTimerJobRun event

タイマー ジョブ フレームワークでは、サイトのリストが作業バッチに分割されます。The Timer Job Framework splits the list of sites into work batches. サイトの各バッチは、独自のスレッドで実行されます。Each batch of sites will be run on its own thread. 既定で、フレームワークによって、5 つのバッチと、それらを実行する 5 つのスレッドが作成されます。By default, the framework will create five batches and five threads to run those five batches. タイマー ジョブ スレッド オプションの詳細については、「スレッド」を参照してください。See the Threading section to learn more about Timer Job threading options.

スレッドがバッチを処理すると、TimerJobRun イベントがタイマー フレームワークによってトリガーされ、タイマー ジョブを実行するために必要なすべての情報が提供されます。When a thread processes a batch the **** event is triggered by the timer framework and will provide all the necessary information to run the Timer Job. タイマー ジョブはイベントとして実行されるため、コードでイベント ハンドラーを TimerJobRun イベントに接続する必要があります。Timer Jobs are run as events, so the code must connect an event handler to the **** event:

public SimpleJob() : base("SimpleJob")
{
    TimerJobRun += SimpleJob_TimerJobRun;
}

void SimpleJob_TimerJobRun(object sender, TimerJobRunEventArgs e)
{
    // your timer job logic goes here
}


もう 1 つの方法では、次のようにインライン委任を使用します。An alternative approach is using an inline delegate as shown here:

public SimpleJob() : base("SimpleJob")
{
    // Inline delegate
    TimerJobRun += delegate(object sender, TimerJobRunEventArgs e)
    {
        // your timer job logic goes here
    };
}


TimerJobRun イベントが発生すると、タイマー ジョブ ロジックを記述するために必要な情報を提供する TimerJobRunEventArgs オブジェクトが送られてきます。When the TimerJobRun event fires, you receive a TimerJobRunEventArgs object, which provides the necessary information to write the timer job logic. このクラスでは、次の属性とメソッドを使用できます。The following attributes and methods are available in this class:

TimerJobRunEventArgs クラスの構造

いくつかのプロパティとすべてのメソッドが、次のセクションで説明するオプションの状態管理機能で使用されます。Several of the properties and all of the methods are used in the optional state management feature which will be discussed in the next section. However the following properties will always be available in every event, regardless of the used configuration: ただし、次のプロパティは、使用されている構成に関係なく、すべてのイベントで常に使用できます。However, the following properties are always available in every event, regardless of the used configuration:

  • Url プロパティ: 動作対象のタイマー ジョブのサイトの URL を取得または設定します。Url property: Gets or sets the URL of the site for the timer job to operate against. サイト コレクションのルート サイトにすることができますが、サイトの展開が行われた場合は、サブサイトにすることもできます。Url property: Gets or sets the URL of the site for the Timer Job to operate against. This can be the root site of the site collection, but it can also be a sub site in case site expanding was done.
  • ConfigurationData プロパティ: 追加のタイマー ジョブ構成データを取得または設定します (オプション)。ConfigurationData property: Gets or sets additional timer job configuration data (optional). This configuration data is passed along as part of the object. この構成データは、TimerJobRunEventArgs オブジェクトの一部として渡されます。ConfigurationData property: Gets or sets additional timer job configuration data (optional). This configuration data is passed along as part of the object.
  • WebClientContext プロパティ: 現在の URL の ClientContext オブジェクトを取得または設定します。WebClientContext property: Gets or sets the ClientContext object for the current URL. このプロパティは、Url プロパティで定義されたサイトの ClientContext オブジェクトです。This property is a ClientContext object for the site defined in the Url property. これは、通常、タイマー ジョブ コードで使用される ClientContext オブジェクトです。This is typically the ClientContext object that you would use in your timer job code.
  • SiteClientContext プロパティ: サイト コレクションのルート サイトの ClientContext オブジェクトを取得または設定します。SiteClientContext property: Gets or sets the ClientContext object for the root site of the site collection. このプロパティは、タイマー ジョブがアクセスするために必要なルート サイトへのアクセス権を提供します。This property provides access to the root site should the timer job require access to it. たとえば、タイマー ジョブは、SiteClientContext プロパティを使用してページ レイアウトをマスター ページ ギャラリーに追加できます。For example, the timer job can add a page layout to the master page gallery by using the SiteClientContext property.
  • TenantClientContext プロパティ: テナント API と連動する ClientContext オブジェクトを取得または設定します。TenantClientContext property: Gets or sets the ClientContext object to work with the Tenant API. このプロパティは、テナント管理サイトの URL を使用して構築された ClientContext オブジェクトを提供します。This property provides a ClientContext object constructed by using the tenant admin site URL. タイマー ジョブの TimerJobRun イベント ハンドラーでテナント API を使用するには、この TenantClientContext プロパティを使用して新しい Tenant オブジェクトを作成します。To use the Tenant API in the timer job TimerJobRun event handler, create a new Tenant object by using this TenantClientContext property.

すべての ClientContext オブジェクトが、「認証」に記載されている認証情報を使用します。All ClientContext objects use the authentication information described in the Authentication section. ユーザー資格情報を選択した場合は、ユーザー アカウントが、指定されたサイトに対して動作するために必要なアクセス許可を持っていることを確認します。All objects use the authentication information described in the Authentication section. If you've opted for user credentials please ensure that the used account has the needed permissions to operate against the specified sites. When using app-only, it is best to set tenant-scoped permissions to the app-only principal. アプリ専用を使用している場合は、テナント スコープ アクセス許可をアプリ専用プリンシパルに設定することをお勧めします。When using app-only, it is best to set tenant-scoped permissions to the app-only principal.

状態管理State management

タイマー ジョブ ロジックを作成する場合は、状態を持続させる必要があります。たとえば、サイトが最後に処理された時点を記録するためやタイマー ジョブのビジネス ロジックをサポートするデータを保存するためなどです。When you write timer job logic, you often need to persist state; for example, to record when a site was last processed, or to store data to support your timer job business logic. このために、タイマー ジョブ フレームワークは状態管理機能を備えています。For this reason, the timer job framework has state management capabilities.

状態管理では、標準およびカスタムのプロパティ セットを、処理されたサイトの Web プロパティ バッグの JSON シリアル化された文字列 (名前 = タイマー ジョブの名前 + 「_Properties」) として保存および取得します。State management stores and retrieves a set of standard and custom properties as a JSON serialized string in the web property bag of the processed site (name = timer job name + "_Properties"). TimerJobRunEventArgs オブジェクトの既定のプロパティを以下に示します。The following are the default properties of the TimerJobRunEventArgs object:

  • PreviousRun プロパティ: 前回の実行の日付と時刻を取得または設定します。PreviousRun property: Gets or sets the date and time of the previous run.
  • PreviousRunSuccessful プロパティ: 前回の実行が正常に完了したかどうかを示す値を取得または設定します。PreviousRunSuccessful property: Gets or sets a value indicating whether the previous run was successful. タイマー ジョブの作成者は、タイマー ジョブの実装の一部として CurrentRunSuccessful プロパティを設定することにより、ジョブの実行に成功というフラグを付ける必要があることに注意してください。PreviousRunSuccessful property: Gets or sets a value indicating whether the previous run was successful. Note that the Timer Job author is responsible for flagging a job run as successful by setting the CurrentRunSuccessful property as part of your Timer Job implementation
  • PreviousRunVersion プロパティ: 前回の実行のタイマー ジョブ バージョンを取得または設定します。PreviousRunVersion property: Gets or sets the Timer Job version of the previous run.

これらの標準プロパティの横で、キーワード–値のペアを TimerJobRunEventArgs オブジェクトの Properties コレクションに追加することにより、独自のプロパティを指定することもできます。Next to these standard properties you also have the option to specify your own properties by adding keyword - value pairs to the – collection of the **** object. To make this easier there are three methods to help you: これを容易にするために、次の 3 つのメソッドがあります。To make this easier, there are three methods to help you:

  • SetProperty はプロパティを追加または更新します。SetProperty adds or updates a property.
  • GetProperty はプロパティの値を返します。GetProperty returns the value of a property.
  • DeleteProperty は、プロパティ コレクションからプロパティを削除します。DeleteProperty removes a property from the property collection.

次のコードは、状態管理の使用方法を示しています。The following code shows how state management can be used:

void SiteGovernanceJob_TimerJobRun(object o, TimerJobRunEventArgs e)
{
    try
    {
        string library = "";

        // Get the number of admins
        var admins = e.WebClientContext.Web.GetAdministrators();

        Log.Info("SiteGovernanceJob", "ThreadID = {2} | Site {0} has {1} administrators.", e.Url, admins.Count, Thread.CurrentThread.ManagedThreadId);

        // grab reference to list
        library = "SiteAssets";
        List list = e.WebClientContext.Web.GetListByUrl(library);

        if (!e.GetProperty("ScriptFileVersion").Equals("1.0", StringComparison.InvariantCultureIgnoreCase))
        {
            if (list == null)
            {
                // grab reference to list
                library = "Style%20Library";
                list = e.WebClientContext.Web.GetListByUrl(library);
            }

            if (list != null)
            {
                // upload js file to list
                list.RootFolder.UploadFile("sitegovernance.js", "sitegovernance.js", true);

                e.SetProperty("ScriptFileVersion", "1.0");
            }
        }

        if (admins.Count < 2)
        {
            // Oops, we need at least 2 site collection administrators
            e.WebClientContext.Site.AddJsLink(SiteGovernanceJobKey, BuildJavaScriptUrl(e.Url, library));
            Console.WriteLine("Site {0} marked as incompliant!", e.Url);
            e.SetProperty("SiteCompliant", "false");
        }
        else
        {
            // We're all good...let's remove the notification
            e.WebClientContext.Site.DeleteJsLink(SiteGovernanceJobKey);
            Console.WriteLine("Site {0} is compliant", e.Url);
            e.SetProperty("SiteCompliant", "true");
        }

        e.CurrentRunSuccessful = true;
        e.DeleteProperty("LastError");
    }
    catch(Exception ex)
    {
        e.CurrentRunSuccessful = false;
        e.SetProperty("LastError", ex.Message);
    }
}

状態は、1 つの JSON シリアル化プロパティとして保存されます。これは、他のカスタマイズにも使用できることを意味します。The state is stored as a single JSON serialized property, which means it can be used by other customizations as well. たとえば、タイマー ジョブが状態エントリ「SiteCompliant = false」を書き込んだ場合は、タイマー ジョブが、サイトが準拠していないと判断したことになるため、JavaScript ルーチンでユーザーのアクションを求めることができます。For example, if the timer job wrote the state entry "SiteCompliant=false", a JavaScript routine could prompt the user to act because the timer job determined that the site was incompliant.

スレッドThreading

タイマー ジョブ フレームワークは、既定で、スレッドを使用して作業を並列化します。The timer job framework by default uses threads to parallelize work. スレッドは、サブサイトの展開 (要求された場合) と、各サイトに対する実際のタイマー ジョブ ロジックの実行 (TimerJobRun イベント) の両方に使用されます。Threading is used for both the subsite expansion (when requested) and for running the actual timer job logic (TimerJobRun event) for each site. スレッドの実装を制御するには、次のプロパティを使用できます。The following properties can be used to control the threading implementation:

  • UseThreading プロパティ: スレッドを使用するかどうかを示す値を取得または設定します。UseThreading property: Gets or sets a value indicating whether threading is used. 既定は true です。Defaults to true. メイン アプリケーション スレッドを使用してすべてのアクションを実行するには、false に設定します。UseThreading property: Gets or sets a value indicating whether threading will be used. Defaults to true. Set to false to perform all actions by using the main application thread.
  • MaximumThreads プロパティ: このタイマー ジョブに使用するスレッドの数を取得または設定します。MaximumThreads property: Gets or sets the number of threads to use for this timer job. 有効な値は 2 から 100 です。Valid values are from 0 to 100. 既定は 5 です。The default is 5. 必ずしも多数のスレッドを使用する方が少数のスレッドを使用するより高速になるとは限りません。Having lots of threads is not necessarily faster than having just a few threads. 最適な数は、さまざまなスレッド数を使用したテストを通して特定する必要があります。The optimal number should be acquired via testing by using a variety of thread counts. 既定の 5 スレッドは、ほとんどのシナリオでパフォーマンスを大幅に向上することがわかっています。The default of 5 threads has been found to significantly boost performance in most scenarios.

調整Throttling

タイマー ジョブはスレッドを使用し、大抵のタイマー ジョブの操作がリソース消費型であるため、タイマー ジョブの実行を調整することができます。Because a timer job uses threading and timer job operations are typically resource-intensive operations, a timer job run could be throttled. 調整を正しく処理するために、タイマー ジョブ フレームワークと PnP コアの全体で、既定の ExecuteQuery メソッドではなく、ExecuteQueryRetry メソッドが使用されます。To correctly deal with throttling, the timer job framework and the whole of PnP Core uses the ExecuteQueryRetry method instead of the default ExecuteQuery method.

注意

タイマー ジョブの実装コードで ExecuteQueryRetry を使用することが重要です。It is important to use **** in your Timer Job implementation code.

同時実行の問題 - 同じスレッド内のサイト コレクションのすべてのサブサイトを処理するConcurrency issues - process all sub sites of a site collection in the same thread

複数のスレッドを使用してサブサイトを処理すると、タイマー ジョブで同時実行の問題が発生する可能性があります。Timer jobs may have concurrency issues when using multiple threads to process subsites.

一例を挙げます。スレッド A はサイト コレクション 1 の最初のサブサイトのセットを処理し、スレッド B はサイト コレクション 1 の残りのサブサイトを処理します。Take this example: Thread A processes the first set of subsites from site collection 1, and thread B processes the rest of the subsites from site collection 1. タイマー ジョブがサブサイトとルート サイトを処理する (SiteClientContext オブジェクトを使用して) 場合は、スレッド A とスレッド B の両方がルート サイトを処理するため、同時実行の問題が発生する可能性があります。If the timer job processes the subsite and the root site (by using the SiteClientContext object), there could be a concurrency issue because both thread A and thread B process the root site.

同時実行の問題を回避する (1 つのスレッド内でタイマー ジョブを実行せずに) には、タイマー ジョブ内で GetAllSubSites メソッドを使用します。To avoid the concurrency issue (without running the timer jobs in a single thread) use the GetAllSubSites method within the timer job.

次のコードは、タイマー ジョブ内で GetAllSubSites メソッドを使用する方法を示しています。The following code shows how to use the **** method within a Timer Job:

public class SiteCollectionScopedJob: TimerJob
{
    public SiteCollectionScopedJob() : base("SiteCollectionScopedJob")
    {
        // ExpandSites *must* be false as we'll deal with that at TimerJobEvent level
        ExpandSubSites = false;
        TimerJobRun += SiteCollectionScopedJob_TimerJobRun;
    }

    void SiteCollectionScopedJob_TimerJobRun(object sender, TimerJobRunEventArgs e)
    {
        // Get all the subsites in the site we're processing
        IEnumerable<string> expandedSites = GetAllSubSites(e.SiteClientContext.Site);

        // Manually iterate over the content
        foreach (string site in expandedSites)
        {
            // Clone the existing ClientContext for the sub web
            using (ClientContext ccWeb = e.SiteClientContext.Clone(site))
            {
                // Here's the timer job logic, but now a single site collection is handled in a single thread which 
                // allows for further optimization or prevents race conditions
                ccWeb.Load(ccWeb.Web, s => s.Title);
                ccWeb.ExecuteQueryRetry();
                Console.WriteLine("Here: {0} - {1}", site, ccWeb.Web.Title);
            }
        }
    }
}

ログLogging

タイマー ジョブ フレームワークは、PnP コア ライブラリの一部であるため、PnP コア ログ コンポーネントを使用します。The timer job framework uses the PnP Core logging components because it's part of the PnP Core library. 組み込みの PnP コア ログをアクティブにするには、該当する構成ファイル (app.config または web.config) を使用して構成します。To activate the built-in PnP Core logging, configure it by using the appropriate config file (app.config or web.config). 次の例は、必要な構文を示しています。The following example shows the required syntax:

  <system.diagnostics>
    <trace autoflush="true" indentsize="4">
      <listeners>
        <add name="DebugListenter" type="System.Diagnostics.TextWriterTraceListener" initializeData="trace.log" />
        <!--<add name="consoleListener" type="System.Diagnostics.ConsoleTraceListener" />-->
      </listeners>
    </trace>
  </system.diagnostics>

上の構成ファイルを使用すると、タイマー ジョブ フレームワークは System.Diagnostics.TextWriterTraceListener を使用して、タイマー ジョブの .exe と同じフォルダー内の trace.log ファイルにログを書き込みます。Using the above configuration file the Timer Job Framework will use the System.Diagnostics.TextWriterTraceListener to write logs to a file called trace.log in the same folder as the Timer Job .exe. Other trace listeners are available such as: 利用可能なその他のトレース リスナーには、次のようなものがあります。Other trace listeners are available such as:

タイマー ジョブ フレームワークと同じログ アプローチを、カスタムのタイマー ジョブ コードに使用することを強くお勧めします。It is strongly advised to use the same logging approach for your custom timer job code as you do for the timer job framework. タイマー ジョブ コード内で、PnP コア Log クラスを使用できます。In your timer job code, you can use the PnP Core Log class:

void SiteGovernanceJob_TimerJobRun(object o, TimerJobRunEventArgs e)
{
    try
    {
        string library = "";

        // Get the number of admins
        var admins = e.WebClientContext.Web.GetAdministrators();

        Log.Info("SiteGovernanceJob", "ThreadID = {2} | Site {0} has {1} administrators.", e.Url, admins.Count, Thread.CurrentThread.ManagedThreadId);

        // Additional timer job logic...

        e.CurrentRunSuccessful = true;
        e.DeleteProperty("LastError");
    }
    catch(Exception ex)
    {
        Log.Error("SiteGovernanceJob", "Error while processing site {0}. Error = {1}", e.Url, ex.Message);
        e.CurrentRunSuccessful = false;
        e.SetProperty("LastError", ex.Message);
    }
}

関連項目See also