contextBridge 中未定义的电子对话框

Electron dialog undefined in contextBridge

平台

描述

我正在尝试显示来自 Electron 渲染器进程的文件对话框。我想我可以像通过 contextBridge.

引用 ipcRenderer 一样引用 dialog 对象
// preload.ts

const { contextBridge, ipcRenderer, dialog } = require('electron');
import type { IpcRendererEvent } from 'electron';

contextBridge.exposeInMainWorld(
  'ipc',
  {
    send: (channel: string, data: string[]) => {
      ipcRenderer.send(channel, data);
    },
    on: (channel: string, func: (evt: IpcRendererEvent, args: any) => void) => {
      ipcRenderer.on(channel, func);
    },
    chooseFile: (title: string) => dialog.showOpenDialogSync({
      title, properties: ['openFile']})
  }
)

但是当我调用 window.ipc.chooseFile('Some Title') 时,我收到一个错误:

Cannot read property 'showOpenDialogSync' of undefined

这似乎表明 dialog 引用未通过 contextBridge 代理。然而,传达 ipcRenderer 的前两个函数起作用了。 exposeInMainWorld documentation 警告我们并非所有类型都可以代理。

备注

  1. 我理解我示例中三个函数的通用性破坏了上下文隔离的安全目的。我只是想确定什么有效 之前 我投入了太多时间来设计详细的消息传递方案。

  2. 我明白我可以在主进程中实现这个功能,并通过IPC调用它。我没意见。我很好奇为什么 ipcRenderer 引用通过 contextBridge 成功代理,但 dialog 却没有。

问题不是通过 contextBridge 进行代理的问题,而是渲染器进程中完全可用的 Electron API 之一。不幸的是 dialog 不是其中之一(note "Process: Main" on its page), so it can't be referenced directly in the renderer process, even during preload. The old remote API 用于使用来自渲染器进程的主进程模块仍然可用,但它正确地警告你

The remote module is deprecated. Instead of remote, use ipcRenderer and ipcMain.

所以是的,您在注释 (2) 中的解决方案是预期的。