WinRT コンポーネント
WinRT (Windows Runtime)は、Windows 8以降で実装された、新しいWindows APIです。 WinRTコンポーネント(WinRT APIが提供するクラスなど)は、COMの進化版(COMの上位互換)に、 .NET Frameworkの型情報を加えたような形式になっています。
WinRT コンポーネントは、Windows 8世代、つまり、.NET Frameworkよりもだいぶ後に作られただけあって、 C# からの参照はかなり簡単になっています。 C# で書かれたライブラリとほとんど区別なく WinRT コンポーネントを参照できます。 よっぽど意識しない限り、ネイティブ ライブラリを参照しているとは感じないでしょう。
Visual Studio 上では、下図のように、「参照の追加」→「Windows」→参照したいコンポーネントを選んで「OK」という手順を踏みます。
Windows アプリ
WinRT は前述のとおり、Windows 8世代の新APIです。 Windows 8から Windows 10にかけて紆余曲折ありましたが、要は、以下のタイプのアプリから使う前提のものです。
-
Windows ストア アプリ
- 「Modern アプリ」とか「メトロ スタイル」とか呼ばれていた時期もあります
- これを単に「Windows アプリ」と呼んで、これまでの Win32 API ベースのアプリは「従来のデスクトップ アプリ」と呼びたがっている(呼ばれるようになってほしい)節もあります
- Universal Windows Platform (UWP)アプリ
これらに関連したプロジェクトを作ると、標準の状態で WinRT コンポーネントの参照ができます。
従来のデスクトップ アプリ
標準の状態では無理ですが、少し手を入れることで、従来のデスクトップ アプリからもWinRTコンポーネントを参照できます。
csproj を手書きで書き換える必要があります。以下のように、TargetPlatformVersion
というタグを1行追加します。
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{F404E6CA-F7FD-4AB8-A531-D8203BCC3F70}</ProjectGuid>
<OutputType>Exe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>NativeInterop</RootNamespace>
<AssemblyName>NativeInterop</AssemblyName>
<TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
<TargetPlatformVersion>10.0.10240.0</TargetPlatformVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
</PropertyGroup>
...
TargetPlatformVersion
タグの中身には、8.0
, 8.1
, 10.0
など、Windows のバージョンを書きます。
これで、例えば、以下のようなコンソール アプリで、WinRT コンポーネントを使えます。
using System;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using Windows.Foundation;
using Windows.System;
namespace NativeInterop
{
class WinRtSample
{
public static void Main()
{
MainAsync().Wait();
}
static async Task MainAsync()
{
var allUsers = await User.FindAllAsync();
foreach (var user in allUsers)
{
Console.WriteLine(user.NonRoamableId);
}
}
}
static class WinRtExtensions
{
public static TaskAwaiter<T> GetAwaiter<T>(this IAsyncOperation<T> t) => t.AsTask().GetAwaiter();
public static Task<T> AsTask<T>(this IAsyncOperation<T> t)
{
var tcs = new TaskCompletionSource<T>();
t.Completed += (info, state) =>
{
try
{
tcs.TrySetResult(info.GetResults());
}
catch(Exception ex)
{
tcs.TrySetException(ex);
}
};
return tcs.Task;
}
}
}