是否可以在桌面 outlook-js 插件上使用 sessionStorage?

Is it possible to utilize sessionStorage on desktop outlook-js addins?

TL;DR

我使用 sessionStorage 在插件的不同部分之间进行通信,在撰写 window 中按下功能区按钮时执行的代码,以及它打开的对话框。这在浏览器中有效,但在桌面 outlook 对话框中的 sessionStorage 是空的。给出了什么?

//TL;DR

我构建了一个 js 插件,它在网络浏览器中运行良好,但在桌面上却严重损坏。我宁愿在桌面上完全禁用它,因为有一个 VSTO 插件比 js api 做的更多,但由于我还没有找到这样做的方法,我现在唯一的选择似乎是是:使js版本在全球范围内工作。

我发现桌面是所有 "browsers" 中的 运行ing IE 并且我在 outlook.com 上使用 IE 调试插件已经很远了,但是我有 运行 由于语法错误,我现在遇到了一个只出现在桌面 outlook 上的问题。

基本思想是:当用户启动此操作时,我想在 sessionStorage 中创建一个对象,除非它存在。然后对话框将读取对象并向用户显示一个表单,提交后更新对象,应用设置并关闭对话框。 由于某些原因,在桌面 outlook 上,当对话框启动时,该键的 sessionStorage 为空,而在浏览器中(即使使用 IE)它被正确初始化。

我试过使用 F12Chooser 打开开发控制台,但由于它是在我要调试的代码已经运行 运行 之后才开始播放的,所以我不知道该怎么做才能捕捉到对话框因为它被执行了。

代码时间:

对话框按钮在清单中定义为

<ExtensionPoint xsi:type="MessageComposeCommandSurface">
...
    <Action xsi:type="ExecuteFunction">
        <FunctionName>showMessageDialog</FunctionName>
    </Action>

其中 运行 个:

function showMessageDialog(event) {
    addinLogic.initializeMessage().done(function(messageItem) {
        addinSessionStorage.setItem('CurrentAccount', Office.context.mailbox.userProfile.emailAddress);
        addinSessionStorage.setItem(addinLogic.CurrentMessageItems, messageItem);
        $.when(openDialogAsIframe('/dialogfile.html')).always(function(){ event.completed(); });
    });
}
function openDialogAsIframe(dialogPage) {
    var def = $.Deferred();
    Office.context.ui.displayDialogAsync(
        window.location.protocol + '//' + window.location.host + dialogPage,
        { height: 50, width: 75, displayInIframe: true }, dialogCallback.bind(def));
    return def.promise();
}

此时 sessionstorage 应该包含该对象,但是,当对话框启动时,它 return 告诉我 messageItem 对象不存在。

(function () {
    var _messageItem = null;
    ...
    Office.onReady( function addinLevelsControllerInit(reason) {
        app.initialize();
        $(function () {
            ...
            _messageItem = addinSessionStorage.getItem(addinLogic.CurrentMessageItems);
            if (!_messageItem) {
                Office.context.ui.messageParent('messageItem isnt there!');
                return;
            }

addinSessionStorage.getItem 基本上 window.sessionStorage || window.opener.sessionStorage || parent.window.opener.sessionStorage

到目前为止,获得任何信息的唯一方法是打开 F12 window 并告诉它在任何异常时停止,这给了我像 IE6 级别的错误消息,没有任何能力更深入地调查错误状态。 经过一番努力,我已经能够将问题缩小到这里,现在我能想到的进一步调试的最佳方法是猜测工作和通过 ui.messageParent 的 return 消息。 如果只有一种方法可以将 console.log 重定向到文件..

--

编辑:所以即使我没有找到任何好的调试途径,我也已经有所进展。如果我将此对象写入 localStorage,插件工作正常,但由于正在处理敏感数据,因此无法将其永久保留在磁盘上。

我应该如何解决这个问题,因为从 Outlook/IE 的角度来看,功能区按钮和打开的对话框似乎 运行 在不同的会话中?

我不确定它是否 100% 适用于您的情况:但我过去用于 "on-load" 问题的一个调试技巧是:

  1. 让taskpane/dialog正常加载

  2. 附加 Visual Studio(例如使用 https://docs.microsoft.com/en-us/office/dev/add-ins/testing/attach-debugger-from-task-pane 处的说明)。在代码中找到您要设置断点的位置;或在代码本身中使用 debugger; 关键字(请注意,当您的 add-in 正在加载时它最初没有效果,因为未附加调试器;但是一旦附加了调试器, debugger;关键字将充当自动断点)。

  3. 从 Visual Studio 右上角的 "Quick Launch" 菜单,启动 "JavaScript Console"

  4. 在出现的 window 中,键入 window.location.reload() 并按回车键:

  1. 您的断点现在应该可以捕获 -- 因此您应该能够调试您的启动逻辑。

希望对您有所帮助!

~迈克尔

因为 sessionStorage 是唯一满足自动清除、最新且可在插件功能之间共享的要求的存储位置;这是我所知道的唯一可行的选择。

但在桌面 outlook 上,会话并未在所有部分之间共享,因为 outlook 用于 运行 js 插件的 IE 表现得好像在执行每个插件功能后关闭,从而清除 sessionStorage .

我相信我也找到了相关的文档 -- https://docs.microsoft.com/en-us/office/dev/add-ins/develop/dialog-api-in-office-add-ins#take-advantage-of-a-performance-option-in-office-online : "If the add-in is not running in Office Online, the displayInIframe is ignored." 这使得桌面 outlook 在单独的 window 中打开我的对话框,因此 https://docs.microsoft.com/en-us/office/dev/add-ins/develop/dialog-api-in-office-add-ins#use-the-office-dialog-api-with-single-page-applications-and-client-side-routing"Important! The dialog box is in a new window with its own execution context ... Similarly, the dialog window has its own session storage, which is not accessible from code in the task pane."

因此,在我找到更好的 inter-add-in 通信方法之前,我不得不求助于很长一段时间以来最丑陋的黑客之一:

Office.onReady(function(){
    addinLocalStorage = new addinStorage('localStorage');
    try { addinLocalStorage.setItem('_useSessionStorage', Office.context.mailbox.diagnostics.hostName != 'Outlook'); 
    } catch (e) {}

    if (addinLocalStorage.getItem('_useSessionStorage')) {
        addinSessionStorage = new addinStorage('sessionStorage');
    } else {
        addinSessionStorage = new addinStorage('localStorage', 'ss_');
    }
    ...
});

基本上,功能区按钮可以访问Office.context.mailbox,因此可以将平台设置为localStorage。对话框无法访问它,顺便说一下,这就是我被迫使用存储进行通信的全部原因,它可以读取 localStorage 并基于它来决定我们是否可以使用 sessionStorage。

现在剩下的就是弄清楚哪些 objects 我可以从 localStorage 中删除,哪些我应该保留,这样数据就不会永远保留在磁盘上。

哦,还有对帖子标题中问题的简短回答:NO