LPT端口默认超时为五分钟。往此端口写一条数据,就是超时五分钟。n条就是5*n分钟。
往LPT端口发数据可以以字节方式发送,也可以以流的方式发送。其中以字节方式发送,超时时不会触发异常,而流的方式可以。捕获此异常,可以得到“打印机缺纸”的错误。
因为是测试,所以代码比较乱。重在理解。
字节方式(设置超时时长精准,但无法触发异常):
Public Class Form1
<DllImport("kernel32.dll")>
Private Shared Function CreateFile(
ByVal lpFileName As String,
ByVal dwDesiredAccess As Integer,
ByVal dwShareMode As Integer,
ByVal lpSecurityAttributes As Integer,
ByVal dwCreationDisposition As Integer,
ByVal dwFlagsAndAttributes As Integer,
ByVal hTemplateFile As Integer
) As Integer
End Function
<DllImport("kernel32.dll")>
Private Shared Function CloseHandle(ByVal hObject As Integer) As Integer
End Function
<DllImport("kernel32.dll")>
Private Shared Function GetCommTimeouts(ByVal hfile As Integer, ByRef lpCommTimeouts As COMMTIMEOUTS) As Boolean
End Function
<DllImport("kernel32.dll")>
Private Shared Function SetCommTimeouts(ByVal hfile As Integer, ByRef lpCommTimeouts As COMMTIMEOUTS) As Boolean
End Function
Private Structure COMMTIMEOUTS
Public ReadIntervalTimeout As Long
Public ReadTotalTimeoutMultiplier As Long
Public ReadTotalTimeoutConstant As Long
Public WriteTotalTimeoutMultiplier As Long
Public WriteTotalTimeoutConstant As Long
End Structure
<DllImport("kernel32.dll")>
Private Shared Function WriteFile(
ByVal hFile As Integer,
ByVal Buffer As Byte(),
ByVal nNumberOfBytesToWrite As Integer,
ByRef lpNumberOfBytesWritten As Integer,
ByRef lpOverlapped As OVERLAPPED
) As Integer
End Function
<StructLayout(LayoutKind.Sequential)>
Private Structure OVERLAPPED
Public ternal As Integer
Public ternalHigh As Integer
Public offset As Integer
Public OffsetHigh As Integer
Public hEvent As Integer
End Structure
Public Const GENERIC_READ As Long = &H80000000
Public Const GENERIC_WRITE As UInteger = &H40000000
Public Const OPEN_EXISTING As UInteger = 3
Private Shared _opened As Boolean = False
Private Shared _handle As IntPtr = -1
Public Shared Property Port() As String = "LPT1"
Dim ntime As COMMTIMEOUTS
Private Sub setTimeout()
_handle = CreateFile(Port, GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0)
ntime.ReadIntervalTimeout = 5000
ntime.ReadIntervalTimeout = 5000
ntime.ReadTotalTimeoutConstant = 5000
ntime.ReadTotalTimeoutMultiplier = 5000
ntime.WriteTotalTimeoutConstant = 5000
ntime.WriteTotalTimeoutMultiplier = 5000
SetCommTimeouts(_handle, ntime)
Close()
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
setTimeout()
OpenBox()
End Sub
Public Shared Sub WriteByte(ByVal data() As Byte)
If _opened Then
WriteFile(_handle, data, data.Length, data.Length, New OVERLAPPED)
End If
End Sub
Public Shared Sub Write_string(ByVal sData As String)
Dim bytes() As Byte = System.Text.Encoding.Default.GetBytes(sData)
WriteByte(bytes)
End Sub
Public Sub OpenBox()
OpenLPT()
MsgBox(1)
Write_string(Chr(27) & Chr(112) & Chr(0) & Chr(13) & Chr(10)) '开钱箱
Close()
MsgBox(2)
End Sub
Public Sub OpenLPT()
If _opened = False Then
_handle = CreateFile(Port, GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0)
If _handle = -1 Then
MsgBox("打开并口失败")
Exit Sub
End If
_opened = True
End If
End Sub
Public Sub Close()
If _handle <> -1 Then
CloseHandle(_handle)
_handle = -1
End If
_opened = False
End Sub
End Class
流方式(好像实际超时时长要比设置的超时时长多一倍):
Imports System.Runtime.InteropServices
Imports System.IO
Public Class Form1
<DllImport("kernel32.dll")>
Private Shared Function CreateFile(
ByVal lpFileName As String,
ByVal dwDesiredAccess As Integer,
ByVal dwShareMode As Integer,
ByVal lpSecurityAttributes As Integer,
ByVal dwCreationDisposition As Integer,
ByVal dwFlagsAndAttributes As Integer,
ByVal hTemplateFile As Integer
) As Integer
End Function
<DllImport("kernel32.dll")>
Private Shared Function CloseHandle(ByVal hObject As Integer) As Integer
End Function
<DllImport("kernel32.dll")>
Private Shared Function GetCommTimeouts(ByVal hfile As Integer, ByRef lpCommTimeouts As COMMTIMEOUTS) As Boolean
End Function
<DllImport("kernel32.dll")>
Private Shared Function SetCommTimeouts(ByVal hfile As Integer, ByRef lpCommTimeouts As COMMTIMEOUTS) As Boolean
End Function
Private Structure COMMTIMEOUTS
Public ReadIntervalTimeout As Long
Public ReadTotalTimeoutMultiplier As Long
Public ReadTotalTimeoutConstant As Long
Public WriteTotalTimeoutMultiplier As Long
Public WriteTotalTimeoutConstant As Long
End Structure
Public Const FILE_ATTRIBUTE_NORMAL As Short = &H80
Public Const INVALID_HANDLE_VALUE As Short = -1
Public Const GENERIC_READ As Long = &H80000000
Public Const GENERIC_WRITE As UInteger = &H40000000
Public Const CREATE_NEW As UInteger = 1
Public Const CREATE_ALWAYS As UInteger = 2
Public Const OPEN_EXISTING As UInteger = 3
Private Shared _opened As Boolean = False
Private Shared _handle As IntPtr = -1
Public Shared Property Port() As String = "LPT1"
Dim ntime As COMMTIMEOUTS
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
_handle = CreateFile(Port, GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0)
ntime.ReadIntervalTimeout = 2000
ntime.ReadIntervalTimeout = 2000
ntime.ReadTotalTimeoutConstant = 2000
ntime.ReadTotalTimeoutMultiplier = 2000
ntime.WriteTotalTimeoutConstant = 2000
ntime.WriteTotalTimeoutMultiplier = 2000
SetCommTimeouts(_handle, ntime)
Close()
OpenBox()
End Sub
'开钱箱
Public Sub OpenBox()
OpenLPT()
If _opened = False Then
MsgBox("LPT未打开")
Exit Sub
End If
MsgBox(1)
Try
Dim fs As FileStream = New FileStream(_handle, FileAccess.Write)
Dim sw As StreamWriter = New StreamWriter(fs, System.Text.Encoding.Default)
sw.Write(Chr(27) & Chr(112) & Chr(0) & Chr(13) & Chr(10))
sw.Close()
fs.Close()
Catch ex As Exception
MsgBox("exex:" & ex.Message)
End Try
Close()
MsgBox(2)
End Sub
'打印小票
Public Function Write(ByVal sData As String) As Boolean
setTimeout2()
If _opened = False Then
_handle = CreateFile(Port, GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0)
If _handle = -1 Then
LastError = ("打不开端口,重启电脑再试一次吧")
Return False
End If
End If
_opened = True
Try
Dim fs As FileStream = New FileStream(_handle, FileAccess.Write)
Dim sw As StreamWriter = New StreamWriter(fs, System.Text.Encoding.Default)
sw.Write(sData)
sw.Close()
fs.Close()
Close()
Return True
Catch ex As Exception
LastError = ex.Message
Close()
Return False
End Try
End Function
Public Sub OpenLPT()
If _opened = False Then
_handle = CreateFile(Port, GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0)
If _handle = -1 Then
MsgBox("打开并口失败")
Exit Sub
End If
_opened = True
End If
End Sub
Public Sub Close()
If _handle <> -1 Then
CloseHandle(_handle)
_handle = -1
End If
_opened = False
End Sub
End Class
测试的时候,把小票纸拿出来,制造一个缺纸状态。就能测试了。
注意上面发送的编码可能需要根据具体的收银机来修改一下。