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

VSTO Excel插件Azure AD认证:MSAL.NET弹窗尺寸优化问询

自定义VSTO Excel插件AAD认证小型弹窗实现方案

核心思路

MSAL.NET支持通过自定义Web UI替代默认的外部浏览器弹窗,我们可以用WPF创建一个小型窗口,嵌入WebView2控件加载AAD授权页面,完全控制窗口尺寸和样式,同时避免直接关联Excel主窗口导致的崩溃问题。

具体实现步骤

1. 添加WebView2控件依赖

在VSTO项目中安装Microsoft.Web.WebView2 NuGet包,用于嵌入浏览器承载授权页面。

2. 创建自定义WPF认证窗口

新建一个WPF Window(命名为AuthPopupWindow),设置固定尺寸并嵌入WebView2:

<Window x:Class="YourAddIn.AuthPopupWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:wv2="clr-namespace:Microsoft.Web.WebView2.Wpf;assembly=Microsoft.Web.WebView2.Wpf"
        Title="账户登录" Width="600" Height="700" ResizeMode="CanMinimize" WindowStartupLocation="CenterOwner">
    <Grid>
        <wv2:WebView2 x:Name="AuthWebView" />
    </Grid>
</Window>

3. 实现MSAL自定义Web UI逻辑

创建实现IWebUi接口的类,处理授权页面加载和回调URL捕获:

using Microsoft.Identity.Client;
using Microsoft.Web.WebView2.Wpf;
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;

public class CustomAuthWebUi : IWebUi
{
    public async Task<Uri> AcquireAuthorizationCodeAsync(Uri authorizationUri, Uri redirectUri, CancellationToken cancellationToken)
    {
        var tcs = new TaskCompletionSource<Uri>();
        var authWindow = new AuthPopupWindow();
        
        // 初始化WebView2环境
        await authWindow.AuthWebView.EnsureCoreWebView2Async();
        
        // 监听导航事件,捕获AAD授权回调
        authWindow.AuthWebView.NavigationStarting += (sender, e) =>
        {
            if (e.Uri.AbsoluteUri.StartsWith(redirectUri.AbsoluteUri))
            {
                e.Cancel = true;
                tcs.SetResult(e.Uri);
                authWindow.Close();
            }
        };
        
        // 加载AAD授权页面
        authWindow.AuthWebView.Source = authorizationUri;
        
        // 在VSTO的STA线程中显示窗口
        Application.Current.Dispatcher.Invoke(() => authWindow.ShowDialog());
        
        return await tcs.Task;
    }
}

4. 修改MSAL认证调用代码

替换原有的AcquireTokenInteractive调用,使用自定义Web UI:

Log.Verbose("calling AcquireTokenInteractive with custom web UI...");
authResult = await app.AcquireTokenInteractive(scopes)
                       .WithAccount(firstAccount)
                       .WithCustomWebUi(new CustomAuthWebUi()) // 启用自定义弹窗
                       .WithPrompt(Prompt.SelectAccount)
                       .ExecuteAsync();

5. 处理VSTO线程兼容问题

VSTO插件运行在STA线程,若出现线程异常,可通过单独线程启动窗口:

if (!Thread.CurrentThread.GetApartmentState().Equals(ApartmentState.STA))
{
    var thread = new Thread(() =>
    {
        var authWindow = new AuthPopupWindow();
        // 此处复用前面的WebView初始化和导航逻辑
        authWindow.ShowDialog();
    });
    thread.SetApartmentState(ApartmentState.STA);
    thread.Start();
    thread.Join();
}

额外优化点

  • 可在自定义窗口中添加加载动画、关闭按钮等元素,优化用户体验;
  • 若需将Excel主窗口设为弹窗父窗口,正确获取句柄的方式:
    using System.Diagnostics;
    IntPtr excelMainHandle = Process.GetCurrentProcess().MainWindowHandle;
    new WindowInteropHelper(authWindow).Owner = excelMainHandle;
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 08:10:29