タイマー ジョブ フレームワークThe Timer Job Framework

PnP タイマー ジョブ フレームワークは、SharePoint サイトに対して動作するバック グラウンド プロセスの作成を容易にするために設計されたクラスのセットです。タイマー ジョブ フレームワークは、オンプレミスの完全信頼コード タイマー ジョブと似ています (SPJobDefinition)。タイマー ジョブ フレームワークと完全信頼コード タイマー ジョブの主な相違点は、タイマー ジョブ フレームワークはクライアント側 API のみを使用するため、SharePoint の外部で実行できる (および必要がある) ことです。タイマー ジョブ フレームワークを使用することで、SharePoint Online に対して動作するタイマー ジョブの作成が可能になります。The PnP Timer Job Framework is a set of classes designed to ease the creation of background processes that operate against SharePoint sites. The Timer Job Framework is similar to on-premises full trust code Timer Jobs (SPJobDefinition). The primary difference with 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. The Timer Job Framework makes it possible to build Timer Jobs that operate against SharePoint Online.

タイマー ジョブを作成したら、スケジュールを設定して実行する必要があります。2 つの最も一般的なオプションは、次のとおりです。Once a Timer Job has been created it needs to be scheduled and executed. 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, this PnP video introduces the Timer Job Framework and demonstrates the Simple Timer Job example.

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

この章では、非常に単純なタイマー ジョブを作成する方法を示します。 このサンプルの目標は、読者に簡易ビューを提供することです。タイマー ジョブ フレームワークの詳細な説明は後ほど提供します。In this chapter you'll see how to create a very simple Timer Job: the goal of this sample is to provide the reader a quick view, later on we'll provide a more detailed explanation of the Timer Job Framework.

注意

「Hello world」サンプルから実際のコンテンツ有効期限ジョブまで、10 の個別タイマー ジョブを使用した、より広範な PnP ソリューションについては、https://github.com/SharePoint/PnP/tree/dev/Solutions/Core.TimerJobs.Samples を参照してください。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 describes 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 パッケージをプロジェクトに追加します。v15 (オンプレミス) および for v16 (Office 365) 用 Nuget パッケージがあります。これは優先オプションです。Add the Office 365 Developer Patterns and Practices Core Nuget package to your project. 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. タイマー ジョブの名前付きクラスを追加しますSimpleJobAdd a class for the Timer Job named SimpleJob.
  2. クラスに、TimerJob抽象基本クラスを継承させます。Have the class inherit the TimerJob abstract base class.
  3. コンストラクターで、タイマー ジョブに名前を付け (base("SimpleJob")) 、TimerJobRun イベント ハンドラーに接続します。In the constructor give the Timer Job a name (base("SimpleJob")) and connect the TimerJobRun 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

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

  1. タイマー ジョブ クラスをインスタンス化します。Instantiate your Timer Job class.
  2. タイマー ジョブの認証の詳細を提供します。次の例では、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 つ以上のサイトを追加します。この例では、URL にワイルドカード文字を使用します。タイマー ジョブは、このワイルド カード URL に一致するすべてのサイトで実行されます。Add one or more sites for the Timer Job program to access. This example uses a wild card character in the URL. The Timer Job will run 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 ファイルです。選択したホスティング プラットフォームに応じて、展開は異なります。次のセクションでは、2 つの最も一般的なホスティング プラットフォーム オプションについて説明します。A Timer Job is an .exe file that must be scheduled on a hosting platform. Depending on the chosen hosting platform the deployment differs. The following sections describe the two most common hosting platform options:

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

Azure WebJobs を使用して Microsoft Azure にタイマー ジョブを展開するDeploying Timer Jobs to Microsoft Azure using Azure WebJobs

タイマー ジョブを展開する前に、ユーザーの介入なしには、ジョブを実行できることを確認します。この記事のサンプルでは、ユーザーにパスワードまたは ClientSecret の入力を求めるメッセージが表示されます (詳細は「認証」を参照してください)。これはテストでは機能しますが、展開時に機能しません。すべての既存のサンプルでは、ユーザーに対し、app.config ファイルを使用したパスワードや ClientSecret の提供を許可しています。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 clientsecret (see more in Authentication) which works while testing but will not work when deployed. The existing samples all allow the user to provide a password or clientsecret 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 app.config file, run the Timer Job from Visual Studio to confirm that it runs without user interaction.

Azure への実際の展開は、Azure Web ジョブに基づいています。このタイマー ジョブの例を展開するには、以下の手順を実行します。The actual deployment to Azure is based on Azure Web Jobs. 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 click OK
  3. 発行先として [Microsoft Azure Websites] を選択します。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 管理ポータルジョブをトリガーし、ジョブの実行を確認できます。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 管理ポータル

また、新しい Azure ポータルからジョブを選択し、[実行] をクリックしてタイマー ジョブを実行することもできます。新しいポータルから WebJobs を使用する方法の詳細については、「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 ポータル

注意

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

Windows Scheduler を使用して Windows Server にタイマー ジョブを展開するDeploying Timer Jobs to Windows Server using the Windows Scheduler

Windows Server に展開する場合、ユーザーの介入なしにタイマー ジョブを実行する必要があります。「Azure WebJobs を使用して Microsoft Azure にタイマー ジョブを展開する」に記載されているように、app.configファイルを変更します。When deployed to Windows Server, the Timer Job must run without user interaction. Modify the app.config file as described in Deploying Timer Jobs to Microsoft Azure using Azure WebJobs.

ジョブのリリース バージョンを、実行するサーバーにコピーします。重要事項: サーバー上に追加のファイルまたはプログラムをインストールしなくてもジョブを実行できるよう、関連するすべてのアセンブリ、.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.

タイマー ジョブの実行をスケジュールします。Windows タスク スケジューラー内で組み込みを使用することを推奨します。Windows タスク スケジューラーを使用するには、以下の手順を実行します。Schedule the execution of the Timer Job. It is recommended to use the built in Windows Task Scheduler. To use the Windows Task Scheduler, take the following steps:

  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. [トリガー] をクリックし、新しいトリガーを追加します。タイマー ジョブのスケジュールを指定します。Click on Triggers and add a new trigger. Specify the schedule you want for the Timer Job.
  4. [アクション] をクリックし、「プログラムを開始する」アクション、タイマー ジョブの .exe ファイルの順に選択し、フォルダーで開始を設定します。Click on Actions and choose action "Start a program", select the Timer Job .exe file and set the start in folder.
  5. [OK] をクリックしてタスクを保存します。Click on OK to save the task.

Windows タスク スケジューラー

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

このセクションでは、タイマー ジョブ フレームワークの機能とそのしくみについて詳しく説明します。This section details how the Timer Job Framework features and how it works.

構造体Structure

TimerJob クラスは、次のパブリック プロパティ、メソッド、およびイベントが含まれている抽象基本クラスです。The TimerJob 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:

  • IsRunning プロパティ:タイマー ジョブが実行中かどうかを示す値を取得します。実行中の場合の値は 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 のバージョンを取得または設定します。このプロパティは、読み込まれている Microsoft.SharePoint.Client.dll のバージョンに基づいて自動的に設定されます。通常は変更しないでください。ただし、v16 CSOM ライブラリを v15 (オンプレミス) 展開で使用する場合などはこのプロパティを変更できます。SharePointVersion property: Gets or sets the SharePoint version. this property is automatically set based on the version of the loaded Microsoft.SharePoint.Client.dll and in general should not change. You can, however, change this property in case you for example want to use the v16 CSOM libraries in a v15 (on-premises) deployment.
  • Version プロパティ:このタイマー ジョブのバージョンを取得します。バージョンは最初、タイマー ジョブのコンストラクターで設定されるか、コンストラクターで設定されない場合は既定値の 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 sub site expanding was requested then the resolved sites list is expanded with all sub sites.
  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 TimerJobRun event for each site in the list.

各手順の詳細については、以下をご覧ください。Further details on each step can be found below.

認証Authentication

タイマー ジョブを使用する前に、タイマー ジョブは SharePoint への認証方法を把握する必要があります。フレームワークが現在サポートしているのは、AuthenticationType 列挙型、Office365NetworkCredentials および AppOnly を使用した方法です。また、以下の図の方法を使用した場合でも、AuthenticationType プロパティは Office365NetworkCredentials および AppOnly の適切な値に自動的に設定されます。以下のフローチャートでは、実行する手順を示します。それぞれの方法の詳細な説明は下にあります。Before a Timer Job can be used the Timer Job needs to know how to authenticate back to SharePoint. The framework currently supports the approaches in the AuthenticationType enum; Office365, NetworkCredentials and AppOnly. Using the methods illustrated below also automatically sets the AuthenticationType property to the appropriate value of Office365, NetworkCredentials and AppOnly. The flowchart below shows the steps to take. Detailed explanations on each approach are found below.

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

ユーザー資格情報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)

最初のメソッドでは、単にユーザー名とパスワードを受け入れます。2 番目のメソッドでは、Windows 資格情報マネージャーに保存されている汎用の資格情報を指定できます。下のスクリーン ショットは、bertonline汎用の資格情報を示しています。これを使用してタイマー ジョブを認証するため、2 つ目のメソッドのパラメーターとして「最低値」を提供します。The first method simply accepts a user name and password. The second one allows you to specify a generic credential stored in the Windows Credential Manager. The screen shot below shows the bertonline generic credential. 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 OnlyApp Only

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

注意

特定のサイト解決ロジックは、App Only 認証では機能しません。Certain site resolving logic wont work with App-only authentication. 詳細は、次のセクションで説明します。Details can be found in the next section.

App Only 認証のジョブを構成するには、次のいずれかのメソッドを使用します。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 のいずれかで同じメソッドを使用し、App Only 認証を使用したタイマー ジョブを環境間で容易に移動させることができます。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.

注意

App Only を使用する場合、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. To add sites to a Timer Job, use the below set of methods.

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

サイトを追加するには、完全修飾 URL (例: https://tenant.sharepoint.com/sites/dev)) またはワイルドカード URL のいずれかを指定します。ワイルド カードの URL は、末尾に * が付く URL です (* は 1 つのみを使用でき、URL の最後の文字にする必要があります)。サンプル ワイルド カードの URL は https://tenant.sharepoint.com/sites/* となり、そのサイトの管理パスの下のすべてのサイト コレクションを返します。別の例では、https://tenant.sharepoint.com/sites/dev* は URL に「dev」が含まれるすべてのサイト コレクションを返します。To add a site, specify either a fully qualified URL (for example, https://tenant.sharepoint.com/sites/dev) or a wild card URL. A wild card URL is a URL that ends with a * (only one single * is allowed and it must be the last character of the url). A sample wild card URL is https://tenant.sharepoint.com/sites/* which will return all the site collections underneath the managed path of that site. For another example, https://tenant.sharepoint.com/sites/dev* will return all site collections where the URL contains "dev".

通常、サイトは、タイマー ジョブ オブジェクトをインスタンス化するプロジェクトによって追加されますが、必要に応じて、タイマー ジョブが渡されたサイトのリストを制御することもできます。次の例に示すように、UpdateAddedSites 仮想メソッドのメソッド上書きを追加してこれを実行します。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 UpdateAddedSitesvirtual method as shown in sample below:

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;
}

ワイルド カードの URL を追加して認証を App Only に設定した後、列挙型の資格情報を指定します。列挙型の資格情報は、実際のサイトのリストを返すためのサイト照合アルゴリズムで使用されるサイト コレクションのリストを取得するために使用されます。サイト コレクションのリストを取得するため、タイマー フレームワークの動作 Office 365 (v16) とオンプレミス (v15) で異なります。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 which are used in the site matching algorithm to return a real list of sites. To acquire a list of site collections the timer framework will behave differently between Office 365 (v16) and on-premises (v15):

  • Office 365:Tenant.GetSiteProperties メソッドは「標準」のサイト コレクションの読み取り、検索 API は OneDrive for Business サイト コレクションの読み取りに使用します。Office 365: The Tenant.GetSiteProperties method is used to read the 'regular' site collections, the search API is used to read the OneDrive for Business site collections.
  • オンプレミス:すべてのサイト コレクションを読み取るために検索 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)

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

サブ サイトの展開Sub site 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 will cause the Timer Job to expand the sub sites as part of the site resolving step.

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

タイマー フレームワークでワイルド カードのサイトを解決し、オプションとしてサブ サイトを展開すると、次にサイトのリストを処理します。サイトのリストを処理する前に、サイトのリストの変更が必要となる場合があります。たとえば、特定のサイトを削除したり、リストにサイトを追加する場合があります。この手順は、ResolveAddedSites 仮想メソッドを上書きすることで実現できます。以下のサンプルは、ResolveAddedSites メソッドを上書きし、リストから 1 つのサイトを削除する方法を示しています。Once the timer framework resolves the wild card sites, and optionally expands the sub sites, 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. This can be accomplished by overriding the ResolveAddedSites virtual method. The sample below 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 つのバッチを実行する 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 TimerJobRun 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 TimerJobRun 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:

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

すべての ClientContextオブジェクトは、「認証セクションに記載されている認証情報を使用します。ユーザーの資格情報を使用することを選択した場合、ユーザー アカウントが、指定したサイトの操作に必要なアクセス許可を持っていることを確認してください。App Only を使用している場合は、テナントを範囲としたアクセス許可を App Only プリンシパルに設定することのが最適です。All ClientContextobjects 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.

状態管理State management

タイマー ジョブのロジックを作成するとき、通常は、状態を永続化する必要があります。たとえば、サイトが最後に処理された時期を記録する、または、タイマー ジョブのビジネス ロジックをサポートするためにデータを保存するためなど。この理由から、タイマー ジョブ フレームワークには状態管理機能が搭載されています。状態管理では、標準およびカスタムのプロパティ セットを、処理されたサイトの Web プロパティ バッグの JSON シリアル化された文字列 (名前 = タイマー ジョブの名前 + 「_Properties」) として保存および取得します。以下は、TimerJobRunEventArgsオブジェクトの既定のプロパティです。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. 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"). The following are the default properties of the TimerJobRunEventArgsobject:

  • PreviousRun プロパティ:前回の実行の日付と時刻を取得または設定します。PreviousRun property: Gets or sets the date and time of the previous run.
  • PreviousRunSuccessful プロパティ:以前の実行が正常に完了したかどうかを示す値を取得または設定します。タイマー ジョブの作成者は、タイマー ジョブの実装の一部として 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.

これらの標準プロパティの横で、キーワードと値のペアを Propertiesオブジェクトの TimerJobRunEventArgs コレクションに追加し、独自のプロパティを指定することもできます。これを容易にするには、3 つの方法があります。Next to these standard properties you also have the option to specify your own properties by adding keyword - value pairs to the Properties collection of the TimerJobRunEventArgsobject. 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 シリアル化プロパティに保存され、他のカスタマイズにも使用できます。たとえば、タイマー ジョブが状態エントリ「SiteCompliant = false」を作成した場合、タイマー ジョブはそのサイトが、準拠していないと判断したため、JavaScript ルーチンでユーザーの入力を求める可能性があります The state is stored as a single JSON serialized property which means it can be used by other customizations as well. 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.

ThreadingThreading

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

  • UseThreading プロパティ:スレッドを使用するかどうかを示す値を取得または設定します。既定は 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 プロパティ:このタイマー ジョブに使用するスレッドの数を取得または設定します。有効な値は 2 から 100 です。既定は 5 です。多数のスレッドが、必ずしも少ないスレッドより高速になるとは限りません。最適な数は、さまざまなスレッド数を使用してテストで取得する必要があります。既定の 5 スレッドは、ほとんどのシナリオでパフォーマンスを大幅に向上することがわかっています。MaximumThreads property: Gets or sets the number of threads to use for this Timer Job. Valid values are 2 to 100. The default is 5. Having lots of threads is not necessarily faster then having just few threads. The optimal number should be acquired via testing using a variety of thread counts. The default of 5 threads has been found to significantly boost performance in most scenarios.

調整Throttling

タイマー ジョブをスレッドを使用し、タイマー ジョブの操作は通常、リソースを集中的に使用する操作のため、タイマー ジョブの実行を制限することができます。タイマー ジョブ フレームワークおよび PnP コア全体の制限を正しく処理するためには、既定の ExecuteQueryRetry メソッドではなく、ExecuteQuery メソッドを使用します。Because Timer Job uses threading and Timer Job operations are typically resource intensive operations, a Timer Job run could be throttled. In order to correctly deal with throttling the Timer Job Framework and the whole of PnP Core uses the ExecuteQueryRetry method instead of the default ExecuteQuerymethod.

注意

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

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

複数のスレッドを使用してサブ サイトを処理するときは、タイマー ジョブで同時実行の問題が発生する場合があります。次の例を使用します。スレッド A はサイト コレクション 1 の最初のサブ セットを処理し、スレッド B はサイト コレクション 1 の残りのサブ サイトを処理します。タイマー ジョブがサブ サイトとルート サイトの処理する場合 (SiteClientContext オブジェクトを使用して)、スレッド A とスレッド B の両方がルート サイトを処理するため、同時実行の問題が発生する可能性があります。同時実行の問題を回避するため (1 つのスレッド内でタイマー ジョブを実行せずに)、タイマー ジョブ内で GetAllSubSites メソッドを使用します。Timer Jobs may have concurrency issues when using multiple threads to process sub sites. Take this example: Thread A processes the first set of sub sites from site collection 1, and thread B processes the rest of the sub sites from site collection 1. If the Timer Job processes the sub site and the root site (by using the SiteClientContext object), there could be a concurrency issue since both thread A and thread B process the root site. 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 GetAllSubSites 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 sub sites 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 のコア ログ収集コンポーネントを使用します。組み込みの PnP コア ログ収集をアクティブ化するには、適切な構成ファイル (app.config または web.config) を使用して構成します。次の例は、必要な構文を示しています。The Timer Job Framework uses the PnP Core logging components as it's part of the PnP Core library. To activate the built-in PnP Core logging, configure it 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:

タイマー ジョブ フレームワークと同じログ収集方法を、カスタムのタイマー ジョブ コードに使用することを強くお勧めします。タイマー ジョブ コード内で、PnP コア Log クラスを使用できます。It is strongly advised to use the same logging approach for your custom Timer Job code as you do for the Timer Job Framework. 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);
    }
}