Skip to content

Instantly share code, notes, and snippets.

@saugatdai
Last active October 6, 2023 06:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save saugatdai/5ba400d42e3fa4be66d323b2d826fe50 to your computer and use it in GitHub Desktop.
Save saugatdai/5ba400d42e3fa4be66d323b2d826fe50 to your computer and use it in GitHub Desktop.
ElectronJS Print BrowserWindow
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'">
<link href="./styles.css" rel="stylesheet">
<title>Hello World!</title>
</head>
<body>
<button id="click">Print</button>
<!-- You can also require other files to run in this process -->
<script src="./renderer.js"></script>
</body>
</html>
// Modules to control application life and create native browser window
const { app, BrowserWindow, ipcMain } = require('electron')
const path = require('path')
let mainWindow;
function createWindow() {
// Create the browser window.
mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
preload: path.join(__dirname, 'preload.js')
}
})
// and load the index.html of the app.
mainWindow.loadFile('index.html')
// Open the DevTools.
// mainWindow.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.
app.whenReady().then(() => {
createWindow()
app.on('activate', function () {
// 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()
})
})
// Quit when all windows are closed, except on macOS. There, it's common
// for applications and their menu bar to stay active until the user quits
// explicitly with Cmd + Q.
app.on('window-all-closed', function () {
if (process.platform !== 'darwin') app.quit()
})
// 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.
ipcMain.on('print', async () => {
const printers = await mainWindow.webContents.getPrintersAsync();
console.log(printers);
mainWindow.webContents.print({
silent: true,
deviceName: 'POS80QMS' ,
printBackground: true,
copies: 1,
pageSize: {
height: 2000,
width: 2000
}
}, (success, error) => {
if(success){
console.log('printed');
}else{
console.log('failed');
}
})
});
const {ipcRenderer} = require('electron');
// All of the Node.js APIs are available in the preload process.
// It has the same sandbox as a Chrome extension.
window.addEventListener('DOMContentLoaded', () => {
document.querySelector('#click').addEventListener('click', () => {
ipcRenderer.send('print');
})
});
// This file is required by the index.html file and will
// be executed in the renderer process for that window.
// No Node.js APIs are available in this process because
// `nodeIntegration` is turned off. Use `preload.js` to
// selectively enable features needed in the rendering
// process.
/* styles.css */
/* Add styles here to customize the appearance of your app */
@frank-dspeed
Copy link

Can you give me more background about your project i am sure we can get that solved via using a diffrent solution to your core problem.

Can you please comment here exactly what your trying to do.

Example: I am coding a App that should allow me to print diffrent pages on a predefined printer when some one clicks print?

@saugatdai
Copy link
Author

saugatdai commented Jul 3, 2022

Scenario :
When a user prints a button on a browser window, I want the to print a token number for the user directly without any prompt (silently) via a POS thermal printer. The program works perfectly on windows, but it is not running on linux. I've attached a youtube video of the program running on windows :

https://www.youtube.com/watch?v=9DY6Jxe-cWs

Once again thank you so much for your response...

Under the hood, my program is printing the web contents of an invisible browser window. In this gist, I've used the same code to print the contents of a browser window.

@frank-dspeed
Copy link

@saugatdai where does the token come from how do we generate it can we create that in the browser side maybe?

it would be better to move as much logic into the browser and away from electron for long term support and also later cross platform support on android ios and so on

@frank-dspeed
Copy link

there is for example in the browser already a:

https://developer.mozilla.org/en-US/docs/Web/API/Window/beforeprint_event

before print event that allows you to listen to print events directly when we combine that with a iframe that contains the token from the server side or client side we can print that iframe silently without opening the site.

@saugatdai
Copy link
Author

The following code is for creating the button that prints the token. The code is responsible for generating token from the storage and printing (Line 71 calls the function that is responsible for printing). The printing function is defined from the line number 76.

image

on the main process token is printed with the following lines of code :

image

The following lines of code adds contents to the contents of the invisible browser window :

image

@frank-dspeed
Copy link

frank-dspeed commented Jul 3, 2022

Ok i understand your problem now more exact as i tryed to move the logic to the browser we need to create some browser api's to support that i will forward that to the fugu project. nice use case!!!

So now lets make a solution for your problem you want to print a token to a print so you should maybe consider printing via the native print api of the system that your running on as you preselect the printer you already know what it is running

on linux printing something like a text is a simple shell command

require('child_process').execSync(`print TOKEN:::TOGETPRINTED`)

will get you up and running. The Api that your using from electron at present maybe makes problems and i have no way to fix electron but chromium and node are in my domain

so my proposal is to catch the before print event and then you use something like this https://www.npmjs.com/package/node-native-printer

and drop the usage of the electron method overall your use case is not well covered at present.

I my self if i would need to implement that would create 2 modules 1 for linux that uses the child process print method and one for windows that uses a small powershell code to print something .

Update

Do you run on WSL2 Enabled Windows? so Win11 if yes you can simply use the execSync method with WSL2 to directly print on all platforms that works even on MacOS

@frank-dspeed
Copy link

Final Conclusion

You should use CUPS it works on Linux/Mac native and on Windows you need to use WSL2 or WSL to enable it which is not hard

i found this example that has no dependencies but should get refactored to use fetch

this will then work on all Platforms and will be better then the current buggy native electron way of doing it

i will try to get printing with devtools work more easy as that would be a better solution.

@saugatdai
Copy link
Author

@frank-dspeed,
My words can not explain the value of your help and suggestions to me. I will try out every suggestions that you made and will be back soon to let you know if the problem gets resolved.

Thank you so much...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment