建立帶有通知功能的 C++ 原生外掛

本指南會教你如何建立一個 C++ 原生外掛,在你的 Electron 應用程式中呼叫 Windows 應用程式 SDK 通知 API。 這是理解原生插件的好起點,之後再深入更複雜的情境。

先決條件

在開始本指南前,請確保你已經:

步驟 1:建立 C++ 原生外掛

讓我們用 C++ 和 node-addon-api 建立一個原生外掛。 這提供了直接存取 Windows API 的方式,以達到最佳效能。

npx winapp node create-addon

Note

如果你還沒安裝 Python 或必要的 Visual Studio 工具,這個指令可能會提示你安裝。

這會建立一個 nativeWindowsAddon/ 資料夾,內容包括:

  • nativeWindowsAddon.cc - 你的 C++ 程式碼,能呼叫 Windows API。
  • binding.gyp - node-gyp 編譯配置

這個指令也會安裝必要的開發相依性(nannode-addon-apinode-gyp),並將一個build-nativeWindowsAddon 腳本加入到你的package.json

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

產生的範本包含一個範例 ShowNotification 函式,該函式使用 Windows SDK 通知 API。 讓我們透過建立插件來確認所有設定是否正確:

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

Note

你也可以用 npx winapp node create-addon --template cs 建立 C# 插件。 C# 插件使用 node-api-dotnet。 更多選項可以參考其他建立插件的指南或 完整指令文件

步驟二:測試生成的外掛

讓我們從主程序呼叫產生的外掛來驗證它是否有效。 開啟 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

Note

這個指令已經是我們在設定指南中加入的腳本的一部分,所以它會在之後自動執行。 然而,每當修改Package.appxmanifest、更新應用程式資源,或重新安裝依賴關係時,您都需要手動執行。

現在啟動你的應用程式:

npm start

你應該會看到通知出現! 🎉 生成的插件開箱即用。

⚠️ 已知問題:應用程式當機或視窗空白(點擊展開)

Windows 有一個已知的 Electron 應用程式封裝稀疏錯誤,會導致應用程式啟動時當機或無法渲染網頁內容。 這個問題在 Windows 上已經修正,但尚未擴散到所有裝置。

請參考 開發環境設定 以取得解決方法。

步驟 3:升級至 Windows 應用程式 SDK 通知

既然我們已經確認外掛可運作,接下來升級它使用現代的 Windows 應用程式 SDK 通知 API(Microsoft.Windows.AppNotifications),這些 API 能提供更好的開發體驗和更多功能。 我們在執行初始化指令時,已經設定好 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 的模式。

步驟四:重建與測試

現在用更新的程式碼重建外掛:

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 來看到更新的通知!

後續步驟

祝賀! 你成功建立了一個原生的 C++ 外掛,可以呼叫 Windows 應用程式 SDK API! 🎉

現在你準備好:

或者探索其他指南:

其他資源