对于与打印机的通信,我们使用WinApi方法和句柄。我们的解决方案可在Windows 7(32位和64位版本)上正常运行。当前,我们正在迁移到Windows 10,并且网络打印机存在问题。
问题是当我们尝试调用GetCommTimeouts
时,将其更新为所需的内容并将其重新设置。使用下面的代码,如果我使用对并行端口的直接访问(路径示例-\\.\LPT1
),则可以连接到打印机。但是,对于网络打印机(路径\\PcName\PrintersName
),以下代码在GetCommTimeouts
上失败。 (在示例中不是SetCommTimeouts
,但其行为与GetCommTimeouts
相同)。
它失败,错误代码为87,即“参数不正确”。但是结构应该有效并且设置了句柄。该句柄是正确的,因为如果我跳过Get / SetCommTimeouts函数,打印机将正确打印。 (未包含在代码中)
Private Const INVALID_HANDLE_VALUE As Integer = -1
Private Const GENERIC_READ = &H80000000L
Private Const GENERIC_WRITE = &H40000000
Private Const FILE_SHARE_READ = &H1
Private Const FILE_SHARE_WRITE = &H2
Private Const OPEN_ALWAYS = 4
Private Const FILE_FLAG_SEQUENTIAL_SCAN = &H8000000
Sub Main()
Dim handle = CreateFile("\\PcName\PrintersSharedName",
GENERIC_READ Or GENERIC_WRITE,
FILE_SHARE_READ Or FILE_SHARE_WRITE,
0,
OPEN_ALWAYS,
FILE_FLAG_SEQUENTIAL_SCAN,
0)
If Not handle <> INVALID_HANDLE_VALUE Then
Console.WriteLine("OpenDeviceHandle_Error")
Console.ReadLine()
Return
End If
Try
Dim commTimeouts As New COMMTIMEOUTS
Dim result = GetCommTimeouts(handle, commTimeouts)
If result = 0 Then
Dim exception As New Win32Exception
If exception.NativeErrorCode = 1 Then
Console.WriteLine("GetCommTimeouts_Correct")
Else
Console.WriteLine($"GetCommTimeouts_Error {exception.NativeErrorCode}")
End If
End If
Finally
CloseHandle(handle)
End Try
Console.ReadLine()
End Sub
<DllImport("Kernel32.dll", SetLastError:=True)>
Private Function CreateFile(lpFileName As String,
dwDesiredAccess As UInteger,
dwShareMode As UInteger,
lpSecurityAttributes As IntPtr,
dwCreationDisposition As UInteger,
dwFlagsAndAttributes As UInteger,
hTemplateFile As IntPtr) As Integer
End Function
<DllImport("Kernel32.dll", SetLastError:=True)>
Private Function GetCommTimeouts(iHandle As Integer, ByRef oCommTimeouts As COMMTIMEOUTS) As Integer
End Function
<DllImport("Kernel32.dll", SetLastError:=True)>
Private Function CloseHandle(hObject As IntPtr) As Integer
End Function
<StructLayout(LayoutKind.Sequential)>
Private Structure COMMTIMEOUTS
Dim ReadIntervalTimeout As UInteger ' Maximum time between read chars
Dim ReadTotalTimeoutMultiplier As UInteger ' Multiplier of characters
Dim ReadTotalTimeoutConstant As UInteger ' Constant in milliseconds
Dim WriteTotalTimeoutMultiplier As UInteger ' Multiplier of characters
Dim WriteTotalTimeoutConstant As UInteger ' Constant in milliseconds
End Structure
该相同代码在装有Windows 7的计算机上正常工作,即使这台计算机也可以连接到共享打印机,而共享打印机在Windows 10计算机上已连接。在Windows 10上,我无法通过共享路径连接到同一台计算机上的共享打印机。
我不确定,如果Win10需要与本地/共享打印机不同的东西,或者与Windows 10有关的东西,或者代码本身有错误,那是不能正常工作的。我尝试了不同的参数设置,多次检查了WinApi的接口和结构,检查打印机的访问权限是否与Win 7相同。
答案 0 :(得分:0)
与Microsoft相关工程师讨论后,Get/SetCommTimeouts
仅适用于直接连接到PC的打印机,例如串行或LPT端口。它也应该适用于蓝牙。而且它应该不起作用,现在不起作用,这是预期的行为。