次の方法で共有


C++/WinRT コンポーネントから C# プロジェクションを生成し、.NET アプリ用の NuGet として配布する

このトピックでは、 C#/WinRT を使用して C++/WinRT Windows ランタイム コンポーネントから C# .NET プロジェクション (または相互運用) アセンブリを生成し、それを .NET アプリケーション用の NuGet パッケージとして配布する方法について説明します。

.NET 6 以降では、Windows メタデータ (WinMD) ファイルの使用はサポートされなくなりました ( WinRT の組み込みサポートが .NET から削除されるを参照)。 代わりに、C#/WinRT ツールを使用して任意の WinMD ファイルのプロジェクション アセンブリを生成できます。これにより、.NET アプリケーションから WinRT コンポーネントを使用できるようになります。 プロジェクション アセンブリは相互運用機能アセンブリとも呼ばれます。 このチュートリアルでは、次の操作を行う方法について説明します。

  • C#/WinRT パッケージを使用して、C++/WinRT コンポーネントから C# プロジェクションを生成します。
  • コンポーネントをプロジェクション アセンブリと共に NuGet パッケージとして配布します。
  • .NET コンソール アプリケーションから NuGet パッケージを使用します。

[前提条件]

このチュートリアルと対応するサンプルには、次のツールとコンポーネントが必要です。

  • Visual Studio 2022(または Visual Studio 2019)にユニバーサル Windows プラットフォーム開発ワークロードがインストールされている。 インストールの詳細>Universal Windows プラットフォーム開発で、C++ (v14x) ユニバーサル Windows プラットフォーム ツール オプションをオンにします。
  • .NET 6.0 SDK 以降を使用します。

Visual Studio 2019 のみ。 C++/WinRT VSIX 拡張機能。Visual Studio で C++/WinRT プロジェクト テンプレートを提供します。 プロジェクト テンプレートは Visual Studio 2022 に組み込まれています。

このチュートリアルでは、Visual Studio 2022 と .NET 6 を使用します。

Von Bedeutung

また、GitHub の C#/WinRT プロジェクション サンプルから、このトピックのサンプル コードをダウンロードまたは複製する必要があります。 CsWinRT にアクセスし、緑色の [コード] ボタンをクリックしてgit clone URL を取得します。 サンプルの README.md ファイルを必ず読んでください。

単純な C++/WinRT Windows ランタイム コンポーネントを作成する

このチュートリアルに従うには、まず C# プロジェクション アセンブリの生成元となる C++/WinRT Windows ランタイム コンポーネント (WRC) が必要です。

このチュートリアルでは、既にダウンロードまたは複製した GitHub 上の C#/WinRT プロジェクション サンプルSimpleMathComponent WRC を使用します。 SimpleMathComponent、Windows ランタイム コンポーネント (C++/WinRT) Visual Studio プロジェクト テンプレート (Visual Studio 2022 または C++/WinRT VSIX 拡張機能に付属) から作成されました。

Visual Studio で SimpleMathComponent プロジェクトを開くには、 \CsWinRT\src\Samples\NetProjectionSample\CppWinRTComponentProjectionSample.sln ファイルを開きます。このファイルは、リポジトリのダウンロードまたは複製にあります。

このプロジェクトのコードは、以下のヘッダー ファイルに示されている基本的な算術演算の機能を提供します。

// SimpleMath.h
...
namespace winrt::SimpleMathComponent::implementation
{
    struct SimpleMath: SimpleMathT<SimpleMath>
    {
        SimpleMath() = default;
        double add(double firstNumber, double secondNumber);
        double subtract(double firstNumber, double secondNumber);
        double multiply(double firstNumber, double secondNumber);
        double divide(double firstNumber, double secondNumber);
    };
}

SimpleMathComponent C++/WinRT Windows ランタイム コンポーネント プロジェクトで、Windows Desktop Compatible プロパティが [はい] に設定されていることを確認できます。 これを行うには、 SimpleMathComponent のプロジェクト プロパティの [構成プロパティ>General>Project の既定値で、 Windows Desktop 互換 プロパティを [はい] に設定します。 これにより、.NET デスクトップ アプリを使用するために適切なランタイム バイナリが読み込まれます。

Desktop Compatible プロパティ ページ

C++/WinRT コンポーネントの作成と WinMD ファイルの生成の詳細な手順については、「 C++/WinRT を使用した Windows ランタイム コンポーネント」を参照してください。

コンポーネント IInspectable::GetRuntimeClassName をコンポーネントに実装する場合は、有効な WinRT クラス名 返 必要があります。 C#/WinRT は相互運用にクラス名文字列を使用するため、ランタイム クラス名が正しくないと InvalidCastException が発生します。

プロジェクション プロジェクトをコンポーネント ソリューションに追加する

まず、 CppWinRTComponentProjectionSample ソリューションを Visual Studio で開いたままにして、そのソリューションから SimpleMathProjection プロジェクトを削除します。 その後、ファイル システムから SimpleMathProjection フォルダーを削除します (または、必要に応じて名前を変更します)。 これらの手順は、このチュートリアルの手順に従うことができるように必要です。

  1. 新しい C# ライブラリ プロジェクトをソリューションに追加します。

    1. ソリューション エクスプローラーで、ソリューション ノードを右クリックし、[新しいプロジェクト追加]クリックします。
    2. [新しいプロジェクト の追加] ダイアログ ボックスで、検索ボックスに「クラス ライブラリ」と入力します。 言語の一覧から C# を選択し、プラットフォームの一覧から Windows を選択します。 クラス ライブラリ (プレフィックスもサフィックスも付かない) 呼び出される C# プロジェクト テンプレートを選択し、[次へ]クリックします。
    3. 新しいプロジェクトに SimpleMathProjection という名前を付けます。 この場所は、\CsWinRT\src\Samples\NetProjectionSample フォルダーと同じ フォルダーに既に設定されている必要がありますが、確認してください。 続けて、 [次へ] をクリックします。
    4. [ 追加情報 ] ページ で、[.NET 6.0 (長期サポート)]、[ 作成] の順に選択します。
  2. スタブ Class1.cs ファイルをプロジェクトから削除します。

  3. C#/WinRT NuGet パッケージをインストールするには、次の手順に従います。

    1. ソリューション エクスプローラーSimpleMathProjection プロジェクトを右クリックし、[NuGet パッケージの管理]を選択します。
    2. [ 参照 ] タブで、 Microsoft.Windows.CsWinRT を入力するか、検索ボックスに貼り付けます。検索結果で最新バージョンのアイテムを選択し、[ インストール ] をクリックしてパッケージを SimpleMathProjection プロジェクトにインストールします。
  4. SimpleMathProjection に、SimpleMathComponent プロジェクトへの参照を追加します。 ソリューション エクスプローラー で、SimpleMathProjection プロジェクト ノードの下にある [依存関係] ノードを右クリックし、[プロジェクト参照の追加] 選択し、[OK] [SimpleMathComponent プロジェクトを選択

まだプロジェクトをビルドしないでください。 これは後の手順で行います。

ここまでは、 ソリューション エクスプローラー は次のようになります (バージョン番号は異なります)。

プロジェクション プロジェクトの依存関係を示すソリューション エクスプローラー

ソースからプロジェクトをビルドする

C#/WinRT プロジェクション サンプルCppWinRTComponentProjectionSample ソリューション (GitHub からダウンロードまたは複製し、現在は開いている) の場合、ビルド出力の場所は、ソースからビルドするように Directory.Build.props ファイルで構成されます。 つまり、ビルド出力のファイルはソース フォルダーの外部で生成されます。 C#/WinRT ツールを使用するときは、ソースからビルドすることをお勧めします。 これにより、C# コンパイラがプロジェクト ルート ディレクトリの下にあるすべての *.cs ファイルを誤って取得するのを防ぐことができます。これにより、重複する型エラーが発生する可能性があります (たとえば、複数の構成やプラットフォーム用にコンパイルする場合)。

これは 既に CppWinRTComponentProjectionSample ソリューション用に構成されていますが、次の手順に従って、自分で構成を実行する方法を確認してください。

ソースからビルドするようにソリューションを構成するには:

  1. CppWinRTComponentProjectionSample ソリューションを開いたままで、ソリューション ノードを右クリックし、[>新しい項目] を追加して選択します。 XML ファイル 項目を選択し、directory.Build.props 名前を付けます (拡張子 付けはありません)。 [はい] をクリックして既存のファイルを上書きします。

  2. Directory.Build.props の内容を次の構成に置き換えます。

    <Project>
      <PropertyGroup>
        <BuildOutDir>$([MSBuild]::NormalizeDirectory('$(SolutionDir)', '_build', '$(Platform)', '$(Configuration)'))</BuildOutDir>
        <OutDir>$([MSBuild]::NormalizeDirectory('$(BuildOutDir)', '$(MSBuildProjectName)', 'bin'))</OutDir>
        <IntDir>$([MSBuild]::NormalizeDirectory('$(BuildOutDir)', '$(MSBuildProjectName)', 'obj'))</IntDir>
      </PropertyGroup>
    </Project>
    
  3. Directory.Build.props ファイルを保存して閉じます。

プロジェクト ファイルを編集して C#/WinRT を実行する

cswinrt.exe ツールを呼び出してプロジェクション アセンブリを生成するには、まずプロジェクト ファイルを編集して、いくつかのプロジェクト プロパティを指定する必要があります。

  1. ソリューション エクスプローラーで、SimpleMathProjection ノードをダブルクリックして、エディターでプロジェクト ファイルを開きます。

  2. 特定の Windows SDK バージョンをターゲットにするように TargetFramework 要素を更新します。 これにより、相互運用とプロジェクションのサポートに必要なアセンブリの依存関係が追加されます。 このサンプルは、Windows SDK バージョン net6.0-windows10.0.19041.0 (Windows 10 バージョン 2004 とも呼ばれます) を対象としています。 結果のプロジェクション アセンブリを任意のアプリ アーキテクチャから参照できるように、 Platform 要素を AnyCPU に設定します。 アプリケーションを参照して以前のバージョンの Windows SDK をサポートできるようにするには、 TargetPlatformMinimumVersion プロパティを設定することもできます。

    <PropertyGroup>
      <TargetFramework>net8.0-windows10.0.19041.0</TargetFramework>
      <!-- Set Platform to AnyCPU to allow consumption of the projection assembly from any architecture. -->
      <Platform>AnyCPU</Platform>
    </PropertyGroup>
    

    このチュートリアルと関連するサンプルコードでは、ソリューションは x64 および Release用に構築されています。 SimpleMathProjection プロジェクトは、すべてのソリューション アーキテクチャ構成で AnyCPU 用にビルドするように構成されていることに注意してください。

  3. 複数の C#/WinRT プロパティを設定する 2 つ目の PropertyGroup 要素 (最初の要素の直後) を追加します。

    <PropertyGroup>
      <CsWinRTIncludes>SimpleMathComponent</CsWinRTIncludes>
      <CsWinRTGeneratedFilesDir>$(OutDir)</CsWinRTGeneratedFilesDir>
    </PropertyGroup>
    

    この例の設定の詳細を次に示します。

    • CsWinRTIncludes プロパティは、プロジェクトする名前空間を指定します。
    • CsWinRTGeneratedFilesDir プロパティは、プロジェクション ソース ファイルが生成される出力ディレクトリを設定します。 このプロパティは、上記のセクションの OutDir で定義されているに設定されます。
  4. SimpleMathProjection.csproj ファイルを保存して閉じ、必要に応じてクリックしてプロジェクトを 再読み込み します。

プロジェクションを使用して NuGet パッケージを作成する

.NET アプリケーション開発者向けにプロジェクション アセンブリを配布するには、いくつかのプロジェクト プロパティを追加することで、ソリューションをビルドするときに NuGet パッケージを自動的に作成できます。 .NET ターゲットの場合、NuGet パッケージには、コンポーネントのプロジェクション アセンブリと実装アセンブリを含める必要があります。

  1. 次の手順を使用して、NuGet 仕様 (.nuspec) ファイルを SimpleMathProjection プロジェクトに追加します。

    1. ソリューション エクスプローラーで、SimpleMathProjection ノードを右クリック 、[新しいフォルダー追加] を選択し、nugetフォルダー 名前を付けます。
    2. nuget フォルダーを右クリックし、[追加>新しいアイテム] を選択し、[XML ファイル] を選択し、SimpleMathProjection.nuspec という名前を付けます。
  2. ソリューション エクスプローラーで、SimpleMathProjection ノードをダブルクリックして、エディターでプロジェクト ファイルを開きます。 現在開いている SimpleMathProjection.csproj (2 つの既存の PropertyGroup 要素の直後) に次のプロパティ グループを追加して、パッケージを自動的に生成します。 これらのプロパティは、NuGet パッケージを生成する NuspecFile とディレクトリを指定します。

    <PropertyGroup>
      <GeneratedNugetDir>.\nuget\</GeneratedNugetDir>
      <NuspecFile>$(GeneratedNugetDir)SimpleMathProjection.nuspec</NuspecFile>
      <OutputPath>$(GeneratedNugetDir)</OutputPath>
      <GeneratePackageOnBuild>true</GeneratePackageOnBuild>
    </PropertyGroup>
    

    パッケージを個別に生成する場合は、コマンド ラインから nuget.exe ツールを実行することもできます。 NuGet パッケージの作成の詳細については、「 nuget.exe CLI を使用したパッケージの作成」を参照してください。

  3. SimpleMathProjection.nuspec ファイルを開いてパッケージ作成プロパティを編集し、次のコードを貼り付けます。 次のスニペットは、 SimpleMathComponent を複数のターゲット フレームワークに配布するための NuGet 仕様の例です。 ターゲット lib\net6.0-windows10.0.19041.0\SimpleMathProjection.dll の代わりに、プロジェクション アセンブリSimpleMathProjection.dllが指定されていることに注意してください。 この動作は .NET 6 以降では新しく、C#/WinRT によって有効になっています。 実装アセンブリ SimpleMathComponent.dllも配布する必要があり、実行時に読み込まれます。

    <?xml version="1.0" encoding="utf-8"?>
    <package xmlns="http://schemas.microsoft.com/packaging/2012/06/nuspec.xsd">
      <metadata>
        <id>SimpleMathComponent</id>
        <version>0.1.0-prerelease</version>
        <authors>Contoso Math Inc.</authors>
        <description>A simple component with basic math operations</description>
        <dependencies>
          <group targetFramework="net6.0-windows10.0.19041.0" />
          <group targetFramework=".NETCoreApp3.0" />
          <group targetFramework="UAP10.0" />
          <group targetFramework=".NETFramework4.6" />
        </dependencies>
      </metadata>
      <files>
        <!--Support .NET 6, .NET Core 3, UAP, .NET Framework 4.6, C++ -->
        <!--Architecture-neutral assemblies-->
        <file src="..\..\_build\AnyCPU\Release\SimpleMathProjection\bin\SimpleMathProjection.dll" target="lib\net6.0-windows10.0.19041.0\SimpleMathProjection.dll" />
        <file src="..\..\_build\x64\Release\SimpleMathComponent\bin\SimpleMathComponent\SimpleMathComponent.winmd" target="lib\netcoreapp3.0\SimpleMathComponent.winmd" />
        <file src="..\..\_build\x64\Release\SimpleMathComponent\bin\SimpleMathComponent\SimpleMathComponent.winmd" target="lib\uap10.0\SimpleMathComponent.winmd" />
        <file src="..\..\_build\x64\Release\SimpleMathComponent\bin\SimpleMathComponent\SimpleMathComponent.winmd" target="lib\net46\SimpleMathComponent.winmd" />
        <!--Architecture-specific implementation DLLs should be copied into RID-relative folders-->
        <file src="..\..\_build\x64\Release\SimpleMathComponent\bin\SimpleMathComponent\SimpleMathComponent.dll" target="runtimes\win10-x64\native\SimpleMathComponent.dll" />
        <!--To support x86 and Arm64, build SimpleMathComponent for those other architectures and uncomment the entries below.-->
        <!--<file src="..\..\_build\Win32\Release\SimpleMathComponent\bin\SimpleMathComponent\SimpleMathComponent.dll" target="runtimes\win10-x86\native\SimpleMathComponent.dll" />-->
        <!--<file src="..\..\_build\arm64\Release\SimpleMathComponent\bin\SimpleMathComponent\SimpleMathComponent.dll" target="runtimes\win10-arm64\native\SimpleMathComponent.dll" />-->
      </files>
    </package>
    

    コンポーネントの実装アセンブリであるSimpleMathComponent.dllは、アーキテクチャ固有です。 他のプラットフォーム (x86 や Arm64 など) をサポートしている場合は、まず目的のプラットフォーム用 に SimpleMathComponent をビルドし、これらのアセンブリ ファイルを適切な RID 相対フォルダーに追加する必要があります。 プロジェクション アセンブリ SimpleMathProjection.dllコンポーネント SimpleMathComponent.winmd はどちらもアーキテクチャに依存しません。

  4. 編集したファイルを保存して閉じます。

ソリューションをビルドしてプロジェクションと NuGet パッケージを生成する

ソリューションをビルドする前に、Visual Studio の [ビルド] の [構成マネージャー] の設定>確認してください。 このチュートリアルでは、ソリューションの 構成Release に、Platformx64 に設定します。

この時点で、ソリューションをビルドできるようになりました。 ソリューション ノードを右クリックし、[ソリューションのビルド]を選択します。 これにより、最初に SimpleMathComponent プロジェクトがビルドされ、次に SimpleMathProjection プロジェクトがビルドされます。 コンポーネント WinMD と実装アセンブリ (SimpleMathComponent.winmdSimpleMathComponent.dll)、プロジェクション ソース ファイル、およびプロジェクション アセンブリ (SimpleMathProjection.dll) はすべて 、_build 出力ディレクトリの下に生成されます。 また、生成された NuGet パッケージ SimpleMathComponent0.1.0-prerelease.nupkg、\SimpleMathProjection\nuget フォルダーの下に表示することもできます。

Von Bedeutung

上記のファイルのいずれかが生成されない場合は、2 回目にソリューションをビルドします。 リビルドする前に、ソリューションを閉じて再度開く必要がある場合もあります。

Visual Studio で .nupkg が表示されるようにするために、ソリューションを閉じて再度開く必要があることがあります(または、[すべてのファイルを表示] を選択してから選択解除するだけです)。

プロジェクションの生成を示すソリューション エクスプローラー

C# .NET 6 コンソール アプリケーションで NuGet パッケージを参照する

.NET プロジェクトから SimpleMathComponent を使用するには、前のセクションで作成した SimpleMathComponent0.1.0-prerelease.nupkg NuGet パッケージへの参照を新しい .NET プロジェクトに追加するだけです。 次の手順では、別のソリューションで単純なコンソール アプリを作成してこれを行う方法を示します。

  1. 次の手順を使用して、C# コンソール アプリ プロジェクトを含む新しいソリューションを作成します (新しいソリューションでこのプロジェクトを作成すると、 SimpleMathComponent NuGet パッケージを個別に復元できます)。

    Von Bedeutung

    この新しい コンソール アプリ プロジェクトを \CsWinRT\src\Samples\NetProjectionSample フォルダー内に作成します。このプロジェクトは、 C#/WinRT プロジェクション サンプルのダウンロードまたは複製にあります。

    1. Visual Studio の新しいインスタンスで、 File>New>Project を選択します。
    2. [ 新しいプロジェクトの作成 ] ダイアログ ボックスで、 コンソール アプリ プロジェクト テンプレートを検索します。 コンソール アプリ 呼び出す C# プロジェクト テンプレート (プレフィックスもサフィックスも付かない) を選択し、[次へ] クリック。 Visual Studio 2019 を使用している場合、プロジェクト テンプレートは コンソール アプリケーションです。
    3. SampleConsoleAppに新しいプロジェクトの名前を付け、その場所を SimpleMathComponent フォルダーと SimpleMathProjection フォルダーと同じ フォルダーに設定し、[次へ]をクリックします
    4. [ 追加情報 ] ページ で、[.NET 6.0 (長期サポート)]、[ 作成] の順に選択します。
  2. ソリューション エクスプローラーSampleConsoleApp ノードをダブルクリックして SampleConsoleApp.csproj プロジェクト ファイルを開き、次の一覧に示すようにTargetFrameworkプロパティとPlatformプロパティを編集します。 Platform要素がない場合は追加します。

    <PropertyGroup>
      <OutputType>Exe</OutputType>
      <TargetFramework>net6.0-windows10.0.19041.0</TargetFramework>
      <Platform>x64</Platform>
    </PropertyGroup>
    
  3. SampleConsoleApp.csproj プロジェクト ファイルがまだ開いているので、次に SampleConsoleApp プロジェクトに SimpleMathComponent NuGet パッケージへの参照を追加します。 プロジェクトのビルド時に SimpleMathComponent NuGet を復元するには、コンポーネント ソリューション内の RestoreSources フォルダーへのパスと共に プロパティを使用できます。 次の構成をコピーし、 SampleConsoleApp.csproj ( Project 要素内) に貼り付けます。

    <PropertyGroup>
      <RestoreSources>
        https://api.nuget.org/v3/index.json;
        ../SimpleMathProjection/nuget
      </RestoreSources>
    </PropertyGroup>
    
    <ItemGroup>
      <PackageReference Include="SimpleMathComponent" Version="0.1.0-prerelease" />
    </ItemGroup>
    

    Von Bedeutung

    上記の RestoreSources パッケージの パスは、../SimpleMathProjection/nugetに設定されています。 SimpleMathComponent プロジェクトと SampleConsoleApp プロジェクトの両方が同じフォルダー (この場合は NetProjectionSample フォルダー) に含まれるように、このチュートリアルの手順に従った場合、このパスは正しいです。 別の作業を行った場合は、それに応じてそのパスを調整する必要があります。 または、 ローカル NuGet パッケージ フィードを ソリューションに追加することもできます。

  4. Program.cs ファイルを編集して、SimpleMathComponent によって提供される機能を使用します。

    var x = new SimpleMathComponent.SimpleMath();
    Console.WriteLine("Adding 5.5 + 6.5 ...");
    Console.WriteLine(x.add(5.5, 6.5).ToString());
    
  5. 編集したファイルを保存して閉じ、コンソール アプリをビルドして実行します。 次の出力が表示されます。

    コンソール NET5 出力

既知の問題

  • プロジェクション プロジェクトをビルドするときに、次のようなエラーが表示されることがあります。 エラー MSB3271ビルド中のプロジェクトのプロセッサ アーキテクチャ "MSIL" と、実装ファイルのプロセッサ アーキテクチャ "x86" が一致していません。\SimpleMathComponent.dll" for "..\SimpleMathComponent.winmd"。この不一致により、ランタイム エラーが発生する可能性があります。プロジェクトと実装ファイルの間でプロセッサ アーキテクチャを調整するように、Configuration Manager を使用してプロジェクトのターゲット プロセッサ アーキテクチャを変更することを検討するか、プロジェクトの対象プロセッサ アーキテクチャに一致するプロセッサ アーキテクチャを持つ実装ファイルで winmd ファイルを選択してください。 このエラーを回避するには、C# ライブラリ プロジェクト ファイルに次のプロパティを追加します。
    <PropertyGroup>
        <!-- Workaround for MSB3271 error on processor architecture mismatch -->
        <ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>None</ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>
    </PropertyGroup>
    

その他の考慮事項

このトピックで作成する方法を示した C# プロジェクション (または相互運用) アセンブリは非常に単純です。他のコンポーネントへの依存関係はありません。 ただし、Windows App SDK 型への参照を持つ C++/WinRT コンポーネントの C# プロジェクションを生成するには、プロジェクション プロジェクトで Windows App SDK NuGet パッケージへの参照を追加する必要があります。 このような参照がない場合は、"Type <T> could not found" などのエラーが表示されます。

このトピックで行うもう 1 つの操作は、プロジェクションを NuGet パッケージとして配布することです。 その は現在 必要です。

リソース