You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

将JavaScript Office插件转为可安装插件时的对话框功能问题

解决方案:VSTO+WebView2环境下替代Office对话框API实现外部窗口与回调

VSTO插件中的WebView2控件属于独立嵌入式浏览器环境,无法直接调用Office Web加载项专属的Office.context.ui API。要实现需求,需通过VSTO原生窗口承载WebView2替代Office对话框,并利用WebView2的消息机制完成任务窗格与外部窗口的通信。

一、实现外部窗口的创建与导航

1. 准备VSTO端基础代码

在VSTO项目中添加WinForm窗口(命名为AuthDialogForm),并安装Microsoft.Web.WebView2 NuGet包。在任务窗格后台代码中注册JS可调用的.NET方法,用于触发窗口打开:

private void TaskPane_Load(object sender, EventArgs e)
{
    webView2.CoreWebView2InitializationCompleted += async (s, args) =>
    {
        // 注册供JS调用的.NET对象
        webView2.CoreWebView2.AddHostObjectToScript("DialogHelper", new DialogHelper(this));
        // 注入脚本让JS能访问该对象
        await webView2.CoreWebView2.AddScriptToExecuteOnDocumentCreatedAsync(@"
            window.dialogHelper = window.chrome.webview.hostObjects.sync.DialogHelper;
        ");
    };
}

[ComVisible(true)]
public class DialogHelper
{
    private readonly YourTaskPaneControl _taskPane;
    public DialogHelper(YourTaskPaneControl taskPane)
    {
        _taskPane = taskPane;
    }

    public void OpenAuthDialog(string url)
    {
        var dialogForm = new AuthDialogForm(url);
        dialogForm.Show();
    }
}

2. 外部窗口加载目标URL

在AuthDialogForm中初始化WebView2并导航到指定页面,同时注册消息接收事件:

public partial class AuthDialogForm : Form
{
    public AuthDialogForm(string url)
    {
        InitializeComponent();
        webView2.CoreWebView2InitializationCompleted += (s, args) =>
        {
            webView2.CoreWebView2.Navigate(url);
            // 监听页面发送的消息
            webView2.CoreWebView2.WebMessageReceived += CoreWebView2_WebMessageReceived;
        };
        webView2.EnsureCoreWebView2Async();
    }

    private void CoreWebView2_WebMessageReceived(object sender, CoreWebView2WebMessageReceivedEventArgs e)
    {
        var message = e.WebMessageAsJson;
        // 将消息转发给任务窗格的WebView2
        Globals.ThisAddIn.TaskPaneWebView.CoreWebView2.PostWebMessageAsString(message);
        
        // 处理关闭指令
        if (message.Contains("\"message\":\"close\""))
        {
            this.Close();
        }
    }
}

3. 任务窗格JS触发窗口打开

替换原来的displayDialogAsync调用,改为调用.NET注册的方法:

document.getElementById('authBtn').addEventListener('click', () => {
    window.dialogHelper.OpenAuthDialog('https://www.ourfrontend.com/auth/google');
});

二、实现窗口操作后的回调触发

1. 外部页面发送消息

在外部页面(https://www.ourfrontend.com/auth/google)中,完成操作后通过WebView2 API发送消息:

// 触发用户信息回调
async function sendUserInfo() {
    const token = await getSignTokenLocal();
    const payload = payloadFromToken(token);
    window.chrome.webview.postMessage({ message: 'getUser', payload: payload });
}

// 触发窗口关闭
function closeWindow() {
    window.chrome.webview.postMessage({ message: 'close' });
}

2. 任务窗格JS处理回调

在任务窗格页面中监听WebView2的消息事件,执行原有的回调逻辑:

window.chrome.webview.addEventListener('message', (event) => {
    const msg = event.data;
    if (msg.message === 'getUser') {
        resolve(msg.payload);
    }
});

关键注意事项

  • 所有供JS调用的.NET类必须标记[ComVisible(true)]。
  • WebView2初始化需异步完成,避免空引用错误。
  • 消息建议使用JSON格式,便于结构化数据传输。

内容的提问来源于stack exchange,提问作者SoftTimur

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 02:40:16