电子远程(关闭、最小化等)不起作用(无法读取未定义的属性“getCurrentWindow”)

Posted

技术标签:

【中文标题】电子远程(关闭、最小化等)不起作用(无法读取未定义的属性“getCurrentWindow”)【英文标题】:Electron Remote (Close, Minimize etc) not work (Cannot read property 'getCurrentWindow' of undefined) 【发布时间】:2020-12-18 15:42:07 【问题描述】:

我正在尝试在 Electron JS 应用程序的无框窗口上添加关闭和最小化按钮。但它无论如何都不起作用。它总是显示“无法读取未定义的属性'getCurrentWindow'”错误。这是我的代码:

const remote = require('electron');

document.getElementById('minimize').onclick = function() 
    var window = remote.getCurrentWindow();
    window.minimize();


document.getElementById('close').onclick = function() 
    var window = remote.getCurrentWindow();
    window.close();

我还在 main.js 中添加了 webPreferences: nodeIntegration: true。

win = new BrowserWindow(width: 990, height: 660, title: "Okkhor52 Tools", show: false, resizable: false, frame: false, webPreferences: nodeIntegration: true);

请给我一个解决方案,我尝试在很多地方找到这个问题的解决方案,但我没有得到确切的解决方案。

【问题讨论】:

你用的是哪个电子版?如果是 10,你在这里找到答案***.com/questions/63269563/… 【参考方案1】:

解决方法很简单。只需在 main.js 的 BrowserWindow 中添加 webPreferences: enableRemoteModule: true

win = new BrowserWindow(
    width: 990, 
    height: 660,
    title: "Okkhor52 Tools", 
    resizable: false, 
    frame: false, 
    webPreferences: 
        nodeIntegration: true, 
        enableRemoteModule: true
    
); 

除了enableRemoteModule: true,你需要在webPreference中添加nodeIntegration: true,否则如果你从别人的javascript调用electron(比如const remote = require('electron');)它会不起作用。

【讨论】:

【参考方案2】:

如果您已经将 enableRemoteModule 设置为 true 并且仍然遇到此问题,则很可能是您需要 the remote module,或者需要一个需要它的文件内部 主要过程,至少对我来说是这样。远程模块在主进程中不是必需的,仅用于渲染器进程。

如果您需要或需要另一个在主进程中使用 require("electron").remote.getCurrentWindow() 的 javascript 文件,那么您将收到此错误。

不以任何方式在主进程中包含该代码即可解决此问题。

【讨论】:

我有一个文件可以处理我的 ipcMain.on 调用。我需要 main.js 文件中的那个文件。我猜这可能是我出现此错误的原因。但是,我需要访问 main.js 文件之外的 mainWindow,这就是我尝试访问远程的原因。我对电子还很陌生。你能帮忙吗? @DavidEssien 我对电子也很陌生,但我会看看我是否能提供帮助。只要您使用remote,在main.js 之外访问mainWindow 应该不是问题。但是,在您的main.js 中需要一个需要ipcMain 的文件( 使用remote,因为它不是主文件)将导致错误。不幸的是,据我所知,除了在main.js 文件中处理您的ipcMain.on 调用外,没有其他方法可以解决这个问题(抱歉,回复晚了)。【参考方案3】:

根据this 文章,我们根本不应该使用“远程”。更好的方式是通过Sending Messages与渲染器通信。

首先,您需要 WindowNodeHandlers 类来调用 BrowserWindow 最大化/取消最大化操作并更新 isMaximized 标志:

class WindowNodeHandlers 
  ipcMain.on('maximize', () => 
    BrowserWindow.getFocusedWindow()?.maximize();
  );

  ipcMain.on('unmaximize', () => 
    BrowserWindow.getFocusedWindow()?.unmaximize();
  );

  ipcMain.on('isMaximized', (event) => 
    event.returnValue = BrowserWindow.getFocusedWindow()?.isMaximized();
  );

然后创建 ElectronWindowApi 类来实现渲染器和主进程之间的通信:

class ElectronWindowApi implements MainWindowApi 
  maximize(): void 
   ipcRenderer.send('maximize');
  

  unmaximize(): void 
   ipcRenderer.send('unmaximize');
  

  isMaximized(): boolean 
   return ipcRenderer.sendSync('isMaximized') as boolean;
  
 

之后在你的 createWindow 函数中创建 WindowNodeHandlers 实例并为这些事件添加监听器,这些监听器会将消息发送回渲染器进程:

const createWindow = async () => 
 ...
 new WindowNodeHandlers();

 mainWindow.on('maximize', () =>
   mainWindow?.webContents.send('window-maximized')
 );

 mainWindow.on('unmaximize', () =>
   mainWindow?.webContents.send('window-unmaximized')
 );

您应该做的最后一件事是为这些消息添加处理程序并使用 ElectronWindowApi 在渲染器端调用最大化/取消最大化操作:

...
const windowApi = new ElectronWindowApi();
const [isMaximized, setIsMaximized] = useState(windowApi.isMaximized());
const onMaximized = () => setIsMaximized(true);
const onRestore = () => setIsMaximized(false);

const toggleMaximize = () => 
  isMaximized ? windowApi.unmaximize() : windowApi.maximize();
;

useEffect(() => 
  ipcRenderer.on('window-maximized', onMaximized);
  ipcRenderer.on('window-unmaximized', onRestore);
, []);

return (
   <IconButton
      aria-label=isMaximized ? 'minimize' : 'maximize'
      onClick=toggleMaximize
    >
      isMaximized ? (
        <SvgIcon
          component=MinimizeWindowIcon
        />
      ) : (
        <SvgIcon
          component=MaximizeWindowIcon
        />
      )
    </IconButton>
)
...

【讨论】:

【参考方案4】:

其实,从安全的角度,我建议你应该使用:

win = new BrowserWindow(
width: 990, 
height: 660,
title: "Okkhor52 Tools", 
resizable: false, 
frame: false, 
webPreferences: 
    nodeIntegration: false, //default 
    enableRemoteModule: true,
    preload: path.join(__dirname, 'preload.js')

); 并将你的js代码放入'preload.js'。

根据官方文档Disable the Node.js integration in all renderers that display remote content,nodeIntergration: true 非常危险。

【讨论】:

以上是关于电子远程(关闭、最小化等)不起作用(无法读取未定义的属性“getCurrentWindow”)的主要内容,如果未能解决你的问题,请参考以下文章

APOLLO CLIENT - 突变不起作用(无法读取未定义的属性“数据”)

TypeError:无法读取未定义的属性“获取”(修复冲突导入不起作用)

useContext 和 useReducer Hooks 不起作用。错误:无法读取未定义的属性“状态”

我的 Apollo 服务器的订阅不起作用:无法读取未定义的属性“标题”

TypeError:无法读取扑动中未定义的属性“应用程序”?颤动的网络不起作用?

api调用在一种方法中工作但在另一种方法中不起作用---TypeError:无法读取未定义的属性'getResponse'