次の方法で共有



May 2018

Volume 33 Number 5

ユニバーサル Windows プラットフォーム - UWP と Win32 のギャップを埋める

によってAndrew Whitechapel

ユニバーサル Windows プラットフォーム (UWP) と従来の Win32 アプリ モデル間のギャップを閉じて Windows の最新の更新プログラムの重要なテーマのいずれかのことにしました。この作業の一環として、Microsoft には、次の 3 つの主な機能強化が導入されました。

  • 複数インスタンス化
  • コンソールの UWP アプリ
  • 広範なファイル システム アクセス

機能は、関連するが、互いに独立します。つまり、正規のウィンドウを持つアプリまたはコンソール アプリのいずれかである複数インスタンス化のアプリを作成できます: 場合があるし、必要なより広範なファイル システムにアクセスできません。同様に、広範なファイル システム アクセス権を持つ正規コンソール以外、マルチ インスタンスではないアプリを作成できます。1 つの制限は、複数インスタンス化をサポートするために、コンソール アプリケーションを構成する必要があります。

複数インスタンス化

Win32、Linux およびその他のアプリ モデル環境では、複数インスタンス化が常に、既定ありました。UWP ではっきりとは異なり、既定値は常にでしたシングル インスタンス —、実際には、複数インスタンス化されていないでサポートされているこれまでとします。

複数インスタンス化せず、一部のアプリケーションが再度並べ替えられたりした複数の windowing アーキテクチャを代わりに、通常大変な作業が含まれます: と複雑さと脆弱性の結果。多くのドメインの要件に焦点を当てたではなく、windows の管理のための労力を費やす必要があります。単一プロセスの複数の windowing は、信頼性の問題からも低下します。すべてのウィンドウをもたらすことに 1 つのインスタンスがクラッシュした場合そうでない複数のインスタンス、各インスタンスが別のプロセスとして実行されているためです。

ユーザー モデルでは、単一インスタンス、さまざまな方法でアプリをアクティブ化できますスタート; タイル tap を使用して。を介して、URL またはプロトコルのアクティブ化します。アプリ; に登録されている拡張子を持つファイルをダブルクリックします。などなど。(任意の種類の) 最初のアクティブ化では、アプリが起動します。その後、以降のアクティブ化は、単に OnActivated メソッドをオーバーライドすることで、アプリを処理できると、アプリの実行中のインスタンスを呼び出します。

複数インスタンス化の新機能により、Win32 アプリと同様に動作する UWP アプリ。アプリのインスタンスが実行されている、後続のライセンス認証要求を受信した場合は、プラットフォームを既存のインスタンスをアクティブ化する呼び出すはありません。代わりに、別のプロセスで新しいインスタンスが作成されます。

この機能は、Win32 パリティに大きく左右されるため、最初にデスクトップや IoT だけではサポートされています。2 つのレベルの複数インスタンス化のサポートが導入されています。

  • UWP アプリの複数インスタンス:これは、単純な場合、ここで、アプリたいと思って宣言の複数インスタンス化する必要があります。
  • マルチ インスタンス UWP アプリのリダイレクト:これは複雑な場合は、ここで、アプリは、複数インスタンス化を希望していますもたい各インスタンスをアクティブにする方法に正確に言うです。

どちらの場合も、Visual Studio プロジェクト テンプレートが提供されてのように図 1です。

アプリの複数インスタンス化の新しいプロジェクト テンプレート
アプリの複数インスタンス化の新しいプロジェクトのテンプレートを図 1

単純なケースでは、プロジェクト テンプレートは、空のアプリケーション テンプレート コードとほぼ同じであるコードを生成します。唯一の違いは、アプリ マニフェストで SupportsMultipleInstances 属性の使用中です。その他の 2 つの宣言があります。1 つは、desktop4 と iot2 XML 名前空間のマニフェストの上部には。

xmlns:desktop4="https://schemas.microsoft.com/appx/manifest/desktop/windows10/4"
xmlns:iot2="https://schemas.microsoft.com/appx/manifest/iot/windows10/2"
  IgnorableNamespaces="uap mp desktop4 iot2">

2 つ目は、< Application > 要素の属性を追加します。

<Application
  Id="App8" Executable="$targetnametoken$.exe" EntryPoint="App8.App"
  desktop4:SupportsMultipleInstances="true"
  iot2:SupportsMultipleInstances="true">

新しいアプリを生成することができます単にこれらのエントリをマニフェストに手動で追加するのではなく、既存のアプリのコードを更新しています。これを終了したら、アプリをビルドし、複数のインスタンスを起動できます。このマニフェスト エントリ、アプリがアクティブ化するたびに — コントラクト アプリケーションがサポートする、ファイルの関連付けまたはプロトコルの起動などのタイル tap、またはその他のすべてのアクティブ化からかどうか、別のインスタンスでアクティブ化のたびになります。こんなに簡単です。

マルチ インスタンスのリダイレクト

ほとんどのアプリ マニフェストのエントリの追加を行うには必要なが細かくそのインスタンスのアクティブ化を制御するアプリでは、2 番目のテンプレートを使用することができます。この、正確に同じマニフェスト入力を追加しで示すようにも、追加のファイル (Program.cs (C#) アプリの場合) または Program.cpp C++ の標準的なメイン関数を含むを追加図 2です。このリリースで導入された新しい AppInstance クラスを使用します。

マルチ インスタンスのリダイレクトの標準的なメイン関数を図 2

static void Main(string[] args)
{
  IActivatedEventArgs activatedArgs = AppInstance.GetActivatedEventArgs();
  if (AppInstance.RecommendedInstance != null)
  {
    AppInstance.RecommendedInstance.RedirectActivationTo();
  }
  else
  {
    uint number = CryptographicBuffer.GenerateRandomNumber();
    string key = (number % 2 == 0) ? "even" : "odd";
    var instance = AppInstance.FindOrRegisterInstanceForKey(key);
    if (instance.IsCurrentInstance)
    {
      global::Windows.UI.Xaml.Application.Start((p) => new App());
    }
    else
    {
      instance.RedirectActivationTo();
    }
  }
}

関数はまずとこのインスタンスのアクティブ化の引数を取得します。アプリのリダイレクト ロジックの一部としてこれらの引数に保持されている情報を使用可能性があります。

一部のシナリオで、プラットフォームは、推奨されるインスタンスを可能性があります。場合は、リダイレクトできますこのアクティブ化をそのインスタンスに代わりに、AppInstance.RedirectActivationTo メソッドを使用して、希望する場合。つまり、アプリは、代わりに既存のインスタンスにリダイレクトするには、このアクティブ化要求を許可するを選択できます。リダイレクトは、ターゲット インスタンスがアクティブ化され、その OnActivated メソッドが呼び出される場合、— この新しいインスタンスを終了します。

場合は、プラットフォーム、優先するインスタンスと示されない、進めてしてキーを作成します。ランダムな数値からキーを作成するコード例を通常このコードを交換し、アプリで定義されたロジックに基づいたキーを作成します。通常これはに基づいて以前に取得されたアクティベーション引数。たとえば、アクティベーション引数 FileActivatedEventArgs 型の場合は、アプリ可能性がありますを使用して指定したファイル名、キーの一部として。キーで構成した後は、このアプリのインスタンスを表す AppInstance オブジェクトを取得する、FindOrRegisterInstanceForKey メソッドに渡します。返す先のインスタンスを特定するのには、メソッドは、次の 2 つをは。

  • このキーは既に登録したアプリの既存のインスタンスを検索します。
  • 既存のインスタンスが既に登録されていない場合このキーをこのキーを持つこの現在のインスタンスを登録します。

このインスタンスを正常に登録した場合をできるようになりました進めて、通常のアプリの初期化を実行します。XAML アプリの場合は、App クラスの新しいインスタンスを Application.Start を呼び出すことを意味します。その他のいくつかのインスタンスでは、このキーは既に登録場合、そのインスタンスを代わりに、このライセンス認証をリダイレクトし、終了するには、このインスタンスを許可するようになりましたできます。たとえば、ファイルを編集するアプリを検討してください。ユーザーは、Foo.doc を開いて、アプリの編集を持ち、し、もう一度 Foo.doc を開こうとすると、アプリ場合 Foo.doc 開くには既にインスタンスに 2 つ目のライセンス認証をリダイレクトする — をユーザーが複数のインスタンスで同じファイルを開くことを防ぐ。リダイレクト先として選択するインスタンスと、リダイレクトするかどうかを決定するためのロジックでは、完全アプリで定義します。

XAML アプリの場合は、Main メソッドは通常自動的に生成されると、developer から非表示です。この動作は、「リダイレクトと複数のインスタンス」テンプレートで抑制されます。既存のアプリを更新する場合は、DISABLE_XAML_GENERATED_MAIN をアプリのビルド プロパティで条件付きコンパイル シンボルの一覧に追加することで、既定のメインを抑制できます。いくつかの種類のアプリで — たとえば、C++ DirectX アプリ — Main 関数が非表示になっていません。別に、新しい Api の DirectX アプリの使用は XAML の例のように同じパターンに従います。

アプリのみを使用 GetActivatedEventArgs および RedirectActivationTo メソッドに関して、メイン; 中にこれらは、呼び出された場合他の場所から、それらは失敗します。これは、ライセンス認証のリダイレクトを行う場合は、これを行う必要がありますので非常に有効期間の初期と確実に開始する前に、アプリのプロセスの windows が作成されます。

その一方で、いつでも、残りの AppInstance メソッドとプロパティを使用することができます。具体的には、するのに必要がある場合、現在のインスタンスのキーを更新するのに FindOrRegisterInstanceForKey を使用することができます。たとえば、ファイル名に基づいて、キーが、後でこのファイルを閉じる場合は、その時点で、キーの登録のパスを更新します。登録解除メソッドを使用して、この特定のインスタンスのライセンス認証のリダイレクトを行う必要がなくなった何らかの理由で完全に登録を解除することができますも。また、いつでもの状態について推論できるように、キーを含む、アプリのすべての登録済みインスタンスの一覧を取得するのに AppInstance.GetInstances メソッドを使用できます。

その他の考慮事項

主要な拡張機能では、複数インスタンス化と、最初のリリースが主要なシナリオだけについて説明します。具体的には、サポートは、フォア グラウンド アプリの複数インスタンス化、コンソール アプリ、およびアプリのサービスを含むほとんどのアウト プロセスのバック グラウンド タスクの含まれています。ただしはありません ApplicationTrigger タスクのこのリリースでサポートや、インプロセスのバック グラウンド タスクです。

開発時に、Microsoft は、広範な複数インスタンス化時に実行する方法を表示する既存のストア アプリをテスト非常に長い時間を費やしたです。Microsoft では、ここから、アプリが 3 つのカテゴリに分類することについて学習しました。

  • 複数インスタンス化する理由がないアプリ。これらのアプリだけされませんをオプトイン機能です。
  • 複数インスタンス化にして、引き続きコード変更を加えずに正しく機能するアプリです。これらのアプリは複数インスタンス化することを選択し、これを呼び出すだけです。
  • 実行モデルの相違を許可する作業を実行する必要がある複数インスタンス化にするアプリです。

3 番目のカテゴリのアプリを使用して、一般的な問題は、サーバーの全体の複数のリソースを使用していること: など、キャッシュ、または、データベース、またはその他のファイル- と単一インスタンスでしたされて安全と仮定した場合、アプリがこのリソースへの排他アクセスを持つことです。複数インスタンス化することを選択すると、リソースにアクセスしようとしています。 複数のインスタンスである可能性があります。このシナリオでは、アプリはアクセス、ロックの読み取りと書き込みを同期するために作業を実行する必要があります: つまり、通常のすべての同期の問題を考慮するその従来の Win32 アプリ必要です。

明確な例として、アプリのローカル ストレージの使用を検討します。これは、リソースのアクセスがプロセスではなく、パッケージごとに制限がある-アプリのすべてのインスタンスが同じパッケージを共有するのとします。アプリの各インスタンスが別のプロセスとして実行されているはすべて、同じローカル記憶域と設定を使用、ApplicationData.Current API によって表されるようにします。ローカル ストレージにデータ アクセス操作を実行する場合は、競合から保護する方法を検討してください。1 つのオプションでは、ここで 1 つのインスタンスの操作が競合のもう一方のインスタンス固有のファイルを使用します。または、複数のインスタンス間で共通のファイルを使用する場合は、ロックおよびファイルへのアクセスを適切にロックを解除する必要があります。この名前付きミュー テックスなどの標準のメカニズムを使用できます。

UWP アプリのコンソール

別の明らかなギャップ UWP とりまく環境では、ヘッドレス コンソール アプリを作成する機能です。Win32 およびその他の環境では、入力と出力をコンソール ウィンドウを使用するコマンド ライン ツールを作成できます。そのため、このサポートもお追加されました。もう一度、新しい Visual Studio プロジェクト テンプレートがあるし、アプリの複数インスタンス化を使用して、追加のマニフェスト エントリが生成されます。デスクトップと IoT にこの機能は制限されても、それらの Sku だけでコンソール ウィンドウを今すぐが実際にはない最小限です。同一の XML 名前空間が宣言されています。< Application > 要素には、"console"に設定されたサブシステムの SupportsMultipleInstances とサブシステムの両方の属性が含まれています。コンソール アプリは、複数インスタンス化する必要があります-これは、従来の Win32 コンソール アプリから移動アプリの予想されるモデル。さらに、アプリには、AppExecutionAlias が含まれます: され、これも、新しいサブシステム属性のように図 3です。

図 3 コンソール アプリの追加のマニフェスト エントリ。

<Application Id="App"
  Executable="$targetnametoken$.exe"
  EntryPoint="App9.App"
  desktop4:Subsystem="console"
  desktop4:SupportsMultipleInstances="true"
  iot2:Subsystem="console"
  iot2:SupportsMultipleInstances="true">
...
  <Extensions>
    <uap5:Extension
      Category="windows.appExecutionAlias"
      Executable="App9.exe"
      EntryPoint="App9.App">
      <uap5:AppExecutionAlias
         desktop4:Subsystem="console" 
        iot2:Subsystem="console">
        <uap5:ExecutionAlias Alias="App9.exe"/>
      </uap5:AppExecutionAlias>
    </uap5:Extension>
  </Extensions>
</Application>

エイリアスの値は、アプリの適切な名前を変更できます。もう一度、複数インスタンスの場合と同様にコード生成にはする際に、Program.cs ファイルまたは Program.cpp ファイルが含まれます。C++ の例で示すように、生成されたコードが必要なの主な機能を実装する方法の例を示します図 4です。カスタム コードで main 内のすべてのコードを置き換えることができます。

図 4 テンプレートによって生成されたコードがコンソール アプリケーションの Main 関数

int __cdecl main()
{
  // You can get parsed command-line arguments from the CRT globals.
  wprintf(L"Parsed command-line arguments:\n");
  for (int i = 0; i < __argc; i++)
  {
    wprintf(L"__argv[%d] = %S\n", i, __argv[i]);
  }
  wprintf(L"Press Enter to continue:");
  getchar();
}

構築し、アプリを展開したらを実行できますが正規のコマンド プロンプト、PowerShell ウィンドウで、または Windows-R からのように図 5です。アプリは、コンソール ウィンドウを使用するためがないと想定を他のウィンドウを作成するメモ: 実際には、これはサポートされていません。代わりに、アプリですべての System.Console Api とコンソール アプリをサポートするために、承認済みリストに追加されましたが従来の Win32 Api が多く使用できます。

コマンドラインからコンソール UWP アプリの実行
図 5 のコマンドラインからコンソール UWP アプリの実行

この機能により、最後に APPX パッケージを含む、UWP の利点を活用、パブリケーション、簡単な更新プログラムに保存するコマンド ライン コンソール アプリをビルドすることができます。

広範なファイル システム アクセス

これまでは、UWP アプリだけだった画像ライブラリやミュージック ライブラリなど、特定の特定のフォルダーにアクセスできなければ — し、アプリが自らのマニフェストで機能としてこれらを宣言する場合のみです。さらに、アプリは、FilePicker ダイアログを発生させると、ユーザーにアプリのアクセス許可を付与する場所を選択してファイル システムにその他の場所へのアクセスを取得する可能性があります。

ここで、Win32 パリティ用に追加する 3 番目の主要な機能は、UWP アプリのファイル システム アクセスのレベルを増加します。これは、2 つの方法を含めることで。

  • 現在の作業ディレクトリに暗黙的にアクセスします。
  • 広範なファイル システム アクセスを制限付き機能によって制御します。

任意の UWP アプリ (通常のウィンドウを持つアプリまたはコンソール アプリケーション)、AppExecutionAlias を宣言するでは、アクティブ化すると、コマンドラインから、ファイルとフォルダーの現在の作業ディレクトリへの暗黙的なアクセスがようになりました付与します。現在の作業ディレクトリは、どのようなファイル システムの場所から、ユーザーが、AppExecutionAlias の実行を選択します。時間が長く協議するこれが、UWP モデルが常にアプリへのファイル システム アクセス許可の付与について非常に注意してください。結局、特定の場所からアプリを実行するユーザーが FilePicker] ダイアログで権限の付与の観点から場所を選択するユーザーと同じであることを決定しました。

アプリが正確に同じファイルのアクセス許可として、アプリを実行しているユーザーを持つことに注意する必要は — がある可能性がありますファイルまたはフォルダーのため、アプリにアクセスできない、ユーザーがアクセスできないため、いずれか。たとえば、dir コマンドを実行するときに、ユーザーが隠しファイルを表示することはできない場合、アプリもことはできませんを非表示ファイルを参照してください。

この機能を利用するを CommandLineActivatedEventArgs 探して OnActivated オーバーライドをコーディングできます。これが含まれます、CurrentDirectoryPath にはここでは、ユーザーが、AppExecutionAlias を実行するためのファイル システムの場所がなる予定です。図 6例を示します。 ここでは、アプリは、現在のディレクトリを抽出し、MainPage に渡します。

図 6 のコマンドラインのアクティブ化の OnActivated を上書きします。

protected override void OnActivated(IActivatedEventArgs args)
{
  switch (args.Kind)
  {
    case ActivationKind.CommandLineLaunch:
      CommandLineActivatedEventArgs cmdLineArgs =
         args as CommandLineActivatedEventArgs;
      CommandLineActivationOperation operation = cmdLineArgs.Operation;
      string activationPath = operation.CurrentDirectoryPath;
      Frame rootFrame = Window.Current.Content as Frame;
      if (rootFrame == null)
      {
        rootFrame = new Frame();
        Window.Current.Content = rootFrame;
      }
      rootFrame.Navigate(typeof(MainPage), activationPath);
      Window.Current.Activate();
      break;
  }
}

でしたのコードを作成、着信 NavigationEventArgs からこのパスを取得する MainPage OnNavigatedTo オーバーライドのように図 7です。この例では、アプリがこのパスから StorageFolder の初期化され、ファイルとフォルダーをここでは下のツリー ビュー コントロールを構築します。

図 7 の現在の作業ディレクトリからファイル システムのツリーの構築

protected async override void OnNavigatedTo(NavigationEventArgs e)
{
  string activationPath = e.Parameter as string;
  argumentsText.Text = activationPath;
  fileTreeView.RootNodes.Clear();
  try
  {
    StorageFolder folder =
       await StorageFolder.GetFolderFromPathAsync(activationPath);
    if (folder != null)
    {
      TreeViewNode rootNode = new TreeViewNode() { Content = folder.Name };
      IReadOnlyList<StorageFolder> folders = await folder.GetFoldersAsync();
      GetDirectories(folders, rootNode);
      fileTreeView.RootNodes.Add(rootNode);
    }
  }
  catch (Exception ex)
  {
    Debug.WriteLine(ex.Message);
  }
}

新機能

複数のファイル システムへのアクセスを提供する 2 番目の方法では、新しい制限付き機能を介してです。これを使用するには、アプリケーション マニフェストの上部にある restrictedcapabilities XML 名前空間を宣言し、一覧で、< 機能 > broadFileSystemAccess を含めます。

xmlns:rescap="https://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
  IgnorableNamespaces="uap mp uap5 rescap">
...
  <Capabilities>
    <rescap:Capability Name="broadFileSystemAccess" />
  </Capabilities>

制限付き機能を宣言すると、このパブリケーションに対しては、ストアは、パッケージの送信時に追加の審査がトリガーされます。アプリでこの機能が付与される場合は、アプリを実行しているユーザーとファイル システムに同じアクセスがあります。現在の作業ディレクトリは、ユーザーがアクセスを持っているすべての場所からだけでなくこの機能がある場合は、AppExecutionAlias は不要です。これは、このような強力な機能であるために、Microsoft はアプリの開発者が、これが使用する方法の説明と、ユーザーがメリットを享受する方法の説明については、要求の理由を提供するかどうかのみ機能で与えられます。

(ドキュメント、画像またはビデオ); のより狭いスコープを指定したファイル システム機能のいずれかを宣言する必要はありません broadFileSystemAccess 機能を宣言する場合実際には、broadFileSystemAccess およびその他の 3 つのファイル システム機能のいずれかのアプリは宣言できません。

アプリが機能与えられた後もランタイム チェックでは、この占めているユーザーのプライバシーの問題です。その他のプライバシーの問題と同じように、アプリに初めて使用するユーザーの同意を求めるプロンプトがトリガーされます。ユーザーは、権限を拒否するが、アプリをこの回復力のある場合があります。ユーザーも変更できますさん、いつでも設定で、プライバシの一覧の下にある関連するファイル システム] ページに移動してで示すように図 8です。

設定で新しいファイル システム] ページ
図 8 ファイル システムで新しいページの設定

活用するために現在の作業ディレクトリのアクセスと broadFileSystemAccess アクセス許可の両方をコードに使用する WinRT Windows.Storage Api ファイルの処理に注意してください。

まとめ

アプリの以前のテクノロジとのギャップを閉じるには、UWP と長期的な戦略の 1 つ: 特に Win32 — UWP が時間の経過と共により多くの異なる種類のアプリの実行可能な選択肢になるようです。マルチ インスタンス化の場合は true、コンソール UWP アプリより広範なファイル システム アクセスのサポートの導入に伴い、さらに 3 つの大きな手順がこの旅を作成しました。サンプル コードで利用可能なbit.ly/2GtzM3Tで Visual Studio プロジェクト テンプレートがありますとbit.ly/2HApmiibit.ly/2FEIAXuです。


Andrew Whitechapelプログラム マネージャー、Microsoft Windows 除算では、ユニバーサル Windows プラットフォームのアプリのアクティブ化のワークフローを担当します。

この記事のレビューに協力してくれた技術スタッフの Jason holmes が行った、Tim Kurtzman、Anis モハメド Khaja Mohideen


この記事について MSDN マガジン フォーラムで議論する