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

我有一些我想调用的C++代码,而且我喜欢WinRT作为组件模型,而不是低级P/Expresske.

我已经成功地使用csWinRT将我的C++代码集成到WinUI 3应用程序中.现在我try 用我的WPF应用程序做同样的事情.我的try 可以在https://github.com/mmarczell-graphisoft/winrtbug处看到

只要我的WPF C#代码中没有using指令,也没有任何使用这些定义的代码,C#投影文件就会在obj\guarding/net6.0-Windows\Generated Files\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

推荐答案

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

因此,从这个(官方)教程Generate a C# projection from a C++/WinRT component, distribute as a NuGet for .NET apps开始,这里有示例代码C#/WinRT Projection Sample.首先要做的是更新所有包,尤其是完全过时的csWinRT(截至今天的当前版本为2.0.7).

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

只需构建SimpleMathComponents 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投影自动生成的文件:

enter image description here

现在,对于WPF项目,相同的项目布局不起作用.出于某种原因,SimpleMathComponent组件没有被csWinRT选中进行代码生成(我能看到的唯一真正区别是OutputTypeExeWinExe),并且没有生成SimpleMathDeliverent.cs,从而导致编译错误.对我来说看起来像个虫子.

一个可能的解决方案是直接向csWinRT提供input it needs,类似于这样的内容;

<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版本等时需要进行调整).

Csharp相关问答推荐

如何禁用ASP.NET MVP按钮,以便无法使用开发人员控制台重新启用它

在依赖性注入和继承之间进行 Select

我无法在Ubuntu下编译使用microsoft.extension.configurationbuilder jsonapi和mono mcs的c#应用程序

使用命令初始化可绑定属性

Mongo作为.NET中Testcontainers的副本集

更改执行目录

每个http请求需要60秒,为什么?

BlockingCollection T引发意外InvalidOperationException

C#Null判断处理失败

确定System.Text.Json序列化中是否无法识别Type

有没有类似于扩展元素的合并元组的语法?

JsonSchema.Net删除假阳性判断结果

将内置的OrderedEumable&Quot;类设置为内部类有什么好处?

WinUI 3中DoubleCollection崩溃应用程序类型的依赖属性

当我将`ConcurentDictionary`转换为`IDictionary`时,出现了奇怪的并发行为

用于获取字符串的最后12个字符的正则表达式(空格除外)

Linq SELECT的多条指令

如何读取TagHelper属性的文本值?

在ObservableCollection上使用[NotifyPropertyChangedFor()]源代码生成器不会更新UI

使用Try-Catch-Finally为API端点处理代码--有什么缺点?