C# Windows アプリでフィード プロバイダーを実装する
Note
一部の情報はリリース前の製品に関する事項であり、正式版がリリースされるまでに大幅に変更される可能性があります。 Microsoft はここに示されている情報について、明示か黙示かを問わず、一切保証しません。
この記事では、フィード コンテンツ URI を登録し、IFeedProvider インターフェイスを実装する単純なフィード プロバイダーを作成する手順について説明します。 このインターフェイスのメソッドは、カスタム クエリ文字列パラメーターを要求するために ウィジェット ボード によって呼び出されます。通常は認証シナリオをサポートするためのものです。 フィード プロバイダーは、1 つのフィードまたは複数のフィードをサポートできます。
C++/WinRT を使ってフィード プロバイダーを実装するには、「win32 アプリでフィード プロバイダーを実装する (C++/WinRT)」をご覧ください。
前提条件
- デバイスで開発者モードが有効になっている必要があります。 詳しくは、「デバイスを開発用に有効にする」をご覧ください。
- ユニバーサル Windows プラットフォーム開発ワークロードを含む Visual Studio 2022 以降。
新しい C# コンソール アプリを作成する
Visual Studio で、新しいプロジェクトを作成します。 [新しいプロジェクトの作成] ダイアログで、言語フィルターを "C#" に設定し、プラットフォーム フィルターを Windows に設定してから、コンソール アプリ プロジェクト テンプレートを選びます。 新しいプロジェクトに "ExampleFeedProvider" という名前を付けます。 このチュートリアルでは、[ソリューションとプロジェクトを同じディレクトリに配置する] がオフになっていることを確認します。 メッセージが表示されたら、ターゲットの .NET バージョンを 6.0 に設定します。
プロジェクトが読み込まれたら、ソリューション エクスプローラーでプロジェクト名を右クリックして、[プロパティ] を選びます。 [全般] ページで、[ターゲット OS] まで下にスクロールして [Windows] を選びます。 [ターゲット OS バージョン] で、バージョン 10.022631.2787 以降を選びます。
このチュートリアルでは、簡単にデバッグできるよう、フィードがアクティブになったらコンソール ウィンドウを表示するコンソール アプリを使うことに注意してください。 フィード プロバイダー アプリを発行する準備ができたら、「コンソール アプリを Windows アプリに変換する」の手順のようにして、コンソール アプリケーションを Windows アプリケーションに変換できます。
Windows アプリ SDK NuGet パッケージへの参照を追加します。
このサンプルでは、最新の安定した Windows App SDK NuGet パッケージを使います。 ソリューション エクスプローラーで [依存関係] を右クリックして、[NuGet パッケージの管理...] を選びます。NuGet パッケージ マネージャーで [参照] タブを選んで、"Microsoft.WindowsAppSDK" を検索します。 [バージョン] ドロップダウンで最新の安定バージョンを選んで、[インストール] をクリックします。
フィード操作を処理する FeedProvider クラスを追加する
Visual Studio のソリューション エクスプローラーで ExampleFeedProvider
プロジェクトを右クリックして、[追加] > [クラス] を選びます。 [クラスの追加] ダイアログで、クラスに "FeedProvider" という名前を付けて、[追加] をクリックします。 生成された FeedProvider.cs ファイルで、クラスの定義を更新し、IFeedProvider インターフェイスを実装していることを示します。
COM のアクティブ化でフィード プロバイダーを識別するために使われる CLSID を作成します。 Visual Studio で [ツール] > [GUID の作成] に移動して、GUID を生成します。 この GUID は、後でフィード プロバイダー アプリをパッケージ化するときに使用するので、テキスト ファイルに保存します。 次の例に示す FeedProvider クラスの注釈の GUID を置き換えます。
// FeedProvider.cs
using Microsoft.Windows.Widgets.Feeds.Providers;
...
[ComVisible(true)]
[ComDefaultInterface(typeof(IFeedProvider))]
[Guid("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")]
public sealed class FeedProvider : IFeedProvider
IFeedProvider メソッドを実装する
次の数セクションでは、IFeedProvider インターフェイスのメソッドを実装します。
Note
IFeedProvider インターフェイスのコールバック メソッドにパスされるオブジェクトは、コールバック内でのみ有効であることが保証されます。 コールバックのコンテキストの外部での動作は定義されていないため、これらのオブジェクトへの参照は保存しないでください。
OnFeedProviderEnabled
プロバイダーに関連付けられているフィードが ウィジェット ボード ホストによって作成されると、OnFeedProviderEnabled メソッドが呼び出されます。 このメソッドの実装では、必要な認証トークンを含むフィード コンテンツを提供する URL にパスされるパラメーターを含むクエリ文字列を生成します。 CustomQueryParametersUpdateOptions のインスタンスを作成し、有効になっているフィードとクエリ文字列を識別するイベント引数から FeedProviderDefinitionId をパスします。 既定の FeedManager を取得し、SetCustomQueryParameters を呼び出して、クエリ文字列パラメーターを ウィジェット ボード に登録します。
// FeedProvider.cs
public void OnFeedProviderEnabled(FeedProviderEnabledArgs args)
{
Console.WriteLine($"{args.FeedProviderDefinitionId} feed provider was enabled.");
var updateOptions = new CustomQueryParametersUpdateOptions(args.FeedProviderDefinitionId, "param1¶m2");
FeedManager.GetDefault().SetCustomQueryParameters(updateOptions);
}
OnFeedProviderDisabled
OnFeedProviderDisabled は、このプロバイダーのすべてのフィードが無効になっている場合にウィジェット ボードが呼び出されます。 フィード プロバイダーは、これらのメソッド呼び出しに応答してアクションを実行する必要はありません。 メソッドの起動は、利用統計情報の目的で使用したり、必要に応じてクエリ文字列パラメーターを更新したり、認証トークンを取り消したりするために使用できます。 アプリが単一のフィード プロバイダーのみをサポートしている場合、またはアプリでサポートされているすべてのフィード プロバイダーが無効になっている場合は、このコールバックに応答してアプリを終了できます。
// FeedProvider.cs
public void OnFeedProviderDisabled(FeedProviderDisabledArgs args)
{
Console.WriteLine($"{args.FeedProviderDefinitionId} feed provider was disabled.");
}
OnFeedEnabled、OnFeedDisabled
フィードが有効または無効になると、OnFeedEnabled と OnFeedDisabled がウィジェット ボードによって呼び出されます。 フィードプロバイダは、これらのメソッド呼び出しに応答して何らかのアクションを実行する必要はありません。 メソッドの起動は、利用統計情報の目的で使用したり、必要に応じてクエリ文字列パラメーターを更新したり、認証トークンを取り消したりするために使用できます。
// FeedProvider.cs
public void OnFeedEnabled(FeedEnabledArgs args)
{
Console.WriteLine($"{args.FeedDefinitionId} feed was enabled.");
}
// FeedProvider.cs
public void OnFeedDisabled(FeedDisabledArgs args)
{
Console.WriteLine($"{args.FeedDefinitionId} feed was disabled.");
}
OnCustomQueryParametersRequested
OnCustomQueryParametersRequested は、フィード プロバイダーに 関連付けられているカスタム クエリ パラメーターを更新する必要があるとウィジェット ボードが判断したときに発生します。 たとえば、リモート Web サービスからフィード コンテンツをフェッチする操作が失敗した場合に、このメソッドが発生する可能性があります。 このメソッドに渡される CustomQueryParametersRequestedArgs の FeedProviderDefinitionId プロパティは、クエリ文字列パラメーターが要求されるフィードを指定します。 プロバイダーは、クエリ文字列を再生成し、SetCustomQueryParameters を呼び出してウィジェット ボードにパスする必要があります。
// FeedProvider.cs
public void OnCustomQueryParametersRequested(CustomQueryParametersRequestedArgs args)
{
Console.WriteLine($"CustomQueryParamaters were requested for {args.FeedProviderDefinitionId}.");
var updateOptions = new CustomQueryParametersUpdateOptions(args.FeedProviderDefinitionId, "param1¶m2");
FeedManager.GetDefault().SetCustomQueryParameters(updateOptions);
}
要求時に FeedProvider をインスタンス化するクラス ファクトリを実装する
フィード ホストがフィード プロバイダーと通信するには、CoRegisterClassObject を呼び出す必要があります。 この関数では、FeedProvider クラスのクラス オブジェクトを作成する IClassFactory の実装を作成する必要があります。 このクラス ファクトリを自己完結型ヘルパー クラスに実装します。
Visual Studio のソリューション エクスプローラーで ExampleFeedProvider
プロジェクトを右クリックして、[追加] > [クラス] を選びます。 [クラスの追加] ダイアログで、クラスに "FactoryHelper" という名前を付けて、[追加] をクリックします。
FactoryHelper.cs ファイルの内容を次のコードに置き換えます。 このコードでは、IClassFactory インターフェイスを定義し、その 2 つのメソッド CreateInstance と LockServer を実装します。 これは、クラス ファクトリを実装するための一般的な定型コードであり、作成されるクラス オブジェクトが IFeedProvider インターフェイスを実装していることを示す点を除き、フィード プロバイダーの機能に固有のものではありません。
// FactoryHelper.cs
using Microsoft.Windows.Widgets.Feeds.Providers;
using System.Runtime.InteropServices;
using WinRT;
namespace ExampleFeedProvider
{
namespace Com
{
static class Guids
{
public const string IClassFactory = "00000001-0000-0000-C000-000000000046";
public const string IUnknown = "00000000-0000-0000-C000-000000000046";
}
[ComImport(), InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid(Guids.IClassFactory)]
internal interface IClassFactory
{
[PreserveSig]
int CreateInstance(IntPtr pUnkOuter, ref Guid riid, out IntPtr ppvObject);
[PreserveSig]
int LockServer(bool fLock);
}
static class ClassObject
{
public static void Register(Guid clsid, object pUnk, out uint cookie)
{
[DllImport("ole32.dll")]
static extern int CoRegisterClassObject(
[MarshalAs(UnmanagedType.LPStruct)] Guid rclsid,
[MarshalAs(UnmanagedType.IUnknown)] object pUnk,
uint dwClsContext,
uint flags,
out uint lpdwRegister);
int result = CoRegisterClassObject(clsid, pUnk, 0x4, 0x1, out cookie);
if (result != 0)
{
Marshal.ThrowExceptionForHR(result);
}
}
public static int Revoke(uint cookie)
{
[DllImport("ole32.dll")]
static extern int CoRevokeClassObject(uint dwRegister);
return CoRevokeClassObject(cookie);
}
}
}
internal class FeedProviderFactory<T> : Com.IClassFactory
where T : IFeedProvider, new()
{
public int CreateInstance(IntPtr pUnkOuter, ref Guid riid, out IntPtr ppvObject)
{
ppvObject = IntPtr.Zero;
if (pUnkOuter != IntPtr.Zero)
{
Marshal.ThrowExceptionForHR(CLASS_E_NOAGGREGATION);
}
if (riid == typeof(T).GUID || riid == Guid.Parse(Com.Guids.IUnknown))
{
// Create the instance of the .NET object
ppvObject = MarshalInspectable<IFeedProvider>.FromManaged(new T());
}
else
{
// The object that ppvObject points to does not support the
// interface identified by riid.
Marshal.ThrowExceptionForHR(E_NOINTERFACE);
}
return 0;
}
int Com.IClassFactory.LockServer(bool fLock)
{
return 0;
}
private const int CLASS_E_NOAGGREGATION = -2147221232;
private const int E_NOINTERFACE = -2147467262;
}
}
フィード プロバイダー クラスのオブジェクトを OLE に登録する
実行可能ファイルの Program.cs ファイルで、CoRegisterClassObject を呼び出してフィード プロバイダーを OLE に登録し、ウィジェット ボードがそれを操作できるようにします。 Program.cs のコンテンツを次のコードに置き換えます。 これは、前の手順で定義した FeedProviderFactory インターフェイスを使用して、FeedProvider ヘルパー クラスを登録します。 デバッグの目的で、この例では、既定の FeedManager インスタンスで GetEnabledFeedProviders を呼び出し て、有効なフィード プロバイダーを表す FeedProviderInfo オブジェクトの一覧を取得します。 EnabledFeedDefinitionIds プロパティを使用して、有効になっているフィード プロバイダーをループ処理して、有効になっているすべてのフィード ID を一覧表示します。
// Program.cs
using Microsoft.Windows.Widgets.Feeds.Providers;
using Microsoft.Windows.Widgets.Providers;
using System;
using System.Runtime.InteropServices;
namespace ExampleFeedProvider
{
public static class Program
{
[DllImport("kernel32.dll")]
static extern IntPtr GetConsoleWindow();
[MTAThread]
static void Main(string[] args)
{
Console.WriteLine("FeedProvider Starting...");
if (args.Length > 0 && args[0] == "-RegisterProcessAsComServer")
{
WinRT.ComWrappersSupport.InitializeComWrappers();
uint registrationHandle;
var factory = new FeedProviderFactory<FeedProvider>();
Com.ClassObject.Register(typeof(FeedProvider).GUID, factory, out registrationHandle);
Console.WriteLine("Feed Provider registered.");
var existingFeedProviders = FeedManager.GetDefault().GetEnabledFeedProviders();
if (existingFeedProviders != null)
{
Console.WriteLine($"There are {existingFeedProviders.Length} FeedProviders currently outstanding:");
foreach (var feedProvider in existingFeedProviders)
{
Console.WriteLine($" ProviderId: {feedProvider.FeedProviderDefinitionId}, DefinitionIds: ");
var m = WidgetManager.GetDefault().GetWidgetIds();
if (feedProvider.EnabledFeedDefinitionIds != null)
{
foreach (var enabledFeedId in feedProvider.EnabledFeedDefinitionIds)
{
Console.WriteLine($" {enabledFeedId} ");
}
}
}
}
if (GetConsoleWindow() != IntPtr.Zero)
{
Console.WriteLine("Press ENTER to exit.");
Console.ReadLine();
}
else
{
while (true)
{
// You should fire an event when all the outstanding
// FeedProviders have been disabled and exit the app.
}
}
}
else
{
Console.WriteLine("Not being launched to service Feed Provider... exiting.");
}
}
}
}
このコード例では、GetConsoleWindow 関数をインポートして、アプリがコンソール アプリケーション (このチュートリアルの既定の動作) として実行されているかどうかを判断していることに注意してください。 関数から有効なポインターが返される場合は、デバッグ情報をコンソールに書き込みます。 それ以外の場合、アプリは Windows アプリとして実行されます。 その場合は、有効なフィード プロバイダーのリストが空のときに OnFeedProviderDisabled メソッドで設定したイベントを待って、アプリを終了します。 コンソール アプリの例を Windows アプリに変換する方法については、「コンソール アプリを Windows アプリに変換する」をご覧ください。
フィード プロバイダー アプリをパッケージ化する
現在のリリースでは、フィード プロバイダーとして登録できるのはパッケージ化されたアプリのみです。 次の手順では、アプリをフィード プロバイダーとして OS に登録するために、アプリをパッケージ化してアプリ マニフェストを更新するプロセスについて説明します。
MSIX パッケージ プロジェクトを作成する
ソリューション エクスプローラーでソリューションを右クリックして、[追加] > [新しいプロジェクト...] を選びます。[新しいプロジェクトの追加] ダイアログで "Windows アプリケーション パッケージ プロジェクト" テンプレートを選んで、[次へ] をクリックします。 プロジェクト名を "ExampleFeedProviderPackage" に設定して、[作成] をクリックします。 求められたらターゲット バージョンをビルド 22621 以降に設定し、[OK] をクリックします。 次に、ExampleFeedProviderPackage プロジェクトを右クリックして、[追加] -> [プロジェクト参照] を選びます。 ExampleFeedProvider プロジェクトを選んで、[OK] をクリックします。
Windows App SDK のパッケージ参照をパッケージ プロジェクトに追加する
Windows App SDK Nuget パッケージへの参照を、MSIX パッケージ プロジェクトに追加する必要があります。 ソリューション エクスプローラーで ExampleFeedProviderPackage プロジェクトをダブルクリックして、ExampleFeedProviderPackage.wapproj ファイルを開きます。 Project 要素内に次の XML を追加します。
<!--ExampleWidgetProviderPackage.wapproj-->
<ItemGroup>
<PackageReference Include="Microsoft.WindowsAppSDK" Version="1.5.231116003-experimentalpr">
<IncludeAssets>build</IncludeAssets>
</PackageReference>
</ItemGroup>
注意
PackageReference 要素で指定されている Version が、前のステップで参照した最新の安定バージョンと一致していることを確認します。
正しいバージョンの Windows アプリ SDK が既にコンピューターにインストールされていて、SDK のランタイムをパッケージにバンドルしたくない場合は、ExampleFeedProviderPackage プロジェクトの Package.appxmanifest ファイルでパッケージの依存関係を指定できます。
<!--Package.appxmanifest-->
...
<Dependencies>
...
<PackageDependency Name="Microsoft.WindowsAppRuntime.1.5.233430000-experimental1" MinVersion="2000.638.7.0" Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" />
...
</Dependencies>
...
パッケージ マニフェストを更新する
ソリューション エクスプローラーで Package.appxmanifest
ファイルを右クリックし、[コードの表示] を選んでマニフェストの xml ファイルを開きます。 次に、使用するアプリ パッケージ拡張機能用の名前空間の宣言をいくつか追加する必要があります。 最上位の Package 要素に次の名前空間定義を追加します。
<!-- Package.appmanifest -->
<Package
...
xmlns:uap3="http://schemas.microsoft.com/appx/manifest/uap/windows10/3"
xmlns:com="http://schemas.microsoft.com/appx/manifest/com/windows10"
Application 要素内に、Extensions という名前の新しい空の要素を作成します。 これは、uap:VisualElements の終了タグの後に必ず追加します。
<!-- Package.appxmanifest -->
<Application>
...
<Extensions>
</Extensions>
</Application>
追加する必要がある最初の拡張機能は、ComServer 拡張機能です。 これにより、実行可能ファイルのエントリ ポイントが OS に登録されます。 この拡張機能は、レジストリ キーを設定することで COM サーバーを登録するのと同等のパッケージ アプリの機能であり、ウィジェット プロバイダーに固有のものではありません。次の com:Extension 要素を、Extensions 要素の子として追加します。 com:Class 要素の Id 属性の GUID を、前のステップで FeedProvider クラスを定義した際に生成した GUID に変更します。
<!-- Package.appxmanifest -->
<Extensions>
<com:Extension Category="windows.comServer">
<com:ComServer>
<com:ExeServer Executable="ExampleFeedProvider\ExampleFeedProvider.exe" Arguments="-RegisterProcessAsComServer" DisplayName="C# Feed Provider App">
<com:Class Id="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" DisplayName="FeedProvider" />
</com:ExeServer>
</com:ComServer>
</com:Extension>
</Extensions>
次に、アプリをフィード プロバイダーとして登録する拡張機能を追加します。 次のコード スニペットの uap3:Extension 要素を、Extensions 要素の子として貼り付けます。 必ず、COM 要素の ClassId 属性を、前の手順で使った GUID に置き換えてください。
<!-- Package.appxmanifest -->
<Extensions>
...
<uap3:Extension Category="windows.appExtension">
<uap3:AppExtension Name="com.microsoft.windows.widgets.feeds" DisplayName="ContosoFeed" Id="com.examplewidgets.examplefeed" PublicFolder="Public">
<uap3:Properties>
<FeedProvider Icon="ms-appx:Assets\StoreLogo.png" Description="FeedDescription">
<Activation>
<!-- Apps exports COM interface which implements IFeedProvider -->
<CreateInstance ClassId="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" />
</Activation>
<Definitions>
<Definition Id="Contoso_Feed"
DisplayName="Contoso_Feed Feed"
Description="Feed representing Contoso"
ContentUri="https://www.contoso.com/"
Icon="ms-appx:Images\StoreLogo.png">
</Definition>
<Definition Id="Fabrikam_Feed"
DisplayName="Fabrikam Feed"
Description="Feed representing Example"
ContentUri="https://www.fabrikam.com/"
Icon="ms-appx:Images\StoreLogo.png">
</Definition>
</Definitions>
</FeedProvider>
</uap3:Properties>
</uap3:AppExtension>
</uap3:Extension>
</Extensions>
これらの要素の詳細な説明と形式の情報については、「フィード プロバイダー パッケージ マニフェストの XML 形式」をご覧ください。
フィード プロバイダーのテスト
[ソリューション プラットフォーム] ドロップダウンで選んだアーキテクチャが、開発用コンピューターと一致していることを確認します (例: "x64")。 ソリューション エクスプローラーでソリューションを右クリックして、[ソリューションのビルド] を選びます。 これが済んだら、ExampleWidgetProviderPackage を右クリックして [配置] を選びます。 デプロイ時にコンソール アプリが起動し、コンソール出力でフィードが有効になっていることがわかります。 ウィジェットボードを開くと、フィードセクションの上部にあるタブに新しいフィードが表示されます。
フィード プロバイダーのデバッグ
フィードをピン留めすると、フィードに関する関連情報を受信および送信するために、ウィジェット プラットフォームによってフィード プロバイダー アプリケーションが起動されます。 実行中のフィードをデバッグするには、実行中のフィード プロバイダー アプリケーションにデバッガーをアタッチするか、フィード プロバイダー プロセスの起動後にそのデバッグを自動的に開始するよう Visual Studio を設定することができます。
実行中のプロセスにアタッチするには:
- Visual Studio で、[デバッグ] > [プロセスにアタッチ] をクリックします。
- プロセスをフィルター処理し、目的のフィード プロバイダー アプリケーションを見つけます。
- デバッガーをアタッチします。
プロセスが最初に開始されるときにデバッガーを自動的にアタッチするには:
- Visual Studio で、[デバッグ] > [その他のデバッグ ターゲット] > [インストールされているアプリ パッケージのデバッグ] の順にクリックします。
- パッケージをフィルター処理し、目的のフィード プロバイダー パッケージを見つけます。
- それを選び、[起動はしないが、開始時にコードをデバッグする] チェック ボックスをオンにします。
- [アタッチ] をクリックします。
コンソール アプリを Windows アプリに変換する
このチュートリアルで作成したコンソール アプリを Windows アプリに変換するには、ソリューション エクスプローラーで [ExampleFeedProvider] プロジェクトを右クリックして、[プロパティ] を選びます。 [アプリケーション] > [全般] で、[出力の種類] を [コンソール アプリケーション] から [Windows アプリケーション] に変更します。
フィード プロバイダー アプリの公開
フィード プロバイダーを開発してテストした後は、ユーザーがフィードをデバイスにインストールできるように、Microsoft Store でアプリを発行する必要があります。 アプリを発行するための詳細なガイダンスについては、「Microsoft Store でアプリを発行する」をご覧ください。
フィード ストア コレクション
Microsoft Store でアプリが公開されたら、アプリをフィード ストア コレクションに含め、ユーザーが Windows フィードを備えるアプリを検出できるように要求できます。 要求を送信するには、「 フィード/ボードを送信してストア コレクションに追加する」を参照してください。
Windows developer