Quellcode durchsuchen

fix: 打印回退PowerShell Out-Printer——USB打印机共享后通过命令行发送

lq vor 1 Monat
Ursprung
Commit
1747771a60

+ 13 - 13
internal/modules/printer/service/serial.go

@@ -3,8 +3,8 @@ package service
 import (
 	"fmt"
 	"os"
+	"os/exec"
 	"syscall"
-	"unsafe"
 
 	"github.com/tarm/serial"
 )
@@ -66,10 +66,8 @@ func NewUSBPrinter(printerName string) (*USBPrinter, error) {
 		}
 	}
 
-	// 所有路径都失败 → 用临时文件 + copy 命令的方式
-	return nil, fmt.Errorf("无法打开打印机 %s (\\\\.\\ 和 UNC均失败): %w。"+
-		"请到 Windows 控制面板→设备和打印机→右键 %s→打印机属性→共享→勾选'共享这台打印机'并设置共享名",
-		printerName, lastErr, printerName)
+	// 所有路径都失败 → 回退 PowerShell Out-Printer
+	return nil, fmt.Errorf("CREATE_FILE_FAILED:%s", printerName)
 }
 
 func (p *USBPrinter) Write(data []byte) error {
@@ -81,23 +79,25 @@ func (p *USBPrinter) Close() error {
 	return syscall.CloseHandle(p.handle)
 }
 
-// PrintRawFile 备选方案:通过临时文件 + copy 命令打印
+// PrintRawFile 通过临时文件 + PowerShell Out-Printer 打印
 func PrintRawFile(printerName string, data []byte) error {
 	tmpFile, err := os.CreateTemp("", "ticket_*.bin")
 	if err != nil {
 		return err
 	}
-	defer os.Remove(tmpFile.Name())
+	tmpPath := tmpFile.Name()
+	defer os.Remove(tmpPath)
 	if _, err := tmpFile.Write(data); err != nil {
 		tmpFile.Close()
 		return err
 	}
 	tmpFile.Close()
-	_, _, _ = syscall.NewLazyDLL("kernel32.dll").NewProc("CopyFileW").Call(
-		uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(tmpFile.Name()))),
-		uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(fmt.Sprintf("\\\\127.0.0.1\\%s", printerName)))),
-		0)
-	return nil
+
+	// PowerShell: Get-Content <file> -Encoding Byte | Out-Printer -Name "<printer>"
+	cmd := exec.Command("powershell", "-Command",
+		fmt.Sprintf("Get-Content -Path '%s' -Encoding Byte | Out-Printer -Name '%s'", tmpPath, printerName))
+	return cmd.Run()
 }
 
-var _ = os.Stderr // keep os import
+var _ = os.Stderr  // keep os import
+var _ = exec.ErrNotFound // keep exec import

+ 12 - 2
internal/modules/printer/service/service.go

@@ -20,10 +20,11 @@ func (s *PrintService) PrintTicket(printerID uint, lotName, channelCode, plateNo
 		return fmt.Errorf("打印机未配置: id=%d", printerID)
 	}
 
-	// 根据 port_name 判断连接类型:COMx=串口,其他=Windows USB打印机名
+	// 根据 port_name 判断连接类型
 	var err error
 	var usb *USBPrinter
 	var srl *SerialPrinter
+	var usePS bool // 使用 PowerShell Out-Printer
 	write := func(data []byte) {}
 
 	if len(printer.PortName) >= 3 && printer.PortName[:3] == "COM" {
@@ -31,12 +32,21 @@ func (s *PrintService) PrintTicket(printerID uint, lotName, channelCode, plateNo
 		if err == nil { defer srl.Close(); write = func(data []byte) { srl.Write(data) } }
 	} else {
 		usb, err = NewUSBPrinter(printer.PortName)
-		if err == nil { defer usb.Close(); write = func(data []byte) { usb.Write(data) } }
+		if err == nil {
+			defer usb.Close()
+			write = func(data []byte) { usb.Write(data) }
+		} else {
+			// CreateFile 失败 → 回退 PowerShell Out-Printer
+			err = nil
+			usePS = true
+			write = func(data []byte) { PrintRawFile(printer.Name, data) }
+		}
 	}
 	if err != nil {
 		global.GVA_DB.Model(&printer).Update("status", "offline")
 		return fmt.Errorf("连接打印机失败: %w", err)
 	}
+	_ = usePS
 
 	now := time.Now().Format("02-01-2006 15:04:05")
 	slipNo := fmt.Sprintf("%d", ticketID)