通过


在桌面应用中调用Windows 运行时 API

本文介绍如何配置桌面应用项目以调用Windows 运行时(WinRT)API,这些 API 支持新式Windows功能,例如通知、文件选取器、共享等。

桌面应用中不支持某些 WinRT API。 有关详细信息,请参阅桌面应用中不支持的Windows 运行时 APIs

配置.NET项目

.NET 6 或更高版本:使用目标框架标识符选项

在项目文件中指定针对特定 Windows OS 版本的目标框架标识符(TFM)。 这会在生成时添加对相应 Windows SDK 目标包的引用。

  1. 在Visual Studio中,在 解决方案资源管理器 中右键单击project,然后选择 Edit Project File

  2. TargetFramework 值替换为特定于Windows的 TFM:

    目标 TFM
    Windows 11 版本 24H2 net8.0-windows10.0.26100.0
    Windows 11版本 22H2 net8.0-windows10.0.22621.0
    Windows 11(初始版本) net8.0-windows10.0.22000.0
    Windows 10 版本 2004 net8.0-windows10.0.19041.0
    Windows 10 版本1903 net8.0-windows10.0.18362.0
    Windows 10版本 1809 net8.0-windows10.0.17763.0

    例:

    <Project Sdk="Microsoft.NET.Sdk">
      <PropertyGroup>
        <OutputType>WinExe</OutputType>
        <TargetFramework>net8.0-windows10.0.19041.0</TargetFramework>
      </PropertyGroup>
    </Project>
    
  3. 保存并关闭项目文件。

支持最低Windows版本

若要允许应用在早于 TFM 目标的Windows版本上运行,请显式设置 TargetPlatformMinVersion

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <OutputType>WinExe</OutputType>
    <TargetFramework>net8.0-windows10.0.19041.0</TargetFramework>
    <TargetPlatformMinVersion>10.0.17763.0</TargetPlatformMinVersion>
  </PropertyGroup>
</Project>

当面向多个 OS 版本时,请使用 ApiInformation 检查来保护对某些版本上不可用的 API 的调用。 有关详细信息,请参阅版本自适应应用

.NET 6 及更高版本中不支持 WinRT API

在 .NET 6 及更高版本中,Windows.UI 命名空间中的多个 WinRT API 不受支持。 请使用 Microsoft.UI 命名空间中的等效 API(由 Windows 应用 SDK 提供)而非:

不支持 请改用
Windows.UI.Colors Microsoft.UI.Colors
Windows.UI.ColorHelper Microsoft.UI.ColorHelper
Windows.UI.Text (大多数类型) Microsoft.UI.Text
Windows.UI.Xaml (所有类型) Microsoft.UI.Xaml

.NET Core 3.x 或 .NET Framework:安装 NuGet 包

如果应用面向 .NET Core 3.x 或 .NET Framework,请安装 Microsoft.Windows.SDK.Contracts NuGet 包:

  1. 在Visual Studio中,右键单击项目并选择 Manage NuGet 包

  2. 搜索 Microsoft.Windows.SDK.Contracts

  3. 选择与最低Windows目标匹配的包版本:

    软件包版本 Windows目标
    10.0.19041.xxxx Windows 10 版本 2004
    10.0.18362.xxxx Windows 10,版本 1903
    10.0.17763.xxxx Windows 10版本 1809
    10.0.17134.xxxx Windows 10版本 1803
  4. 单击“安装”。

多目标同时支持 .NET 6 及早期 .NET 版本

将项目文件配置为使用适用于 .NET 6+ 的 TFM 方法和早期版本的 NuGet 包:

<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">
  <PropertyGroup>
    <OutputType>WinExe</OutputType>
    <TargetFrameworks>netcoreapp3.1;net8.0-windows10.0.19041.0</TargetFrameworks>
    <UseWPF>true</UseWPF>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Condition="'$(TargetFramework)' == 'netcoreapp3.1'"
                     Include="Microsoft.Windows.SDK.Contracts"
                     Version="10.0.19041.0" />
  </ItemGroup>
</Project>

配置 C++ (Win32) 项目

使用 C++/WinRT 在 C++ 桌面应用中调用 WinRT API。

有关详细信息,请参阅 Visual Studio C++/WinRT 的支持

示例:发送 Toast 通知

配置项目后,可以直接调用 WinRT API。 以下示例从 WPF 或 Win32 应用发送 toast 通知。

注意

Toast 通知需要应用标识。 打包的应用自动具有标识。 有关解压缩的应用,请参阅 从桌面 C# 应用发送本地 Toast 通知 ,了解所需的其他注册步骤。

using System.Security;
using Windows.Data.Xml.Dom;
using Windows.UI.Notifications;

void ShowToast(string title, string content, string image, string logo)
{
    string xmlString =
        $@"<toast><visual><binding template='ToastGeneric'>" +
        $"<text>{SecurityElement.Escape(title)}</text><text>{SecurityElement.Escape(content)}</text>" +
        $"<image src='{SecurityElement.Escape(image)}'/>" +
        $"<image src='{SecurityElement.Escape(logo)}' placement='appLogoOverride' hint-crop='circle'/>" +
        "</binding></visual></toast>";

    XmlDocument toastXml = new XmlDocument();
    toastXml.LoadXml(xmlString);
    ToastNotificationManager.CreateToastNotifier().Show(new ToastNotification(toastXml));
}
#include <sstream>
#include <string>
#include <string_view>
#include <winrt/Windows.Data.Xml.Dom.h>
#include <winrt/Windows.UI.Notifications.h>

using namespace winrt::Windows::UI::Notifications;
using namespace winrt::Windows::Data::Xml::Dom;

std::wstring XmlEscape(std::wstring_view input)
{
    std::wstring result;
    result.reserve(input.size());
    for (wchar_t ch : input) {
        switch (ch) {
            case L'&':  result += L"&amp;";  break;
            case L'<':  result += L"&lt;";   break;
            case L'>':  result += L"&gt;";   break;
            case L'\'': result += L"&apos;"; break;
            case L'"':  result += L"&quot;"; break;
            default:    result += ch;        break;
        }
    }
    return result;
}

void ShowToast(std::wstring title, std::wstring content, std::wstring image, std::wstring logo)
{
    std::wostringstream xml;
    xml << L"<toast><visual><binding template='ToastGeneric'>"
        << L"<text>" << XmlEscape(title) << L"</text><text>" << XmlEscape(content) << L"</text>"
        << L"<image src='" << XmlEscape(image) << L"'/>"
        << L"<image src='" << XmlEscape(logo) << L"' placement='appLogoOverride' hint-crop='circle'/>"
        << L"</binding></visual></toast>";

    XmlDocument toastXml;
    toastXml.LoadXml(xml.str().c_str());
    ToastNotificationManager::CreateToastNotifier().Show(ToastNotification(toastXml));
}

有关更多通知场景,请参阅 自适应和交互式通知(Toast 通知)

条件编译

当在 .NET 6 及更早版本中进行多目标编译时,请使用条件编译在单个项目中编写特定版本的代码:

#if NET6_0_OR_GREATER
    // Code that uses .NET 6+ APIs or TFM-available WinRT APIs
#else
    // Fallback code for .NET Core 3.x / .NET Framework
#endif