GetCommTimeouts为网络打印机返回错误87

时间:2019-10-29 13:31:15

标签: .net windows vb.net winapi

对于与打印机的通信,我们使用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相同。

1 个答案:

答案 0 :(得分:0)

与Microsoft相关工程师讨论后,Get/SetCommTimeouts仅适用于直接连接到PC的打印机,例如串行或LPT端口。它也应该适用于蓝牙。而且它应该不起作用,现在不起作用,这是预期的行为。