|
@@ -30,33 +30,12 @@ func NewSerialPrinter(portName string, baudRate int) (*SerialPrinter, error) {
|
|
|
return &SerialPrinter{Port: port}, nil
|
|
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 {
|
|
type DOC_INFO_1 struct {
|
|
|
pDocName *uint16
|
|
pDocName *uint16
|
|
@@ -68,37 +47,37 @@ func PrintRaw(printerName string, data []byte) error {
|
|
|
namePtr, _ := syscall.UTF16PtrFromString(printerName)
|
|
namePtr, _ := syscall.UTF16PtrFromString(printerName)
|
|
|
rawType, _ := syscall.UTF16PtrFromString("RAW")
|
|
rawType, _ := syscall.UTF16PtrFromString("RAW")
|
|
|
|
|
|
|
|
- pd := PRINTER_DEFAULTS{
|
|
|
|
|
- pDatatype: rawType,
|
|
|
|
|
- pDevMode: 0,
|
|
|
|
|
- DesiredAccess: 0x000F0000 | 0x00000008, // PRINTER_ACCESS_USE | PRINTER_ACCESS_ADMINISTER
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
var handle syscall.Handle
|
|
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 {
|
|
if ret == 0 {
|
|
|
return fmt.Errorf("OpenPrinter 失败: %s", printerName)
|
|
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}
|
|
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
|
|
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)))
|
|
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
|
|
return nil
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-// copyToPrinter 通过临时文件 + COPY /B 到打印机共享发送 RAW 数据
|
|
|
|
|
func copyToPrinter(printerName string, data []byte) error {
|
|
func copyToPrinter(printerName string, data []byte) error {
|
|
|
tmpFile, err := os.CreateTemp("", "tkt_*.bin")
|
|
tmpFile, err := os.CreateTemp("", "tkt_*.bin")
|
|
|
if err != nil {
|
|
if err != nil {
|
|
@@ -112,23 +91,12 @@ func copyToPrinter(printerName string, data []byte) error {
|
|
|
}
|
|
}
|
|
|
tmpFile.Close()
|
|
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)
|
|
return PrintRaw(printerName, data)
|
|
|
}
|
|
}
|
|
|
|
|
|