简体   繁体   English

electron v10.1.1 给出 Uncaught TypeError: Cannot read property 'dialog' of undefined,但相同的代码在 electron v9.3.0 中有效

[英]electron v10.1.1 gives Uncaught TypeError: Cannot read property 'dialog' of undefined, but same code works in electron v9.3.0

I am trying to upload a file in an electron app which works perfectly for electron v9.3.0 but as soon as I use electron v10.1.1, it gives the following error Uncaught TypeError: Cannot read property 'dialog' of undefined at this line const dialog = electron.remote.dialog;我正在尝试在 electron 应用程序中上传一个文件,该应用程序非常适合 electron v9.3.0,但是一旦我使用 electron v10.1.1,它就会出现以下错误Uncaught TypeError: Cannot read property 'dialog' of undefined at this line const dialog = electron.remote.dialog; see the screenshot below.请参阅下面的屏幕截图。 在此处输入图像描述

The content of main.js is as below main.js 的内容如下

const { app, BrowserWindow } = require('electron') 

function createWindow () { 
// Create the browser window. 
const win = new BrowserWindow({ 
    width: 800, 
    height: 600, 
    webPreferences: { 
    nodeIntegration: true
    } 
}) 

// Load the index.html of the app. 
win.loadFile('src/index.html') 

// Open the DevTools. 
win.webContents.openDevTools() 
} 

// This method will be called when Electron has finished 
// initialization and is ready to create browser windows. 
// Some APIs can only be used after this event occurs. 
// This method is equivalent to 'app.on('ready', function())' 
app.whenReady().then(createWindow) 

// Quit when all windows are closed. 
app.on('window-all-closed', () => { 
// On macOS it is common for applications and their menu bar 
// To stay active until the user quits explicitly with Cmd + Q 
if (process.platform !== 'darwin') { 
    app.quit() 
} 
}) 

app.on('activate', () => { 
// On macOS it's common to re-create a window in the 
// app when the dock icon is clicked and there are no 
// other windows open. 
if (BrowserWindow.getAllWindows().length === 0) { 
    createWindow() 
} 
}) 

// In this file, you can include the rest of your 
// app's specific main process code. You can also 
// put them in separate files and require them here. 

The content of index.js is as below index.js 的内容如下

const electron = require('electron'); 
const path = require('path'); 

// Importing dialog module using remote 
const dialog = electron.remote.dialog;

var uploadFile = document.getElementById('upload'); 

// Defining a Global file path Variable to store 
// user-selected file 
global.filepath = undefined; 

uploadFile.addEventListener('click', () => { 
// If the platform is 'win32' or 'Linux' 
    if (process.platform !== 'darwin') { 
        // Resolves to a Promise<Object> 
        dialog.showOpenDialog({ 
            title: 'Select the File to be uploaded', 
            defaultPath: path.join(__dirname, '../assets/'), 
            buttonLabel: 'Upload', 
            // Restricting the user to only Text Files. 
            filters: [ 
                { 
                    name: 'Text Files', 
                    extensions: ['txt', 'docx'] 
                }, ], 
            // Specifying the File Selector Property 
            properties: ['openFile'] 
        }).then(file => { 
            // Stating whether dialog operation was 
            // cancelled or not. 
            console.log(file.canceled); 
            if (!file.canceled) { 
            // Updating the GLOBAL filepath variable 
            // to user-selected file. 
            global.filepath = file.filePaths[0].toString(); 
            console.log(global.filepath); 
            } 
        }).catch(err => { 
            console.log(err) 
        }); 
    } 
    else { 
        // If the platform is 'darwin' (macOS) 
        dialog.showOpenDialog({ 
            title: 'Select the File to be uploaded', 
            defaultPath: path.join(__dirname, '../assets/'), 
            buttonLabel: 'Upload', 
            filters: [ 
                { 
                    name: 'Text Files', 
                    extensions: ['txt', 'docx'] 
                }, ], 
            // Specifying the File Selector and Directory 
            // Selector Property In macOS 
            properties: ['openFile', 'openDirectory'] 
        }).then(file => { 
            console.log(file.canceled); 
            if (!file.canceled) { 
            global.filepath = file.filePaths[0].toString(); 
            console.log(global.filepath); 
            } 
        }).catch(err => { 
            console.log(err) 
        }); 
    } 
}); 

The content of index.html is as below index.html的内容如下

<!DOCTYPE html> 
<html> 
<head> 
    <meta charset="UTF-8"> 
    <title>Hello World!</title> 
    <!-- https://electronjs.org/docs/tutorial 
                        /security#csp-meta-tag -->
    <meta http-equiv="Content-Security-Policy"
        content="script-src 'self' 'unsafe-inline';" /> 
</head> 
<body> 
    <h1>Hello World!</h1> We are using node 
    <script> 
        document.write(process.versions.node) 
    </script>, Chrome 
    <script> 
        document.write(process.versions.chrome) 
    </script>, and Electron 
    <script> 
        document.write(process.versions.electron) 
    </script>. 

    <h3>File Upload in Electron</h3> 
    <button id="upload">Upload File</button> 
    
    <!-- Adding Individual Renderer Process JS File -->
    <script src="index.js"></script> 
</body> 
</html> 
const win = new BrowserWindow({ 
    width: 800, 
    height: 600, 
    webPreferences: { 
         enableRemoteModule: true,
         nodeIntegration: true
    } 
}) 

In order to access the remote module on the renderer process.为了访问渲染器进程上的remote模块。 We need to enable enableRemoteModule as true as this is default false from the newer version.我们需要将enableRemoteModule设为true因为这是较新版本的默认false

as @tpikatchu stated:正如@tpikatchu所说:

const win = new BrowserWindow({ 
    width: 800, 
    height: 600, 
    webPreferences: { 
         enableremotemodule: true,
         nodeIntegration: true
    } 
})

but enableremotemodule: trueenableremotemodule: true
has to be in camelCase: enableRemoteModule: true必须在驼峰式: enableRemoteModule: true

reference: https://www.electronjs.org/docs/api/browser-window参考: https : //www.electronjs.org/docs/api/browser-window

ps: Sorry for the new answer creation, but I can't comment yet. ps:很抱歉创建新答案,但我还不能发表评论。

For Electron 11.0 and above对于 Electron 11.0 及以上

The remote module has been deprecated.远程模块已被弃用。 This means that the dialog object, needed in order to update a file, is not accessible from aa renderer javascript file (such as index.js in this post).这意味着更新文件所需的对话框 object 无法从渲染器 javascript 文件(例如本文中的index.js )访问。 The dialog object is still accessible from the main entry point.仍然可以从主入口点访问对话框 object。 In order to fix this, you can use the ipcMain and ipcRenderer objects to manage communication between entry point and renderer javascript code.为了解决这个问题,您可以使用ipcMainipcRenderer对象来管理入口点和渲染器 javascript 代码之间的通信。

in main.js - or the entrypoint used in your app - add the following:main.js - 或者你的应用程序中使用的入口点 - 添加以下内容:

const {app, BrowserWindow, dialog, ipcMain } = require('electron')

// *** REST OF YOUR CODE GOES HERE *** 

ipcMain.on('file-request', (event) => {  
  // If the platform is 'win32' or 'Linux'
  if (process.platform !== 'darwin') {
    // Resolves to a Promise<Object>
    dialog.showOpenDialog({
      title: 'Select the File to be uploaded',
      defaultPath: path.join(__dirname, '../assets/'),
      buttonLabel: 'Upload',
      // Restricting the user to only Text Files.
      filters: [ 
      { 
         name: 'Text Files', 
         extensions: ['txt', 'docx'] 
      }, ],
      // Specifying the File Selector Property
      properties: ['openFile']
    }).then(file => {
      // Stating whether dialog operation was
      // cancelled or not.
      console.log(file.canceled);
      if (!file.canceled) {
        const filepath = file.filePaths[0].toString();
        console.log(filepath);
        event.reply('file', filepath);
      }  
    }).catch(err => {
      console.log(err)
    });
  }
  else {
    // If the platform is 'darwin' (macOS)
    dialog.showOpenDialog({
      title: 'Select the File to be uploaded',
      defaultPath: path.join(__dirname, '../assets/'),
      buttonLabel: 'Upload',
      filters: [ 
      { 
         name: 'Text Files', 
         extensions: ['txt', 'docx'] 
      }, ],
      // Specifying the File Selector and Directory 
      // Selector Property In macOS
      properties: ['openFile', 'openDirectory']
    }).then(file => {
      console.log(file.canceled);
      if (!file.canceled) {
      const filepath = file.filePaths[0].toString();
      console.log(filepath);
      event.send('file', filepath);
    }  
  }).catch(err => {
      console.log(err)
    });
  }
});

Replace your code in index.js for:index.js中的代码替换为:

const { ipcRenderer } = require('electron');
var uploadFile = document.getElementById('upload');

//upon clicking upload file, request the file from the main process
uploadFile.addEventListener('click', () => {
  ipcRenderer.send('file-request');
});

//upon receiving a file, process accordingly
ipcRenderer.on('file', (event, file) => {
  console.log('obtained file from main process: ' + file);
});

NOTE: I am using a asynchronous events.注意:我正在使用异步事件。 This can be made synchronous by using ipcRenderer.sendSync and processing a return value - check the electron documentation for more information.这可以通过使用ipcRenderer.sendSync并处理返回值来同步 - 查看electron 文档以获取更多信息。 The difference between the two is that sendSync is a synchronous promise: it blocks the window until a return value is issued by ipcMain .两者之间的区别在于sendSync是同步 promise:它会阻塞 window,直到ipcMain发出返回值。 This may seem desiarable for a process like this as we may want the window to wait for the file to be uploaded until allowing the user to continue interacting.这对于像这样的过程来说似乎是可取的,因为我们可能希望 window 等待文件上传,直到允许用户继续交互。 I did not do it that way because:我没有那样做,因为:

  • It would block the whole app if unproperly unhandled, as explained in the electron documentation如果处理不当,它将阻止整个应用程序,如electron 文档中所述
  • Even if the app is blocked on sendSync , the button clicks are processed.即使应用程序在sendSync上被阻止,按钮点击也会被处理。 Once the file dialogue is closed, the app will fire all responses of the clicks that have been made, so the blockage is not that useful.关闭文件对话框后,应用程序将触发所有已进行的点击响应,因此阻塞不是那么有用。
  • It is possible to manage whether the dialogue is open or not on the renderer javascript by using a simple bool and managing the cancel option - happy to provide this if anyone needs it!可以通过使用简单的 bool 和管理cancel选项来管理渲染器 javascript 上的对话是否打开 - 如果有人需要,我们很乐意提供它!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 未捕获的类型错误:无法使用 Electron 更新程序代码读取未定义的属性“on” - Uncaught TypeError: Cannot read property 'on' of undefined with Electron updater code 未捕获的TypeError:无法读取未定义的属性'fn',电子2,角6? - Uncaught TypeError: Cannot read property 'fn' of undefined, electron 2, angular 6? 带有 Electron 的 TestCafe 抛出“Uncaught TypeError: Cannot read property 'source' of undefined” - TestCafe with Electron throwing "Uncaught TypeError: Cannot read property 'source' of undefined" 电子类型错误:无法读取未定义的属性“ normalizePath” - Electron TypeError: Cannot read property 'normalizePath' of undefined 未捕获的类型错误:无法读取未定义的属性“on”。 我也尝试重新安装电子 - Uncaught TypeError: Cannot read property 'on' of undefined. I have tried to reinstall electron as well 类型错误:无法读取 ipcMainImpl 处未定义的属性“webContents”。 在电子 - TypeError: Cannot read property 'webContents' of undefined at ipcMainImpl. in electron 在 electron 中进行 ipc 调用时,“TypeError: Cannot read property 'on' of undefined” - “TypeError: Cannot read property 'on' of undefined” when making an ipc call in electron 类型错误:无法读取未定义的属性“v4” - TypeError: Cannot read property 'v4' of undefined 未捕获的TypeError:无法读取zTree_v3库上未定义的属性“ init” - Uncaught TypeError: Cannot read property 'init' of undefined on zTree_v3 library 反应路由器 v^4.0.0 未捕获类型错误:无法读取未定义的属性“位置” - react router v^4.0.0 Uncaught TypeError: Cannot read property 'location' of undefined
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM