使用通知功能创建 C++ 原生插件

本指南介绍如何创建一个 C++ 本机加载项,用于在 Electron 应用中调用Windows 应用 SDK通知 API。 在深入了解更复杂的方案之前,这是了解原生插件的一个很好的起点。

先决条件

在开始本指南之前,请确保已:

步骤 1:创建 C++ 本机加载项

让我们使用 C++ 和 node-addon-api 创建本机加载项。 这提供对具有最佳性能的Windows API 的直接访问。

npx winapp node create-addon

注释

如果您尚未安装Python或所需的Visual Studio工具,此命令可能会提示您进行安装。

这将创建一个 nativeWindowsAddon/ 文件夹,其中包含:

  • nativeWindowsAddon.cc - 将调用 Windows API 的 C++ 代码
  • binding.gyp - 为 node-gyp 生成配置

该命令还会安装所需的开发依赖项(nannode-addon-apinode-gyp),并将build-nativeWindowsAddon脚本添加到package.json中。

{
  "scripts": {
    "build-nativeWindowsAddon": "node-gyp clean configure build --directory=nativeWindowsAddon"
  }
}

生成的模板包含使用 Windows SDK 通知 API 的示例 ShowNotification 函数。 让我们通过构建加载项来验证所有设置是否正确。

# Build the C++ addon
npm run build-nativeWindowsAddon

注释

还可以使用 npx winapp node create-addon --template cs. 创建 C# 加载项。 C# 加载项使用 node-api-dotnet。 有关更多选项,请参阅其他指南,了解如何创建加载项或 完整的命令文档

步骤 2:测试生成的加载项

让我们通过从主进程调用它来验证生成的加载项是否正常工作。 打开 src/index.js

  1. 使用顶部的其他 require 语句添加加载项导入:
const nativeWindowsAddon = require('../nativeWindowsAddon/build/Release/nativeWindowsAddon.node');
  1. createWindow() 函数末尾调用通知函数:
const createWindow = () => {
  // ... existing window creation code ...

  // Test the Windows SDK notification
  nativeWindowsAddon.showNotification(
    'Hello from Electron!',
    'This notification uses the Windows SDK.'
  );
};

在通知 API 正常工作之前,需要确保应用使用标识运行。 运行:

npx winapp node add-electron-debug-identity

注释

此命令已经是我们在安装指南中添加的 postinstall 脚本的一部分,因此它在 npm install 之后自动运行。 但是,每当修改 Package.appxmanifest、更新应用资产或重新安装依赖项时,都需要手动运行它。

现在运行应用:

npm start

应会看到通知出现! 🎉 生成的加载项开箱即用。

⚠️ 已知问题:应用崩溃或空白窗口(单击以展开)

已知存在与稀疏打包相关的Windows bug,会导致Electron应用程序启动时崩溃或无法呈现Web内容。 此问题已在Windows中修复,但尚未传播到所有设备。

有关解决方法,请参阅 开发环境设置

步骤 3:升级到 Windows 应用 SDK 通知功能

确认加载项正常工作后,让我们将其升级为使用新式 Windows 应用 SDK 通知 API(Microsoft.Windows.AppNotifications),从而提供更好的开发人员体验和更多功能。 从设置步骤运行 init 命令时,我们已经设置了Windows 应用 SDK。

打开 nativeWindowsAddon/nativeWindowsAddon.cc 并用以下代码替换整个内容:

#include <napi.h>
#include <windows.h>

#include <winrt/Windows.Foundation.h>
#include <winrt/Microsoft.Windows.AppNotifications.h>
#include <winrt/Microsoft.Windows.AppNotifications.Builder.h>

using namespace winrt;
using namespace Microsoft::Windows::AppNotifications;
using namespace Microsoft::Windows::AppNotifications::Builder;

// Function to display a Windows App SDK notification
void ShowNotification(const Napi::CallbackInfo& info) {
    Napi::Env env = info.Env();

    try {
        // Get arguments from JavaScript (title and message)
        if (info.Length() < 2 || !info[0].IsString() || !info[1].IsString()) {
            Napi::TypeError::New(env, "Expected two string arguments: title and message").ThrowAsJavaScriptException();
            return;
        }

        std::string title = info[0].As<Napi::String>();
        std::string message = info[1].As<Napi::String>();

        // Convert to wide strings
        std::wstring wTitle(title.begin(), title.end());
        std::wstring wMessage(message.begin(), message.end());

        // Use AppNotificationBuilder for a cleaner API
        AppNotificationBuilder builder;
        builder.AddText(wTitle);
        builder.AddText(wMessage);
        
        AppNotification notification = builder.BuildNotification();
        AppNotificationManager::Default().Show(notification);

    } catch (const winrt::hresult_error& ex) {
        Napi::Error::New(env, winrt::to_string(ex.message())).ThrowAsJavaScriptException();
    } catch (const std::exception& ex) {
        // Handle exceptions and throw back to JavaScript
        Napi::Error::New(env, ex.what()).ThrowAsJavaScriptException();
    } catch (...) {
        Napi::Error::New(env, "Unknown error occurred").ThrowAsJavaScriptException();
    }
}

// Initialize the module
Napi::Object Init(Napi::Env env, Napi::Object exports) {
    exports.Set(Napi::String::New(env, "showNotification"), Napi::Function::New(env, ShowNotification));
    return exports;
}

NODE_API_MODULE(addon, Init)

此处的关键更改是从较旧的 Windows.UI.Notifications 命名空间切换到新式 Microsoft.Windows.AppNotifications API,并使用 AppNotificationBuilder 来构造通知,而不是手动生成 XML 字符串。 这提供了更简洁、更可维护的 API,与Windows 应用 SDK模式一致。

步骤 4:重新生成和测试

现在,使用更新的代码重新生成加载项:

npm run build-nativeWindowsAddon

更新 src/index.js 中的消息来反映更改:

nativeWindowsAddon.showNotification(
  'Hello from Electron!',
  'This notification is powered by the Windows App SDK!'
);

再次运行应用:

npm start

你将看到使用新式Windows 应用 SDK API 更新的通知!

后续步骤

祝贺! 已成功创建调用 Windows 应用 SDK API 的本机 C++ 加载项! 🎉

现在,你已准备好:

或者浏览其他指南:

其他资源