次の方法で共有


アプリ サービスの作成と利用

重要

このトピックのコード リストは C# のみです。 C++/WinRT および C# の App Service サンプル アプリについては、App service サンプル アプリに関するページを参照してください。

アプリ サービスは、他の UWP アプリにサービスを提供する UWP アプリです。 これらは、デバイス上のWebサービスに似ています。 アプリ サービスは、バック グラウンド タスクとしてホスト アプリで実行され、そのサービスを他のアプリに提供することができます。 たとえば、アプリ サービスによって、他のアプリで使用できるバー コード スキャナー サービスが提供される場合があります。 また、アプリのエンタープライズ スイートに共通のスペル チェック アプリ サービスを備えておき、そのサービスを同じスイート内の他のアプリから利用可能にする場合もあるでしょう。 アプリ サービスでは、同じデバイス上のアプリから呼び出せる UI を持たないサービスを作成できます。また、Windows 10 バージョン 1607 以降では、リモート デバイスからも呼び出せます。

Windows 10バージョン1607以降では、ホストアプリと同じプロセスで実行されるアプリサービスを作成できます。 この記事では、別のバックグラウンド プロセスで実行されるアプリ サービスの作成と使用に焦点を当てます。 プロバイダーと同じプロセスでアプリ サービスを実行する方法の詳細については、「 ホスト アプリと同じプロセスで実行するアプリ サービスを変換する 」を参照してください。

新しいアプリ サービス プロバイダー プロジェクトを作成する

このハウツーでは、わかりやすくするために、すべてを 1 つのソリューションで作成します。

  1. Visual Studio 2015 以降で、新しい UWP アプリ プロジェクトを作成し、これに AppServiceProvider という名前を付けます。

    1. [ファイル] > [新規] > [プロジェクト...] の順に選択します。
    2. [新しいプロジェクトの作成] ダイアログ ボックスで、[空のアプリ (ユニバーサル Windows) C#] を選択します。 これは、アプリ サービスを他の UWP アプリで使用できるようにするアプリです。
    3. [次へ] をクリックし、プロジェクトに AppServiceProvider という名前を付け、その場所を選択して、[作成] をクリックします。
  2. プロジェクトの[ターゲット][最小バージョン] の選択を求められたら、10.0.14393 以上を選びます。 新しい SupportsMultipleInstances 属性を使用する場合は、Visual Studio 2017 または Visual Studio 2019 を使用し、ターゲット 10.0.15063 (Windows 10 Creators Update) 以降を使用する必要があります。

Package.appxmanifest への App Service 拡張機能の追加

AppServiceProvider プロジェクトの Package.appxmanifest ファイルをテキスト エディターで開きます。

  1. ソリューション エクスプローラーで右クリックします。
  2. [プログラムから開く] を選択します。
  3. [XML (テキスト) エディター] を選択します。

次の AppService 拡張機能を <Application> 要素内に追加します。 この例では、 com.microsoft.inventory サービスをアドバタイズし、このアプリをアプリ サービス プロバイダーとして識別します。 実際のサービスはバックグラウンド タスクとして実装されます。 App Service プロジェクトは、サービスを他のアプリに公開します。 サービス名には逆ドメイン名スタイルを使用することをお勧めします。

xmlns:uap4名前空間プレフィックスと uap4:SupportsMultipleInstances 属性は、Windows SDK バージョン 10.0.15063 以降を対象としている場合にのみ有効です。 古い SDK バージョンを対象としている場合は、安全に削除できます。

Note

C++/WinRT および C# の App Service サンプル アプリについては、App service サンプル アプリに関するページを参照してください。

<Package
    ...
    xmlns:uap3="http://schemas.microsoft.com/appx/manifest/uap/windows10/3"
    xmlns:uap4="http://schemas.microsoft.com/appx/manifest/uap/windows10/4"
    ...
    <Applications>
        <Application Id="AppServiceProvider.App"
          Executable="$targetnametoken$.exe"
          EntryPoint="AppServiceProvider.App">
          ...
          <Extensions>
            <uap:Extension Category="windows.appService" EntryPoint="MyAppService.Inventory">
              <uap3:AppService Name="com.microsoft.inventory" uap4:SupportsMultipleInstances="true"/>
            </uap:Extension>
          </Extensions>
          ...
        </Application>
    </Applications>

Category 属性は、このアプリケーションを App Service プロバイダーとして識別します。

EntryPoint 属性は、サービスを実装する名前空間修飾クラスを識別します。これについては、次に実装します。

SupportsMultipleInstances 属性は、App Service が呼び出されるたびに、新しいプロセスで実行する必要があることを示します。 これは必須ではありませんが、その機能が必要で、10.0.15063 SDK (Windows 10 Creators Update) 以降を対象としている場合は使用できます。 また、 uap4 名前空間の前に置く必要があります。

App Service を作成する

  1. アプリ サービスはバックグラウンド タスクとして実装できます。 これにより、フォアグラウンド アプリケーションは別のアプリケーションでアプリ サービスを呼び出すことができます。 App Service をバックグラウンド タスクとして作成するには、MyAppService という名前の新しい Windows ランタイム コンポーネント プロジェクトをソリューションに追加 ([ファイル] > [追加] > [新しいプロジェクト]) します。 [新しいプロジェクトの追加] ダイアログ ボックスで、[インストール済み] > [Visual C#] > [Windows ランタイム コンポーネント (ユニバーサル Windows)] の順に選びます。

  2. AppServiceProvider プロジェクトで、新しい MyAppService プロジェクト (ソリューション エクスプローラーで、[AppServiceProvider] を右クリックし、[プロジェクト]>[追加]>[リファレンス]>[プロジェクト]>[ソリューション] から [MyAppService]>[OK] を選択) へプロジェクト間の参照を追加します。 参照を追加しない場合、アプリ サービスは実行時に接続されないため、この手順は重要です。

  3. MyAppService プロジェクトで、Class1.cs の上部に、次の using ステートメントを追加します。

    using Windows.ApplicationModel.AppService;
    using Windows.ApplicationModel.Background;
    using Windows.Foundation.Collections;
    
  4. Class1.cs から Inventory.cs に名前を変更し、Class1 のスタブ コードを Inventory という名前の新しいバックグラウンド タスク クラスに置き換えます。

    public sealed class Inventory : IBackgroundTask
    {
        private BackgroundTaskDeferral backgroundTaskDeferral;
        private AppServiceConnection appServiceconnection;
        private String[] inventoryItems = new string[] { "Robot vacuum", "Chair" };
        private double[] inventoryPrices = new double[] { 129.99, 88.99 };
    
        public void Run(IBackgroundTaskInstance taskInstance)
        {
            // Get a deferral so that the service isn't terminated.
            this.backgroundTaskDeferral = taskInstance.GetDeferral();
    
            // Associate a cancellation handler with the background task.
            taskInstance.Canceled += OnTaskCanceled;
    
            // Retrieve the app service connection and set up a listener for incoming app service requests.
            var details = taskInstance.TriggerDetails as AppServiceTriggerDetails;
            appServiceconnection = details.AppServiceConnection;
            appServiceconnection.RequestReceived += OnRequestReceived;
        }
    
        private async void OnRequestReceived(AppServiceConnection sender, AppServiceRequestReceivedEventArgs args)
        {
            // This function is called when the app service receives a request.
        }
    
        private void OnTaskCanceled(IBackgroundTaskInstance sender, BackgroundTaskCancellationReason reason)
        {
            if (this.backgroundTaskDeferral != null)
            {
                // Complete the service deferral.
                this.backgroundTaskDeferral.Complete();
            }
        }
    }
    

    このクラスは、アプリ サービスが作業を行う場所です。

    バックグラウンド タスクが作成されると、Run が呼び出されます。 バックグラウンド タスクは Run が完了した後に終了するため、バックグラウンド タスクが要求に対応できるように遅延が取り出されます。 バックグラウンド タスクとして実装されたアプリ サービスは、呼び出しを受信してから約 30 秒間存続します。ただし、その時間枠内で再度呼び出されるか、遅延が取り出されない限りです。アプリ サービスが呼び出し元と同じプロセスで実装されている場合、アプリ サービスの有効期間は呼び出し元の有効期間に関連付けられます。

    アプリ サービスの有効期間は、呼び出し元によって異なります。

    • 呼び出し元がフォアグラウンドである場合は、App Service の有効期間は、呼び出し元と同じです。
    • 呼び出し元がバックグラウンドである場合は、App Service は実行に 30 秒間が確保されます。 遅延を取り出す場合は、5 秒に 1 回追加されます。

    タスクが取り消されると、OnTaskCanceled が呼び出されます。 タスクが取り消されるのは、クライアント アプリが AppServiceConnection を破棄したとき、クライアント アプリが中断されたとき、OS がシャットダウンまたはスリープ状態になったとき、または OS がリソース不足になりタスクを実行できなくなったときです。

アプリ サービスのコードを記述する

OnRequestReceived は、App Service のコードが配置される場所です。 MyAppServiceInventory.cs のスタブ OnRequestReceived を、この例のコードに置き換えます。 このコードは、インベントリ項目のインデックスを取得し、それをコマンド文字列と共にサービスに渡して、指定された在庫品目の名前と価格を取得します。 独自のプロジェクトの場合は、エラー処理コードを追加します。

private async void OnRequestReceived(AppServiceConnection sender, AppServiceRequestReceivedEventArgs args)
{
    // Get a deferral because we use an awaitable API below to respond to the message
    // and we don't want this call to get canceled while we are waiting.
    var messageDeferral = args.GetDeferral();

    ValueSet message = args.Request.Message;
    ValueSet returnData = new ValueSet();

    string command = message["Command"] as string;
    int? inventoryIndex = message["ID"] as int?;

    if (inventoryIndex.HasValue &&
        inventoryIndex.Value >= 0 &&
        inventoryIndex.Value < inventoryItems.GetLength(0))
    {
        switch (command)
        {
            case "Price":
            {
                returnData.Add("Result", inventoryPrices[inventoryIndex.Value]);
                returnData.Add("Status", "OK");
                break;
            }

            case "Item":
            {
                returnData.Add("Result", inventoryItems[inventoryIndex.Value]);
                returnData.Add("Status", "OK");
                break;
            }

            default:
            {
                returnData.Add("Status", "Fail: unknown command");
                break;
            }
        }
    }
    else
    {
        returnData.Add("Status", "Fail: Index out of range");
    }

    try
    {
        // Return the data to the caller.
        await args.Request.SendResponseAsync(returnData);
    }
    catch (Exception e)
    {
        // Your exception handling code here.
    }
    finally
    {
        // Complete the deferral so that the platform knows that we're done responding to the app service call.
        // Note for error handling: this must be called even if SendResponseAsync() throws an exception.
        messageDeferral.Complete();
    }
}

OnRequestReceivedasync であることに注意してください。この例では、SendResponseAsync への待機可能なメソッド呼び出しを行うためです。

保留が行われるのは、サービスが OnRequestReceived ハンドラーで async メソッドを使用できるようにするためです。 これにより、メッセージの処理が完了するまで、 OnRequestReceived の呼び出しは完了しません。 SendResponseAsync は、結果を呼び出し元に送信します。 SendResponseAsync は呼び出しの完了を通知しません。 これは、OnRequestReceived が完了したことをSendMessageAsyncに通知する遅延の完了です。 SendResponseAsync の呼び出しは、SendResponseAsync が例外をスローした場合でも保留を完了する必要があるため、try/finally ブロックでラップされます。

App Services では ValueSet オブジェクトを使って情報を交換します。 渡すことのできるデータのサイズは、システム リソースによってのみ制限されます。 ValueSet で使用できる定義済みのキーはありません。 App Service のプロトコルを定義するために使用するキー値を決定する必要があります。 呼び出し元は、そのプロトコルを念頭に置いて記述する必要があります。 この例では、 Command という名前のキーを選択しました。このキーには、App Service で在庫品目の名前またはその価格を指定するかどうかを示す値が含まれています。 インベントリ名のインデックスは、 ID キーの下に格納されます。 戻り値は、 Result キーの下に格納されます。

AppServiceClosedStatus 列挙型が呼び出し元に返され、アプリ サービスへの呼び出しが成功したか失敗したかが示されます。 アプリ サービスの呼び出しが失敗する可能性がある例は、リソースが超過したために OS がサービス エンドポイントを中止した場合です。 ValueSet を使用して、追加のエラー情報を返すことができます。 この例では、 Status という名前のキーを使用して、より詳細なエラー情報を呼び出し元に返します。

SendResponseAsync の呼び出しはValueSetを呼び出し元に返します。

サービス アプリをデプロイし、パッケージ ファミリ名を取得する

クライアントから呼び出す前に、App Service プロバイダーを展開する必要があります。 Visual Studio の [ビルド] > [ソリューションの配置] を選択して展開できます。

これを呼び出すには、App Service プロバイダーのパッケージ ファミリ名も必要になります。 これは、デザイナー ビューで AppServiceProvider プロジェクトの Package.appxmanifest ファイルを開いて取得できます (ソリューション エクスプローラー でダブルクリックします)。 [パッケージ化] タブを選択し、[パッケージ ファミリ名] 横の値をコピーし、一旦メモ帳などに貼り付けます。

アプリ サービスを呼び出すクライアントを作成する

  1. File > Add > New Project を使用して、新しい空の Windows ユニバーサル アプリ プロジェクトをソリューションに追加[新しいプロジェクトの追加] ダイアログ ボックスで、[インストール済み] > [Visual C#] > [空のアプリ (ユニバーサル Windows)] の順に選び、ClientAppという名前を付けます。

  2. ClientApp プロジェクトで、MainPage.xaml.cs の上部に、次の using ステートメントを追加します。

    using Windows.ApplicationModel.AppService;
    
  3. textBox というテキスト ボックスとボタンを MainPage.xaml に追加します。

  4. button_Click というボタンのクリック ハンドラーを追加し、ボタン ハンドラーの署名にキーワード async を追加します。

  5. ボタン クリック ハンドラーのスタブを次のコードに置き換えます。 必ず inventoryService フィールド宣言を含めます。

    private AppServiceConnection inventoryService;
    
    private async void button_Click(object sender, RoutedEventArgs e)
    {
       // Add the connection.
       if (this.inventoryService == null)
       {
           this.inventoryService = new AppServiceConnection();
    
           // Here, we use the app service name defined in the app service 
           // provider's Package.appxmanifest file in the <Extension> section.
           this.inventoryService.AppServiceName = "com.microsoft.inventory";
    
           // Use Windows.ApplicationModel.Package.Current.Id.FamilyName 
           // within the app service provider to get this value.
           this.inventoryService.PackageFamilyName = "Replace with the package family name";
    
           var status = await this.inventoryService.OpenAsync();
    
           if (status != AppServiceConnectionStatus.Success)
           {
               textBox.Text= "Failed to connect";
               this.inventoryService = null;
               return;
           }
       }
    
       // Call the service.
       int idx = int.Parse(textBox.Text);
       var message = new ValueSet();
       message.Add("Command", "Item");
       message.Add("ID", idx);
       AppServiceResponse response = await this.inventoryService.SendMessageAsync(message);
       string result = "";
    
       if (response.Status == AppServiceResponseStatus.Success)
       {
           // Get the data  that the service sent to us.
           if (response.Message["Status"] as string == "OK")
           {
               result = response.Message["Result"] as string;
           }
       }
    
       message.Clear();
       message.Add("Command", "Price");
       message.Add("ID", idx);
       response = await this.inventoryService.SendMessageAsync(message);
    
       if (response.Status == AppServiceResponseStatus.Success)
       {
           // Get the data that the service sent to us.
           if (response.Message["Status"] as string == "OK")
           {
               result += " : Price = " + response.Message["Result"] as string;
           }
       }
    
       textBox.Text = result;
    }
    

    this.inventoryService.PackageFamilyName = "Replace with the package family name";行のパッケージ ファミリ名を、「サービス アプリをデプロイし、パッケージ ファミリ名を取得するAppServiceProvider プロジェクトのパッケージ ファミリ名に置き換えます

    Note

    文字列リテラルは、変数に配置するのではなく、必ず貼り付けてください。 変数を使用した場合は機能しません。

    コードは、最初に App Service との接続を確立します。 接続は、 this.inventoryService破棄するまで開いたままです。 App Service 名は、AppServiceProvider プロジェクトの Package.appxmanifest ファイルに追加した AppService 要素の Name 属性と一致する必要があります。 この例では <uap3:AppService Name="com.microsoft.inventory"/> です。

    message という名前の ValueSet が作成され、App Service に送信するコマンドを指定します。 このアプリ サービスの例では、2 つのアクションのうちどれを実行するかを示すコマンドが必要です。 クライアント アプリのテキスト ボックスからインデックスを取得し、Item コマンドでサービスを呼び出して項目の説明を取得します。 次に、 Price コマンドを使用してアイテムの価格を取得する呼び出しを行います。 ボタンのテキストが結果に設定されます。

    AppServiceResponseStatusは、オペレーティング システムがアプリ サービスへの呼び出しを接続できたかどうかを示すだけなので、ValueSet でStatus キーを確認しますアプリ サービスから受信して、要求を満たすことができることを確認します。

  6. ClientApp プロジェクトをスタートアップ プロジェクトとして設定し (ソリューション エクスプローラー>[スタートアップ プロジェクトとして設定] で右クリック)、ソリューションを実行します。 テキスト ボックスに数値 1 を入力し、ボタンをクリックします。 サービスから "Chair : Price = 88.99" が返されます。

    椅子の価格を表示するサンプル アプリ=88.99

App Service の呼び出しが失敗した場合は、ClientApp プロジェクトで次のことを確認します。

  1. インベントリ サービスの接続に割り当てられたパッケージ ファミリ名が、AppServiceProvider アプリのパッケージ ファミリ名と一致することを確認します。 this.inventoryService.PackageFamilyName = "..."; を含む button_Click の行をご覧ください。
  2. button_Click で、インベントリ サービスの接続に割り当てられた App Service 名が、AppServiceProviderPackage.appxmanifest ファイルの App Service 名と一致することを確認します。 this.inventoryService.AppServiceName = "com.microsoft.inventory";を参照してください。
  3. AppServiceProvider アプリが展開済みであることを確認します。 (ソリューション エクスプローラーで、[ソリューション] を右クリックし、[ソリューションの配置] を選択します)。

アプリ サービスをデバッグする

  1. サービスを呼び出す前にアプリ サービス プロバイダー アプリをデプロイする必要があるため、デバッグの前にソリューションがデプロイされていることを確認します。 (Visual Studio では、 ソリューションのビルド > デプロイ)。
  2. ソリューション エクスプローラーで、AppServiceProvider プロジェクトを右クリックして、[プロパティ] を選択します。 Debug タブで、Start アクションDo に変更しますが、起動時にコードをデバッグします。 (C++ を使用してアプリ サービス プロバイダーを実装していた場合は、 [デバッグ ] タブで、 アプリケーションの起動No) に変更します。
  3. MyAppService プロジェクトの Inventory.cs ファイルで、OnRequestReceived にブレークポイントを設定します。
  4. AppServiceProvider プロジェクトをスタートアップ プロジェクトとなるように設定し、F5 キーを押します。
  5. (Visual Studio からではなく) [スタート] メニューから ClientApp を起動します。
  6. テキスト ボックスに数値 1 を入力し、ボタンを押します。 デバッガーは、アプリ サービスのブレークポイントの App Service 呼び出しで停止します。

クライアントをデバッグする

  1. 前の手順の手順に従って、アプリ サービスを呼び出すクライアントをデバッグします。
  2. [スタート] メニューから ClientApp を起動します。
  3. (ApplicationFrameHost.exe プロセスではなく) ClientApp.exe プロセスにデバッガーをアタッチします。 (Visual Studio で、 デバッグ > プロセスへのアタッチ...)。)
  4. ClientApp プロジェクトで、button_Click にブレークポイントを設定します。
  5. ClientApp のテキスト ボックスに数値 1 を入力してボタンをクリックすると、クライアントと App Service の両方のブレークポイントがヒットするようになります。

一般的な App Service のトラブルシューティング

App Service に接続しようとして AppUnavailable 状態が発生した場合、以下を確認します。

  • アプリ サービス プロバイダー プロジェクトと App Service プロジェクトがデプロイされていることを確認します。 クライアントを実行する前に両方を展開する必要があります。そうしないと、クライアントに接続するものがないためです。 Visual Studio からデプロイするには、 Build>Deploy Solution を使用します。
  • ソリューション エクスプローラーを使って、App Service プロバイダー プロジェクトで、App Service を実装したプロジェクトへの、プロジェクト間の参照が設定されていることを確認します。
  • <Extensions> エントリとその子要素が、App Service プロバイダー プロジェクトに属する Package.appxmanifest ファイルに追加されていることを確認します。詳しくは上述の「Package.appxmanifest への App Service 拡張機能の追加」をご覧ください。
  • App Service プロバイダーを呼び出すクライアントの AppServiceConnection.AppServiceName 文字列が、App Service プロバイダー プロジェクトの Package.appxmanifest ファイルで指定された <uap3:AppService Name="..." /> と一致していることを確認します。
  • AppServiceConnection.PackageFamilyName が、App Service プロバイダーのコンポーネントのパッケージ ファミリ名と一致していることを確認します。詳しくは上述の「Package.appxmanifest への App Service 拡張機能の追加」をご覧ください。
  • この例のようなプロセス外の App Services では、App Service プロバイダー プロジェクトの Package.appxmanifest ファイルの <uap:Extension ...> 要素で指定された EntryPoint が、App Service プロジェクトで IBackgroundTask を実装するパブリック クラスの名前空間とクラス名と一致していることを確認します。

デバッグのトラブルシューティング

デバッガーがアプリ サービス プロバイダーまたはアプリ サービス プロジェクトのブレークポイントで停止しない場合は、次の点を確認します。

  • アプリ サービス プロバイダー プロジェクトと App Service プロジェクトがデプロイされていることを確認します。 クライアントを実行する前に、両方をデプロイする必要があります。 Build>Deploy Solution を使用して、Visual Studio からデプロイできます。
  • デバッグするプロジェクトがスタートアップ プロジェクトとして設定されていることを確認します。そのプロジェクトのデバッグ プロパティを確認し、F5 キーが押されたときにプロジェクトを実行しないように設定されていることを確認します。 プロジェクトを右クリックし、 PropertiesDebug (または C++ の場合は Debugging ) をクリックします。 C# で、 Start アクションに変更します。起動せず、起動時にコードをデバッグします。 C++ で、 Launch ApplicationNo に設定します。

解説

この例では、バックグラウンド タスクとして実行されるアプリ サービスを作成し、別のアプリから呼び出す方法の概要を示します。 次の点に注意してください。

  • App service をホストするバックグラウンド タスクを作成します。
  • App service プロバイダーの Package.appxmanifest ファイルに windows.appService 拡張機能を追加します。
  • App service プロバイダーのパッケージ ファミリ名を取得し、クライアント アプリからアプリに接続できるようにします。
  • App service プロバイダー プロジェクトから App service プロジェクトへのプロジェクト間参照を追加します。
  • Windows.ApplicationModel.AppService.AppServiceConnection を使用してサービスを呼び出します。

MyAppService の完全なコード

using System;
using Windows.ApplicationModel.AppService;
using Windows.ApplicationModel.Background;
using Windows.Foundation.Collections;

namespace MyAppService
{
    public sealed class Inventory : IBackgroundTask
    {
        private BackgroundTaskDeferral backgroundTaskDeferral;
        private AppServiceConnection appServiceconnection;
        private String[] inventoryItems = new string[] { "Robot vacuum", "Chair" };
        private double[] inventoryPrices = new double[] { 129.99, 88.99 };

        public void Run(IBackgroundTaskInstance taskInstance)
        {
            // Get a deferral so that the service isn't terminated.
            this.backgroundTaskDeferral = taskInstance.GetDeferral();

            // Associate a cancellation handler with the background task.
            taskInstance.Canceled += OnTaskCanceled;

            // Retrieve the app service connection and set up a listener for incoming app service requests.
            var details = taskInstance.TriggerDetails as AppServiceTriggerDetails;
            appServiceconnection = details.AppServiceConnection;
            appServiceconnection.RequestReceived += OnRequestReceived;
        }

        private async void OnRequestReceived(AppServiceConnection sender, AppServiceRequestReceivedEventArgs args)
        {
            // Get a deferral because we use an awaitable API below to respond to the message
            // and we don't want this call to get canceled while we are waiting.
            var messageDeferral = args.GetDeferral();

            ValueSet message = args.Request.Message;
            ValueSet returnData = new ValueSet();

            string command = message["Command"] as string;
            int? inventoryIndex = message["ID"] as int?;

            if (inventoryIndex.HasValue &&
                 inventoryIndex.Value >= 0 &&
                 inventoryIndex.Value < inventoryItems.GetLength(0))
            {
                switch (command)
                {
                    case "Price":
                        {
                            returnData.Add("Result", inventoryPrices[inventoryIndex.Value]);
                            returnData.Add("Status", "OK");
                            break;
                        }

                    case "Item":
                        {
                            returnData.Add("Result", inventoryItems[inventoryIndex.Value]);
                            returnData.Add("Status", "OK");
                            break;
                        }

                    default:
                        {
                            returnData.Add("Status", "Fail: unknown command");
                            break;
                        }
                }
            }
            else
            {
                returnData.Add("Status", "Fail: Index out of range");
            }

            // Return the data to the caller.
            await args.Request.SendResponseAsync(returnData);

            // Complete the deferral so that the platform knows that we're done responding to the app service call.
            // Note for error handling: this must be called even if SendResponseAsync() throws an exception.
            messageDeferral.Complete();
        }


        private void OnTaskCanceled(IBackgroundTaskInstance sender, BackgroundTaskCancellationReason reason)
        {
            if (this.backgroundTaskDeferral != null)
            {
                // Complete the service deferral.
                this.backgroundTaskDeferral.Complete();
            }
        }
    }
}