How to prevent crashing app while using IOHOOK in electron app
Iohook is a Node.js global native keyboard and mouse listener.
That (Iohook) can handle keyboard and mouse events via native hooks inside and outside your javascript/typescript application.
Iohook determines the event of left-click, right-click, scrolling and key down, key up, key pressed, etc. events that are triggered by users.
I have created one application, with frontend Electron with version v8.5.5 and the backend is on Node.Js with a version of v12.14.1.
This application is working on 2 Operating systems (OS), respectively windows and Mac.
In this blog, I will briefly explain from purpose to solution of Iohook in electron application.
1. Purpose of use Iohook
Iohook handles the keyboard and mouse activity of users so the admin can keep track of the activity of users’ work.
Admin can count percentages of user’s activity during the work.
From this percentage, the admin can easily figure out the activity of users.
2. Configuration & Installation steps
Before installing the iohook package module, you will need to set a runtime version in your package.json.
When developing, you will need the Node.js runtime.
In production, your Electron app will need the Electron version.
Check out your ABI for node.js or electron (opens new window). The example below uses Node.js v12.X and Electron v8.X
For knowing the target of node and electron follow the below steps.
Install this package node-abi: npm install node-abi
- Import this module for usage : const nodeAbi = require(‘node-abi’)
- Get target of node and electron like this : nodeAbi.getAbi(‘7.2.0’, ‘node’) //51 nodeAbi.getAbi(‘1.4.10’, ‘electron’) //50
- Also you can get version of node and electron by giving target as an argument : Ex. nodeAbi.getTarget(’51’, ‘node’) // ‘7.2.0’ nodeAbi.getTarget(’50’, ‘electron’) // ‘1.4.15’
- Also you can get all target by using this syntax : Ex. nodeAbi.allTargetsOutput. [ { runtime: ‘node’, target: ‘0.10.48’, abi: ’11’, lts: false }, { runtime: ‘node’, target: ‘0.12.17’, abi: ’14’, lts: false }, { runtime: ‘node’, target: ‘4.6.1’, abi: ’46’, lts: true }, { runtime: ‘node’, target: ‘5.12.0’, abi: ’47’, lts: false }, { runtime: ‘node’, target: ‘6.9.4’, abi: ’48’, lts: true }, { runtime: ‘node’, target: ‘7.4.0’, abi: ’51’, lts: false }, { runtime: ‘electron’, target: ‘1.0.2’, abi: ’47’, lts: false }, { runtime: ‘electron’, target: ‘1.2.8’, abi: ’48’, lts: false },
{ runtime: 'electron', target: '1.3.13', abi: '49', lts: false }, { runtime: 'electron', target: '1.4.15', abi: '50', lts: false } ]
Now you know your target of node and electron. Now added below configuration inside package.json file.
"iohook": { "targets": [ "Node-72", "Electron-76" ] "platforms": [ "win32", "darwin" "linux" ], "arches": [ "x64", "ia32" ] }
After the above configuration, put it inside the package.json file. Install the iohook package using npm i iohook. It will add dependencies inside the package.json file.
“dependencies”: {
“iohook”: “^0.9.0”
}
Installation was done.
3. Available events in the iohook package
- Keypress (NOT WORKING AT THIS MOMENT, USE keydown/keyup)
Calls when the user presses and releases a key. Event contain next object: {keychar: ‘f’, keycode: 19, raw code: 15, type: ‘keypress’}
- keydown
Calls when the user presses a key. Event contain next object: { keychar: ‘d’, keycode: 46, rawcode: 8, type: ‘keydown’ }
- Keyup
Calls when the user releases a key. Event contain next object: {keychar: ‘f’, keycode: 19, rawcode: 15, type: ‘keup’}
- Mouseclick
Calls when the user clicks the mouse button. Event contain next object: { button: 1, clicks: 1, x: 545, y: 696, type: ‘mouseclick’ }
- Musedown
Calls when the user presses and releases a key. Event contain next object: { button: 1, clicks: 1, x: 545, y: 696, type: ‘mousedown’ }
- Mouseup
Calls when the user presses and releases a key. Event contain next object: { button: 1, clicks: 1, x: 545, y: 696, type: ‘mouseup’ }
- Mouse move
Calls when the user presses and releases a key. Event contain next object: { button: 0, clicks: 0, x: 521, y: 737, type: ‘mousemove’ }
- Mouse drag
Calls when the user presses and releases a key. Event contain next object: { button: 0, clicks: 0, x: 373, y: 683, type: ‘mousedrag’ }
- Mouse wheel
Calls when the user presses and releases a key. Event contain next object: { amount: 3, clicks: 1, direction: 3, rotation: 1, type: ‘mousewheel’, x: 466, y: 683 }
4. How to use IOHOOK In Electron Apps?
Import iohook package.
- const ioHook = require(‘iohook’); Use any one of the methods as per your requirement.
- ioHook.on(‘mousemove’, (event) => { console.log(event); // { type: ‘mousemove’, x: 700, y: 400 } });
Now Register and start the hook.
- ioHook.start();
5. Issues I face
Normally, Iohook code we place in the electron file. and It’s working fine in both os windows and mac.
It gives accurate keycodes of pressed keys by a user and left/right click information of mouse activity.
But in mac, when you press the caps lock key and some media keys, it crashes the electron application. All other keys are working fine.
6. The solution I find (IOHOOK In Electron Apps)
For mac, you have to place your iohook code inside the renderer process, which means inside react.js, the main entry point file where you have your routes. And after that, you send these activity details using ipcRenderer to the electron file.
After placing iohook code inside the renderer process file then it won’t crash the application and gives proper accurate keyboard and mouse events data.
You can see the code in below attachment snap.
class App extends PureComponent{ componentDidMount(){ const ipcRenderer = window.require('electron').ipcRenderer; let system = ipcRenderer.sendSync('getSystem'); if(system == 'Mac'){ const ioHook = window.require('ioHook'); ioHook.start(); ioHook.on('mouseclick',(event) => { if(event.button == 1){ ipcRenderer.sendSync('mouseLeftClick'); } if(event.button == 2){ ipcRenderer.sendSync('mouseRightClick'); } }); ioHook.on('mouseWheel',(event) => { if(event.rotation == -1){ ipcRenderer.sendSync('mouseUpWheel'); } if(event.rotation == 1){ ipcRenderer.sendSync('mouseDownWheel'); } }); ioHook.on('keydown',(event) => { ipcRenderer.sendSync('keyboardKeydown'); });
After applying the above solution, Now, Iohook is working fine.
Please share your reviews in the comments.
Enjoy!!!
Reference:- https://www.electronjs.org/
Leave a Reply
Want to join the discussion?Feel free to contribute!