在 WPF .NET 6 中使用 C++/WinRT 组件(但实际上是任何 WinRT 组件)

问题描述 投票:0回答:1

我想编写一个 WPF 应用程序,但尽可能在现代框架上构建它,包括 .NET 6 甚至更高版本。

我有一些想要调用的 C++ 代码,并且我喜欢将 WinRT 作为组件模型,而不是低级别的 P/Invoke。

我已经成功使用 CsWinRT 将我的 C++ 代码集成到 WinUI3 应用程序中。现在我尝试对我的 WPF 应用程序执行相同的操作。我的尝试可以在https://github.com/mmarczell-graphisoft/winrtbug

看到

只要我的 WPF C# 代码中没有 using 指令,也没有任何使用这些定义的代码,C# 投影文件就会在 obj\Debug 下生成 et6.0-windows\生成的文件\CsWinRT。然而,一旦我输入 using 指令并重建,这个文件就不再存在了。

我做错了什么?


我找到了一些关于类似用例的文档,但它们已有一些年头了,似乎并不直接适用。

最初不支持在非打包应用程序中使用 WinRT 组件。 https://github.com/microsoft/cppwinrt/issues/256

然后在2019年宣布了“免注册WinRT”: https://blogs.windows.com/windowsdeveloper/2019/04/30/enhancing-non-packaged-desktop-apps-using-windows-runtime-components/

带有示例代码: https://github.com/microsoft/RegFree_WinRT

但是,在 .NET 5 中,直接引用 .winmd 的功能已从 .NET 中删除并提取到 CsWinRT 包中: https://github.com/microsoft/CsWinRT

这就是我未能正确配置的原因。该文档指出,直接项目引用是不可能的,而应使用两阶段构建过程,第一阶段将库打包为 NuGet 包,顶级应用程序引用它。 https://learn.microsoft.com/en-us/windows/apps/develop/platform/csharp-winrt/net-projection-from-cppwinrt-component

然而,GitHub 讨论中的 MS 员工一再暗示这实际上是不必要的,因为 CsWinRT 通过直接引用项目来支持更简单的工作流程,例如 https://github.com/microsoft/CsWinRT/discussions/1072#discussioncomment-8497693https://github.com/microsoft/CsWinRT/issues/1289#issuecomment-1481878399

我也将此问题作为 GitHub 问题提交: https://github.com/microsoft/CsWinRT/issues/1543

c# wpf windows-runtime c++-winrt
1个回答
0
投票

这里指出的许多文章都是旧的(也称为几年,但对于 .NET Core 来说几年已经很老了),并且使用最近的框架,有些事情比以前更容易,但很难找到解决方案。

因此,从本(官方)教程开始从 C++/WinRT 组件生成 C# 投影,作为 .NET 应用程序的 NuGet 进行分发,可在此处作为示例代码C#/WinRT 投影示例。首先要做的是更新所有软件包,尤其是 CsWinRT,它已经完全过时了(截至今天的当前版本是

2.0.7
)。

然后,由于这个较新的 CsWinRT,您甚至不需要像示例中所解释的那样使用中间 Nuget 项目,因为这个新的 CsWinRT 会从组件的 .winmd 文件中动态为我们生成一些 .cs 文件(元数据)。

只需构建 SimpleMathComponent C++/WinRT 项目,现在您可以使用 .NET 8 和 x64(调试或发布)在带有 .csproj 的控制台应用程序中引用它

<PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net8.0-windows10.0.19041.0</TargetFramework>
    <Nullable>enable</Nullable>
    <PlatformTarget>x64</PlatformTarget>
    <Platforms>x64</Platforms>
</PropertyGroup>

<ItemGroup>
    <PackageReference Include="Microsoft.Windows.CsWinRT" Version="2.0.7" />
</ItemGroup>

<ItemGroup>
    <ProjectReference Include="..\SimpleMathComponent\SimpleMathComponent.vcxproj" />
</ItemGroup>

<PropertyGroup>
    <CsWinRTIncludes>
        SimpleMathComponent;
    </CsWinRTIncludes>
</PropertyGroup>

我们可以在

obj
目录下看到.cs投影自动生成的文件:

现在,对于 WPF 项目,相同的项目布局不起作用。由于某种原因,CsWinRT 没有选择

SimpleMathComponent
组件来生成代码(我能看到的唯一真正区别是
OutputType
Exe
WinExe
)并且未生成 SimpleMathComponent.cs,这会导致编译错误。对我来说看起来像是一个错误。

一个可能的解决方法是直接向 CsWinRT 提供它需要的输入,如下所示;

<Project Sdk="Microsoft.NET.Sdk">

    <PropertyGroup>
        <OutputType>WinExe</OutputType>
        <TargetFramework>net8.0-windows10.0.19041.0</TargetFramework>
        <Nullable>enable</Nullable>
        <PlatformTarget>x64</PlatformTarget>
        <Platforms>x64</Platforms>
        <UseWPF>true</UseWPF>
    </PropertyGroup>

    <ItemGroup>
        <PackageReference Include="Microsoft.Windows.CsWinRT" Version="2.0.7" />
    </ItemGroup>

    <ItemGroup>
        <ProjectReference Include="..\SimpleMathComponent\SimpleMathComponent.vcxproj" />
    </ItemGroup>

    <PropertyGroup>
        <CsWinRTParams>
            -target net6.0
            -input 10.0.19041.0
            -input "$(BuildOutDir)SimpleMathComponent\bin\SimpleMathComponent\SimpleMathComponent.winmd"
            -output "$(IntermediateOutputPath)\net8.0-windows10.0.19041.0\Generated Files\CsWinRT"
            -exclude Windows
            -exclude Microsoft
            -include SimpleMathComponent
        </CsWinRTParams>
    </PropertyGroup>
</Project>

显然它不如控制台应用程序版本实用(并且在改变.NET版本、SDK版本等时需要进行调整)。

© www.soinside.com 2019 - 2024. All rights reserved.