日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

electron通过edge-js调用TSCLIB.dll 打印卡白屏或退出的解决方案

發布時間:2024/3/26 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 electron通过edge-js调用TSCLIB.dll 打印卡白屏或退出的解决方案 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

軟件版本:

閱讀坑記需謹慎,版本要看仔細。

"node":"v14.16.0", "electron": "^13.0.0", //當然本文問題和vue 沒毛線關系 "vue": "^2.6.14", //遇到坑的主角是這個 "electron-edge-js": "^14.16.1", // 打包用到是該工具是 electron-builder,我想我遇到的坑應該和打包工具沒有啥關系,但還是列出來,便于交流

幾年前,直接使用IE 調用相關的插件執行打印,可,IE在win11已經找不到入口了,需要單獨設置edge瀏覽器,且使用的人,經常“不小心”重置網絡的安全,導致檢查需要遠程幫他們開啟,故此需要個桌面軟件,一次解決,永不煩人。

遇到的問題

經過查看tsc打印機官網,找到了SDK下載到入口tsc官方SDK下載地址(有些人很賤,從官網下載了資料,上傳到其他收費平臺上去“賺錢”);找到了nodejs相關的樣例。
nodejs的樣例,需要用到edge-js,但經過多日的入坑,找到的資料是使用:electron-edge-js;
用electron-edge-js參考官方的edge-js樣例,確實可以打印,但是:

如果循環打印大量數據,會卡死。

卡死的調試場景

  • 渲染進程的打印頁面(組件)循環 執行(調用)tsclibnet.dll打印方法;結果:頁面卡白了。
  • 我把對tsclibnet.dll是調用、循環打印,新開啟一個窗口來執行;結果,該新開的窗口,如果打印數量超過3條同樣還是卡死了。
  • 放在“主進程”來執行:通過渲染進程(頁面)向主進程發送數據信息,主進程執行數據的循環實施打印,結果還是卡死。

以上是我用electron-edge-js調用tsclibnet.dll遇到的問題,我不確定是不是因為我執行打印代碼寫的太垃圾,而導致卡死,或者我對electron了解太少,垃圾代碼貼出,便于交流:
(此代碼不要直接全部復制粘貼使用,我有刪改,不保證可執行)

//關于庫方法的說明,我在官方的站點中有pdf中文文檔 //為了方便交流,我找到一個html版本,方便閱讀的 https://www.e-learn.cn/topic/3539545 (以官方為準,此僅方便交流) var openport = edge.func({assemblyFile: './tsc_dll/tsclibnet.dll',typeName: 'TSCSDK.node_driver',methodName: 'openport' }); //省略了一堆官方樣例給到的如上動態庫引入方法 // windowsfont sendcommand barcode sendcommand printlabel 都省略了,看官方樣例 let data = [[{//文本類坐標信息"type": "text","printVal": {"x": 0,"y": 11,"fontheight": 40,"rotation": 0,"fontstyle": 0,"fontunderline": 0,"szFaceName": "黑體","content": "打印內容1"}}, {"type": "qrcode","printVal": "QRCODE 102,364,H,5,A,0,M2,S5,\"https://www.baidu.com\""}//此處省略了n組如上結構數據]//此處也省略了n組如上數據 ]; // data的解釋 // data的第一緯:出紙的總張數,即循環一次完,打印機打印完成,出一次紙 // data的第二緯度:每個需要打印內容和動態庫相應方法匹配,openport('打印機名或網絡地址', true); // 打印機相關配置 setup(conf,true); for (let i = 0; i < data.length; i++) {clearbuffer('', true);let reverseArr = [];data[i].forEach(ele => {// 文本類型處理if (ele.type == 'text') {windowsfont(ele.printVal, true);} else if (ele.type == 'qrcode'){// 二維碼類處理sendcommand(ele.printVal, true);} else if (ele.type == 'barcode'){// 條碼類處理barcode(ele.printVal, true);} else if (ele.type == 'reverse'){// 反相打印(黑底白字)類處理// 此處為什么不直接執行sendcommand()執行打印命令?// 因為反相打印如果在文字之前執行命令,只會打印一個黑塊,沒有字;如果需要黑底白字,就要放在所有指令的最后執行if (Array.isArray(ele.printVal) && ele.printVal.length > 0) {reverseArr.push.apply(reverseArr, ele.printVal);}}});// if (reverseArr.length > 0) {for (let ri = 0; ri < reverseArr.length; ri++) {sendcommand(reverseArr[ri], true);}}let label_variable = { quantity: '1', copy: '1' };// 此方法的參數的含義,我沒理解透printlabel(label_variable, true); } // 關閉打印機 closeport('', true);

以上就是我執行打印,頁面卡死的代碼。

解決方法嘗試

思來想去,翻來覆去搜索資料,開啟系統任務管理器,打印的時候CPU占用突增,是不是進程資源占用不符合系統規則,系統弄死該進程呢?如何重新開啟進程?略熟悉的語言也只有js?
nodejs 好像可以開啟臨時web服務,我把數據發送到另外一個軟件上執行,對吧。且還可以打包exe可執行文件->應該可以完美解決打印:

對,可行,沒有卡死,打印流程完美按照我的想法工作;(在本地 執行 node server.js 的時候服務完全正常啟動,打印正常完美執行;)
打印執行打循環體,還是上述代碼;web 服務我用node的框架 express(完全不懂,參照網絡樣例使用)

package.json 文件

{"name": "print_exe","version": "0.0.1","description": "執行打印服務","main": "server.js","author": {"name": "programmer"},"dependencies": {// 重新自己安裝,根據自己的版本來"edge-js": "^18.4.0","express": "^4.18.1"},"pkg": {"scripts": "build/**/*.js","assets": "views/**/*","targets": ["node14-win-x64"],"outputPath": "dist"} }

server.js

// 'use strict'; const fs = require('fs'); const crypto = require('crypto'); const path = require ('path'); var edge = require('edge-js'); var express = require('express'); var bodyParser = require('body-parser') var app = express();var urlencodedParser = bodyParser.urlencoded({ extended: false }); var urlencodedJsonParser = bodyParser.json(); app.use(bodyParser.urlencoded({extended: true })); app.use(express.static('./'));app.listen(5000, function () {console.log("Server Start!!");log("Server Start!!"); }) // 接受打印數據方法入口 app.post('/printing', urlencodedJsonParser, (req, res) =>{// 數據合理性驗證// 節約頁面,省去我的垃圾代碼res.json({code:0,message:'打印執行中請等待',data:null});printfile(req.body); });var openport; var setup; var about; var sendcommand; var clearbuffer; var printerfont; var barcode; var printlabel; var closeport; var sendcommand_utf8; var sendcommand_binary; var windowsfont; try {openport = edge.func({assemblyFile: 'tsclibnet.dll',typeName: 'TSCSDK.node_driver',methodName: 'openport'});setup = edge.func({assemblyFile: 'tsclibnet.dll',typeName: 'TSCSDK.node_driver',methodName: 'setup'});about = edge.func({assemblyFile: 'tsclibnet.dll',typeName: 'TSCSDK.node_driver',methodName: 'about'});sendcommand = edge.func({assemblyFile: 'tsclibnet.dll',typeName: 'TSCSDK.node_driver',methodName: 'sendcommand'});clearbuffer = edge.func({assemblyFile: 'tsclibnet.dll',typeName: 'TSCSDK.node_driver',methodName: 'clearbuffer'});printerfont = edge.func({assemblyFile: 'tsclibnet.dll',typeName: 'TSCSDK.node_driver',methodName: 'printerfont'});barcode = edge.func({assemblyFile: 'tsclibnet.dll',typeName: 'TSCSDK.node_driver',methodName: 'barcode'});printlabel = edge.func({assemblyFile: 'tsclibnet.dll',typeName: 'TSCSDK.node_driver',methodName: 'printlabel'});closeport = edge.func({assemblyFile: 'tsclibnet.dll',typeName: 'TSCSDK.node_driver',methodName: 'closeport'});sendcommand_utf8 = edge.func({assemblyFile: 'tsclibnet.dll',typeName: 'TSCSDK.node_driver',methodName: 'sendcommand_utf8'});sendcommand_binary = edge.func({assemblyFile: 'tsclibnet.dll',typeName: 'TSCSDK.node_driver',methodName: 'sendcommand_binary'});windowsfont = edge.func({assemblyFile: 'tsclibnet.dll',typeName: 'TSCSDK.node_driver',methodName: 'windowsfont'}); }catch (error) {log(error,'error'); } // 日志處理方法 function log(logContent,type='info') {//省去垃圾代碼, }/*** 執行打印* @param {Object} printData 打印數據*/ function printfile(printData){try {if (! printData.hasOwnProperty('print_name')) {throw "缺少打印機";}if (! printData.hasOwnProperty('printer_config')) {throw "缺少打印紙配置";}if (! printData.hasOwnProperty('print_data')) {throw "缺少打印數據";}const {print_name,printer_config,print_data} = printData;let {width,height,speed,consistence,sensor,spacing,offsetDistance,column} = printer_config;// 傳入的單位為cm 此處是單位處理width = width * 10;height = height * 10;spacing = spacing * 10;// 總寬 mmlet totalWidth = width * column + spacing * (column-1);// 打印紙配置數據const conf = {width: Math.ceil(totalWidth).toString(),//aheight: Math.ceil(height).toString(),//bspeed: speed.toString(),//cdensity: consistence.toString(),//dsensor: sensor.toString(),//evertical: spacing.toString(),//f verticaloffset: offsetDistance.toString(),//g};for (let i = 0; i < print_data.length; i++) {openport(print_name, true);setup(conf,true);clearbuffer('', true);sendcommand('DIRECTION 1');let reverseArr = [];print_data[i].forEach(ele => {log(ele.printVal);if (ele.type == 'text') {windowsfont(ele.printVal, true);} else if (ele.type == 'qrcode'){sendcommand(ele.printVal, true);} else if (ele.type == 'barcode'){barcode(ele.printVal, true);} else if (ele.type == 'reverse'){if (Array.isArray(ele.printVal) && ele.printVal.length > 0) {reverseArr.push.apply(reverseArr, ele.printVal);}}});if (reverseArr.length > 0) {for (let ri = 0; ri < reverseArr.length; ri++) {sendcommand(reverseArr[ri], true);}}let label_variable = { quantity: '1', copy: '1' };printlabel(label_variable, true);// 關閉打印機closeport('', true);log('打印關閉');}} catch (error) {// console.log(error);log(error,'error');} }

但是!但是!打包后的exe文件的啟動錯誤問題讓我無法解決:

Error: Module did not self-register: '\\?\E:\a\node_modules\edge-js\lib\native\win32\x64\14.19.3\edge_nativeclr.node'.


打包工具是 pkg
網絡上查找了原因,說需要重新針對自己的node版本打包動態庫!不想再去研究了,項目需要使用(向老板匯報)。

最終解決方法

之前簡單了解過Python 且也嘗試過Python 調用該庫,(很早之前記錄的踩坑記 Electron-vue開發桌面應用調用TSCLIB.dll)
只是之前 通過發送命令調用Python打包的 exe 程序;這次用Python的exe啟動了一個web服務,這樣用http方式發送打印數據到該服務器即可。

打印數據結構和循環體的邏輯,和最早代碼的邏輯一致:
特別注意:Python 的 TSCLIB.dll動態庫,和nodejs的不一致,去前文給到的官方地址下載Python 的例子,另外Python樣例的動態庫參數數據類型 沒有描述,參照 java 樣例的代碼可以知道參數類型。

我遇到的問題,都寫在代碼注釋中:(我的TSCLIB.dll庫和.py在同級)

# coding=utf-8 from flask import Flask,request,json,jsonify # import ctypes from ctypes import * import logging import os import datetime from time import strftime # import chardet app = Flask(__name__)''' 是否是開發 True-開發 False-生產 ''' # develop = False # 應用執行目錄,該應用存在于調用應用下的地址 appExePath = ""@app.route('/') def hello_world():# 用于應用檢測是否可以正常訪問return 'Hello World'@app.route('/printing',methods=['POST']) def exeprint():app.logger.info('info log')p_ddata = request.get_data()data = json.loads(p_ddata)# 的數據格式完全和最開始體到代碼 data 數據格式一致print_data = data['print_data']# 打印機名printer_name = data['print_name']# 打印機相關配置printer_config = data['printer_config']column = printer_config['column']width = printer_config['width'] * 10height = printer_config['height'] * 10vertical = printer_config['spacing'] * 10totalWidth = width * column + vertical * (column-1)speed = printer_config['speed']density = printer_config['consistence']sensor = printer_config['sensor']offset = printer_config['offsetDistance']# print(totalWidth)try:path = os.getcwd()dllPath = path+"\\TSCLIB.dll"tsclibrary = CDLL(dllPath)# 如果用了 tsclibrary.setup() 來設置,好像會出錯,不執行,我不清楚是否是傳入參數的錯誤,所以我用 tsclibrary.sendcommandW() 來執行我需要的設置命令# tsclibrary.setup(str(totalWidth),str(height),str(speed),str(density),str(sensor),str(spacing),str(offset))# setup (String width,String height,String speed,String density,String sensor,String vertical,String offset); # java 的# tsclibrary.sendcommandW("DIRECTION 1")for item in print_data:tsclibrary.openportW(printer_name)tsclibrary.sendcommandW("DIRECTION 1")tsclibrary.sendcommandW("SIZE "+str(totalWidth)+" mm, "+str(height)+" mm")tsclibrary.sendcommandW("GAP "+str(vertical)+" mm, 0 mm")tsclibrary.sendcommandW("SPEED "+str(speed))tsclibrary.sendcommandW("DENSITY "+str(density))# tsclibrary.setup(str(round(totalWidth)),str(round(height)),str(round(speed)),str(round(density)),str(round(sensor)),str(round(vertical)),str(round(offset)))tsclibrary.clearbuffer()reverseList = []for pd in item:if pd['type'] == 'text':x = pd['printVal']['x']y = pd['printVal']['y']fontheight = pd['printVal']['fontheight']rotation = pd['printVal']['rotation']fontstyle = pd['printVal']['fontstyle']fontunderline = pd['printVal']['fontunderline']szFaceName = pd['printVal']['szFaceName']szFaceName = 'simhei'content = pd['printVal']['content']# 官方給的 tsclibrary.windowsfontW() 好像調用無效(打印數據好像沒傳到打印機) # tsclibrary.windowsfontW 和 tsclibrary.windowsfont 有什么區別嗎?# 還是官方給到例子太老了??# tsclibrary.windowsfontW(x,y,fontheight,rotation, fontstyle, fontunderline, szFaceName,content)#無法打印# tsclibrary.windowsfont(x,y,fontheight,rotation, fontstyle, fontunderline, szFaceName,content)#打印亂碼tsclibrary.windowsfontUnicode( x, y, fontheight, rotation, fontstyle, fontunderline, szFaceName, content)#字體為默認宋elif pd['type'] == 'qrcode':tsclibrary.sendcommandW(pd['printVal'])elif pd['type'] == 'reverse':reverseList.extend(pd['printVal'])for revCmd in reverseList:tsclibrary.sendcommandW(revCmd)# tsclibrary.sendcommand(revCmd)# tsclibrary.printlabelW("1","1")tsclibrary.printlabel("1","1")tsclibrary.closeport()except OSError as err:app.logger.warning(err)print(err)return jsonify(status="success")if __name__ == '__main__':# 日志配置 不需要的話此處可以刪now=datetime.datetime.now()logdate = now.strftime("%Y-%m-%d")handler = logging.FileHandler(logdate+'.log', encoding='UTF-8')handler.setLevel(logging.DEBUG)logging_format = logging.Formatter('%(asctime)s - %(levelname)s - %(filename)s - %(funcName)s - %(lineno)s - %(message)s')handler.setFormatter(logging_format)app.logger.addHandler(handler)# 日志配置endapp.run()

Python 打印服務程序 全部代碼。
打包 exe 命令pyinstaller -F -w -i my.ico PrintServer.py 參考地址

應用程序啟動打印服務(python 打包的exe)

打包后的EXE 和 TSCLIB.dll 庫都和應用打包后的啟動exe位于同級目錄(如果要放在子目錄或者其他目錄 Python 動態庫地址,需要再處理,否則electon 無法啟動打印服務)

我的此段代碼是位于electron主js文件的最后。

try {// 啟動打印服務if (是生產) {//注意每個人的端口號可能不一樣child_process.exec('netstat -ano|findstr "5000"',(err, stdout, stderr)=>{if (stdout === "") {child_process.exec(`${homeDir}\\PrintServer.exe`,(err, stdout, stderr)=>{logger.info(`命令執行err:${err}`);logger.info(`命令執行stdout:${stdout}`);logger.info(`命令執行stderr:${stderr}`);});}else{logger.info('5000 端口被占用,或打印服務已啟動');}})}// 如果是開發,手動啟動打印服務 } catch (e) {logger.info(`命令執行異常:${e}`); }

后記

記錄我的坑,便于后來者。希望我遇到的問題您能避免,且把您的解決方案留言告訴我們有共同問題的人。

總結

以上是生活随笔為你收集整理的electron通过edge-js调用TSCLIB.dll 打印卡白屏或退出的解决方案的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。