nuintun/node-adodb

It works perfectly on runtime node but not in asar

xielehe opened this issue · 6 comments

I developed an react+Electron application with node-adodb on Windows. It works perfectly in development mode, but when packaging everything (create the .exe and other electron files), the connection.query got "Uncaught Fatal Exception"

Using node-adodb version 4.2.2
React 16.4.0
electron 2.0.5
electron-builder: 20.15.1

main.js code

ipcMain.on('read-cid', (event, obj) => {
  const connection = ADODB.open('Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\\Users\\DB.mdb;')
  async function query() {
      try {
          const users = await connection.query(`SELECT top 1 id_birth, id_addr FROM IDBaseInfo  `)
          event.returnValue = users
      } catch (error) {
           event.returnValue = error
      }
  }
  query()
})

不打包成asar就运行良好,打包成asar,就会出现Uncaught Fatal Exception,请问有什么方法可以在打包成asar的情况下使用模块吗
谢谢!

Yeah, so I had this issue a few months ago and figure out the problem. Basically this. Packaged Electron projects don't play well with child_process.spawn. And also cwd() doesn't work properly in asar files, that may have also contributed. I forget.

But the workaround is the following:

  1. In your packager settings, add a glob that matches the node-adodb package to the asar.unpack setting.
  2. Go to line 13 of proxy.js and change it so that it matches the unpacked directory.

The way I did this was I changed
require.resolve('./adodb')
to
require.resolve('./adodb').replace('app.asar', 'app.asar.unpacked')

I also published my own npm package to make things easier for myself, you can try it out if you want, and see if it works for you. It doesn't use the latest version though so just be aware of that. Just don't forget to add the unpacked setting or it won't work.

npm i -S node-adodb-electronfork

Hope it works out for you. Cheers.

HaveF commented

@lega0208 Did I need to change code? Something like

import * as ADODB from 'node-adodb-electronfork'
change to this?
import * as ADODB from '../../node-adodb-electronfork'

Without luck both = =;

Still see this:

"Error: Spawn C:\WINDOWS\SysWOW64\cscript.exe error
    at ChildProcess.<anonymous> (file:///C:/Users/dell/AppData/Local/Programs/analysis_system/resources/app.asar/dist/bundle.js:45:1210)
    at emitTwo (events.js:126:13)
    at ChildProcess.emit (events.js:214:7)
    at maybeClose (internal/child_process.js:925:16)
    at Socket.stream.socket.on (internal/child_process.js:346:11)
    at emitOne (events.js:116:13)
    at Socket.emit (events.js:211:7)
    at Pipe._handle.close [as _onclose] (net.js:554:12)"

Could you tell me how to debug this?

@HaveF No, the path to the package should be the same. It looks like the replace function isn't working properly though, which is strange. Because it should change the "app.asar" folder name to "app.asar.unpacked". I wouldn't include it in the bundle though because if you unpack it, then there's extra overhead because it has to be read from the filesystem, so you want to only unpack the code that needs to be unpacked.
In any case, I'm on vacation on another continent at the moment so I can't help much, but iirc, Electron 3.0 includes features to address this exact problem, so I would look into that. (Plus it has a much newer version of node + chromium/V8, so less polyfills needed and better performance)

I also haven't looked into newer versions of the actual node-adodb package, nuintun may have fixed this already.

So good luck, and if you still need help in a week or so I can probably look into it.

HaveF commented

@lega0208 Thanks for your kindness and detailed explanation. Frankly speaking, I do not understand the unpack part. I configure the electron-builder to unpack the node-adodb or your version node-adodb-electronfork, and make sure after installed the production of my app, the dir is over there. I thought bundle.js is only about the src code which exclude node_modules, maybe I am wrong. I use this webpack config, it seems not exclude node_modules dir.

I use the newest version of node-adodb(4.2.2) but failed, then find your solution but still without success.

Thank your info. I will try later.

Have a good vacation 😄

HaveF commented

Get everything work by a trick.

I use webpack.

  • In the main process add this before opening the BrowserWindow
const nodeEnv = process.env.NODE_ENV;

if(nodeEnv === 'development'){
  global.ADODB = require('node-adodb')
} else {
  let libPath = path.join(app.getAppPath(), 'node_modules/node-adodb').replace('app.asar', 'app.asar.unpacked')
  global.ADODB = require(libPath)
}
  • In the renderer process pick the value this way:
const ADODB = require('electron').remote.getGlobal('ADODB')

Btw, new Electron version does not work in the situation, I tried on 4.0.0-nightly.20181010

Cheers

REF: node.js - How can I bundle a precompiled binary with electron - Stack Overflow

Yeah, so I had this issue a few months ago and figure out the problem. Basically this. Packaged Electron projects don't play well with child_process.spawn. And also cwd() doesn't work properly in asar files, that may have also contributed. I forget.

But the workaround is the following:

  1. In your packager settings, add a glob that matches the node-adodb package to the asar.unpack setting.
  2. Go to line 13 of proxy.js and change it so that it matches the unpacked directory.

The way I did this was I changed require.resolve('./adodb') to require.resolve('./adodb').replace('app.asar', 'app.asar.unpacked')

I also published my own npm package to make things easier for myself, you can try it out if you want, and see if it works for you. It doesn't use the latest version though so just be aware of that. Just don't forget to add the unpacked setting or it won't work.

npm i -S node-adodb-electronfork

Hope it works out for you. Cheers.

How to use this package? Any guidance?