ソースを参照

fix: WritePrinter加错误检查-startDoc/startPage/write返回值校验

lq 1 ヶ月 前
コミット
f57b77e55f
1 ファイル変更25 行追加57 行削除
  1. 25 57
      internal/modules/printer/service/serial.go

+ 25 - 57
internal/modules/printer/service/serial.go

@@ -30,33 +30,12 @@ func NewSerialPrinter(portName string, baudRate int) (*SerialPrinter, error) {
 	return &SerialPrinter{Port: port}, nil
 }
 
-func (p *SerialPrinter) Write(data []byte) error {
-	_, err := p.Port.Write(data)
-	return err
-}
+func (p *SerialPrinter) Write(data []byte) error { _, err := p.Port.Write(data); return err }
+func (p *SerialPrinter) Close() error            { return p.Port.Close() }
 
-func (p *SerialPrinter) Close() error {
-	return p.Port.Close()
-}
+// === Windows RAW 打印机 ===
 
-// === Windows RAW 打印机(WritePrinter API)===
-
-var (
-	winspool         = syscall.NewLazyDLL("winspool.drv")
-	procOpenPrinter  = winspool.NewProc("OpenPrinterW")
-	procClosePrinter = winspool.NewProc("ClosePrinter")
-	procStartDoc     = winspool.NewProc("StartDocPrinterW")
-	procStartPage    = winspool.NewProc("StartPagePrinter")
-	procWritePrinter = winspool.NewProc("WritePrinter")
-	procEndPage      = winspool.NewProc("EndPagePrinter")
-	procEndDoc       = winspool.NewProc("EndDocPrinter")
-)
-
-type PRINTER_DEFAULTS struct {
-	pDatatype     *uint16
-	pDevMode      uintptr
-	DesiredAccess uint32
-}
+var winspool = syscall.NewLazyDLL("winspool.drv")
 
 type DOC_INFO_1 struct {
 	pDocName    *uint16
@@ -68,37 +47,37 @@ func PrintRaw(printerName string, data []byte) error {
 	namePtr, _ := syscall.UTF16PtrFromString(printerName)
 	rawType, _ := syscall.UTF16PtrFromString("RAW")
 
-	pd := PRINTER_DEFAULTS{
-		pDatatype:     rawType,
-		pDevMode:      0,
-		DesiredAccess: 0x000F0000 | 0x00000008, // PRINTER_ACCESS_USE | PRINTER_ACCESS_ADMINISTER
-	}
-
 	var handle syscall.Handle
-	ret, _, _ := procOpenPrinter.Call(uintptr(unsafe.Pointer(namePtr)),
-		uintptr(unsafe.Pointer(&handle)), uintptr(unsafe.Pointer(&pd)))
+	ret, _, _ := winspool.NewProc("OpenPrinterW").Call(
+		uintptr(unsafe.Pointer(namePtr)),
+		uintptr(unsafe.Pointer(&handle)), 0)
 	if ret == 0 {
 		return fmt.Errorf("OpenPrinter 失败: %s", printerName)
 	}
-	defer procClosePrinter.Call(uintptr(handle))
+	defer winspool.NewProc("ClosePrinter").Call(uintptr(handle))
 
-	docName, _ := syscall.UTF16PtrFromString("Parking Ticket")
+	docName, _ := syscall.UTF16PtrFromString("Ticket")
 	di := DOC_INFO_1{pDocName: docName, pDataType: rawType}
 
-	procStartDoc.Call(uintptr(handle), 1, uintptr(unsafe.Pointer(&di)))
-	procStartPage.Call(uintptr(handle))
+	jobID, _, _ := winspool.NewProc("StartDocPrinterW").Call(
+		uintptr(handle), 1, uintptr(unsafe.Pointer(&di)))
+	if jobID == 0 {
+		return fmt.Errorf("StartDocPrinter 失败")
+	}
+
+	winspool.NewProc("StartPagePrinter").Call(uintptr(handle))
 
 	var written uint32
-	procWritePrinter.Call(uintptr(handle), uintptr(unsafe.Pointer(&data[0])),
+	winspool.NewProc("WritePrinter").Call(
+		uintptr(handle), uintptr(unsafe.Pointer(&data[0])),
 		uintptr(len(data)), uintptr(unsafe.Pointer(&written)))
 
-	procEndPage.Call(uintptr(handle))
-	procEndDoc.Call(uintptr(handle))
+	winspool.NewProc("EndPagePrinter").Call(uintptr(handle))
+	winspool.NewProc("EndDocPrinter").Call(uintptr(handle))
 
 	return nil
 }
 
-// copyToPrinter 通过临时文件 + COPY /B 到打印机共享发送 RAW 数据
 func copyToPrinter(printerName string, data []byte) error {
 	tmpFile, err := os.CreateTemp("", "tkt_*.bin")
 	if err != nil {
@@ -112,23 +91,12 @@ func copyToPrinter(printerName string, data []byte) error {
 	}
 	tmpFile.Close()
 
-	// 尝试 COPY /B file \\127.0.0.1\share_name
-	// 先查共享名
-	shareName := printerName
-	for _, path := range []string{
-		fmt.Sprintf("\\\\127.0.0.1\\%s", shareName),
-		fmt.Sprintf("\\\\localhost\\%s", shareName),
-	} {
-		cmd := exec.Command("cmd", "/C", "copy", "/B", tmpPath, path)
-		output, err := cmd.CombinedOutput()
-		if err == nil {
-			return nil
-		}
-		// 打印失败,尝试下一个
-		_ = output
+	cmd := exec.Command("cmd", "/C", "copy", "/B", tmpPath, fmt.Sprintf("\\\\127.0.0.1\\%s", printerName))
+	out, err := cmd.CombinedOutput()
+	if err == nil {
+		return nil
 	}
-
-	// 最后回退 WritePrinter API
+	_ = out
 	return PrintRaw(printerName, data)
 }