アプリ ブローカの作り方 2

前回に解説したホワイトペーパーに基づくプロジェクトの作成方法では、1つだけ面倒な箇所があります。それは、使用するライブラリーに対する参照を追加するたびに、プロジェクト ファイルを手作業で編集しないといけないという点になります。また、ビルド イベントに登録したコマンドにおける面倒なことは、ビルドした Windows メタデータが上書きされるために、implフォルダーにコピーしているという点になります。この二つの使い難さを解消しているのが、NorthwindRT サンプルとなります。NorthwindRT サンプルの Windows ランタイム コンポーネントの作成方法は、ホワイトペーパーに記載されている手順に対して、Windows ランタイム コンポーネントの作成方法が異なります。具体的には、以下のような方法になります。

  1. C#で新規プロジェクトを作成します。
    [Visual C#]-[Windows デスクトップ]-[クラス ライブラリ] テンプレートを選択します。

  2. 作成したプロジェクトをアンロードします。

  3. プロジェクト ファイルを編集します。
    <OutputType>Library</OutputType> を以下のように編集します。

     <OutputType>winmdobj</OutputType>
    

    この作業で、ビルドする結果として Windows ランタイム コンポーネントが出力されるようになります。 
    続いて、<FileAlignment>512</FileAlignment>の次に以下の内容を追加します。

       <TargetPlatformVersion>8.1</TargetPlatformVersion>
      <GenerateTargetFrameworkAttribute>false</GenerateTargetFrameworkAttribute>
    
  4. プロジェクト ファイルを上書き保存してから、プロジェクトを再読み込みします。

  5. ソリューション エクスプローラーの[参照]ノードを選択して、コンテキスト メニューより[参照の追加]を選択します。

  6. 参照マネージャーで参照設定を行います。
    [Windows 8.1]-[コア]-[Windows] への参照を追加します(この作業は必須です)。
    後は、必要なアセンブリに対する参照を追加したり、不要な参照を削除します。
    次に記載するアセンブリへの参照を追加した方が良いでしょう。
    %ProgramFiles(x86)%\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5\Facades\System.Runtime.dll
    %ProgramFiles(x86)%\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5\Facades\System.Threading.Tasks.dll
    %ProgramFiles(x86)%\Reference Assemblies\Microsoft\Framework\.NETCore\v4.5.1\System.Runtime.WindowsRuntime.dll

  7. プロジェクト プロパティの[ビルド イベント]-[ビルド後に実行するコマンド ライン]に以下のコマンドを登録します。

     call "$(DevEnvDir)..\..\vc\vcvarsall.bat" x86
    REM winmdidlでWindowsメタデータよりidlを作成します
    md "$(ProjectDir)bin\idl"
    winmdidl /metadata_dir:C:\Windows\System32\Winmetadata /outdir:"$(ProjectDir)bin\idl" "$(TargetPath)"
    REM midlでidlより各種のファイルと参照用のWindowsメタデータを作成します
    md "$(ProjectDir)bin\proxystub"
    midl /metadata_dir "%WindowsSdkDir%References\CommonConfiguration\Neutral" /env win32 /W1 /char signed /nologo /winrt /dlldata "$(ProjectDir)bin\proxystub\dlldata.c" /proxy "$(ProjectDir)bin\proxystub\proxy.c" /iid "$(ProjectDir)bin\proxystub\iid.c" /header "$(ProjectDir)bin\proxystub\proxystub.h" /winmd "$(ProjectDir)bin\idl\$(TargetFileName)" "$(ProjectDir)bin\idl\$(TargetName).idl"
    REM mdmergeでWindows ストア アプリで使用する参照用のWindowsメタデータを作成します
    md "$(ProjectDir)bin\mdmerge"
    mdmerge -i "$(ProjectDir)bin\idl" -o "$(ProjectDir)bin\mdmerge" -metadata_dir "%WindowsSdkDir%References\CommonConfiguration\Neutral" -partial
    

      
    上記のコマンドで、idl、proxystub、mdmerge サブフォルダーが作成されて、各サブ フォルダーに出力結果が登録されるようになります。つまり、ビルドされた Windows メタデータを上書きすることが無くなります。

  8. 後は、インターフェースの定義と実装コードを記述します。

これで、アプリ ブローカーで使用する Windows ランタイム コンポーネントの作成は終了です。後は、プロキシ スタブの作成ですが、これはホワイト ペーパーと同じ方法で作成できます。VC++のプロジェクトから、proxystub サブフォルダーに作成されているコードを追加すれば良いのです。
作成したアプリ ブローカーを使用する Windows ストア アプリでは、mdmerge サブフォルダーに作成されているメタデータに参照設定を行うことを除けば、ホワイト ペーパーと同じです。

この方法のメリットは、使用するライブラリーに対する参照設定を参照マネージャーという GUI で行うことができることです。手作業で、プロジェクト ファイルを編集するよりも保守性に優れた方法になります。Visual Studioの使用上で問題になる箇所は、プロジェクト プロパティにおける出力の種類に何も表示されないことだけだと思います。このような表示になる理由は、デスクトップ用のクラス ライブラリーのプロジェクト テンプレートを利用しているからであり、出力の種類にWindows ランタイム コンポーネントと表示させるにはホワイト ペーパーと同じように Windows ランタイム コンポーネント プロジェクト テンプレートを使用する必要があるからです。表示がおかしいとしても、動作に問題はありませんので、現実のプロジェクトではこの方法をお勧めします。

de:codeでは、NorthwindRT サンプルをベースにしながら、SQL Server 2014を使用するようにカスタマイズしたプログラムをデモで使用しました。NorthwindRT サンプル自体は、SQL Compactを使用していますが、現実的なプロジェクトでは SQL Server を使用すると私が考えているからです。

このNorthwindRT サンプルの考え方を発展させたものとして、Brokered WinRT Component Project Templatesが公開されています。このテンプレートをインストールすると、Brokered WindowsRuntime Component とBrokered WindowsRuntime ProxyStub というテンプレートが追加されます。作り方は、以下のようにします。

  1. C# で新規プロジェクトを作成します。
    [Visual C#]-[Brokered WindowsRuntime Component]テンプレートを選択します。
  2. 参照や実装を作成します。
  3. 同一のソリューションに対して、VC++のプロジェクトを追加します。
    [Brokered WindowsRuntime ProxyStub]テンプレートを選択します。
  4. VC++ プロジェクトのプロパティより参照の追加を行います。
    [プロパティページ]/[共通プロパティ]/[参照]/[新しい参照の追加] を使って、C# プロジェクトに対する参照を行います。
  5. ソリューションをビルドすれば、アプリ ブローカーとプロキシ スタブの完成です。

作成したアプリ ブローカーを使用する Windows ストア アプリを作成する場合は、VC++のプロジェクト フォルダー内の Debug\Reference サブ フォルダーにある参照用のメタデータを参照するだけです。

このテンプレートとホワイト ペーパー、NorthwindRT サンプルの大きな違いは、winmdidl、midl、mdmergeをC#プロジェクトのビルド後に実行するのかと、C++のビルド前に実行するかという点です(厳密には、C++のプロジェクト参照の解決時です)。プロジェクト ファイルに記述されている既定の言語が英語(en-US)になっている点を除けば、このテンプレートを使用するのが、アプリ ブローカーを作成する方法として一番簡単でしょう。理由は、VC++プロジェクトの各種の設定を行う必要がないからです。
既定の言語が問題になるケースは、言語毎のリソース ファイルなどを扱う場合だと思われますので、このような場合はプロジェクト ファイルを編集して既定の言語を修正するようにしてください。