VB6 StrPtr函数到VB.NET

时间:2016-08-25 15:29:03

标签: vb.net vb6-migration

尝试将VB6代码转换为VB.net。如果打印机关闭或打开,代码将用作标识 感谢

" PRINTERFOUND = OpenPrinterW(StrPtr(PrinterName),hPrinter)" 特定 StrPtr 功能......

无法使OpenPrinter工作 - 尝试打印我只是想知道打印机是关闭还是开启

将行更改为

PRINTERFOUND = OpenPrinterW(PrinterName.Normalize(),hPrinter,Nothing)

不起作用,谢谢

试图按照之前的建议将VB6声明转换为VB.net,但它仍然是同样的错误,无法将String转换为Integer,请参阅下面的

'Private Declare Function GetPrinterApi Lib "winspool.drv" Alias "GetPrinterA" (ByVal hPrinter As Long, ByVal Level As Long, ByRef BUFFER As  Long, ByVal pbSize As Long, ByRef pbSizeNeeded As Long) As Long     
 <DllImport("winspool.Drv", EntryPoint:="GetPrinterA", SetLastError:=True, CharSet:=CharSet.Ansi, ExactSpelling:=True, CallingConvention:=CallingConvention.StdCall)> _
Public Function GetPrinterApi(<MarshalAs(UnmanagedType.LPStr)> ByVal hPrinter As String, ByVal Level As IntPtr, ByVal BUFFER As IntPtr, ByVal pbSize As IntPtr, ByRef pbSizeNeeded As IntPtr) As Boolean
End Function

'Private Declare Function OpenPrinterW Lib "winspool.drv" (ByVal pPrinterName As Long, ByRef phPrinter As Long, Optional ByVal pDefault As Long = 0) As Long  
 <DllImport("winspool.Drv", SetLastError:=True, CharSet:=CharSet.Ansi, ExactSpelling:=True, CallingConvention:=CallingConvention.StdCall)> _
Public Function OpenPrinterW(ByVal pPrinterName As IntPtr, ByVal phPrinter As Int32, <[In](), MarshalAs(UnmanagedType.LPStruct)> ByVal pDefault As IntPtr) As Boolean
End Function

'Private Declare Function ClosePrinter Lib "winspool.drv" (ByVal hPrinter As Long) As Long
 <DllImport("winspool.Drv", EntryPoint:="ClosePrinter", SetLastError:=True, ExactSpelling:=True, CallingConvention:=CallingConvention.StdCall)> _
Public Function ClosePrinter(ByVal hPrinter As IntPtr) As Boolean
End Function

'Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (ByRef Destination As Long, ByRef Source As Long, ByVal Length As Long)  
 <DllImport("kernel32.dll", SetLastError:=True, EntryPoint:="RtlMoveMemory")> _
Public Function CopyMemory(ByRef Destination As Long, ByVal Source As IntPtr, ByVal Length As String) As IntPtr
End Function

完整代码

'Acknowledgements : This program has been written making extensive use of the
'Merrion article http://www.merrioncomputing.com/Programming/PrintStatus.htm
'It has also benefited from the contributors to VBForums thread # 733849
'http://www.vbforums.com/showthread.php?t=733849&goto=newpost - especially the code
'suggested by "Bonnie West"

'Program written 14 Sept. 2013 by C.A. Moore

Option Explicit

Dim PRINTERFOUND As Long
Dim GETPRINTER As Long
Dim BUFFER() As Long
Dim pbSizeNeeded As Long
Dim PRINTERINFO As PRINTER_INFO_2
Dim N As Integer
Dim M As Integer
Dim CHAR As String
Dim prnPrinter As Printer
Dim BUF13BINARY As String

' Note : PRINTERREADY as an Integer variable is Dim'd
'"Public PRINTERREADY As Integer" at Form1 Option Explicit

Private Type PRINTER_INFO_2
    pServerName As String
    pPrinterName As String
    pShareName As String
    pPortName As String
    pDriverName As String
    pComment As String
    pLocation As String
    pDevMode As Long
    pSepFile As String
    pPrintProcessor As String
    pDatatype As String
    pParameters As String
    pSecurityDescriptor As Long
    Attributes As Long
    Priority As Long
    DefaultPriority As Long
    StartTime As Long
    UntilTime As Long
    Status As Long
    JobsCount As Long
    AveragePPM As Long
End Type

Private Declare Function GetPrinterApi Lib "winspool.drv" Alias "GetPrinterA" (ByVal hPrinter As Long, ByVal Level As Long, BUFFER As Long, ByVal pbSize As Long, pbSizeNeeded As Long) As Long
Private Declare Function OpenPrinterW Lib "winspool.drv" (ByVal pPrinterName As Long, ByRef phPrinter As Long, Optional ByVal pDefault As Long) As Long
Private Declare Function ClosePrinter Lib "winspool.drv" (ByVal hPrinter As Long) As Long
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)

Public Function StringFromPointer(lpString As Long, lMaxLength As Long) As String
    'this service function extracts a string (sRet) when fed with a pointer (lpstring)
    'from a buffer
    Dim sRet As String
    Dim lret As Long

    If lpString = 0 Then
        StringFromPointer = ""
        Exit Function
    End If

    '\\ Pre-initialise the return string...
    sRet = Space$(lMaxLength)
    CopyMemory ByVal sRet, ByVal lpString, ByVal Len(sRet)
    If Err.LastDllError = 0 Then
        If InStr(sRet, Chr$(0)) > 0 Then
            sRet = Left$(sRet, InStr(sRet, Chr$(0)) - 1)
        End If
    End If

    StringFromPointer = sRet
End Function

Public Function IsPrinterReady(ByRef PrinterName As String)
    Form1.PRINTERREADY = 0

    'first select the named printer and check if it is installed
    For Each prnPrinter In Printers
        CHAR = prnPrinter.DeviceName
        If CHAR = PrinterName Then
            Set Printer = prnPrinter   'sets this as printer
            Form1.PRINTERREADY = 1
        End If
    Next

    If Form1.PRINTERREADY = 0 Then GoTo Line1000     'exit. printer not installed
        Dim hPrinter As Long
        Dim PI6 As PRINTER_INFO_2

        PRINTERFOUND = 0
        Form1.PRINTERREADY = 0
        PRINTERFOUND = OpenPrinterW(StrPtr(PrinterName), hPrinter)
        '(OpenPrinterW(ByVal pPrinterName As Long, ByRef phPrinter As Long) As Long)

        If PRINTERFOUND = 0 Then                'ie. printer not found
            Form1.PRINTERREADY = 0
            Debug.Assert ClosePrinter(hPrinter)
            GoTo Line100
        End If

        'If we get here named printer was found and accessed and its hPrinter handle is
        'known
         'Dim BUFFER() As Long
         'Dim pbSizeNeeded As Long

         ReDim Preserve BUFFER(0 To 1) As Long
         GETPRINTER = GetPrinterApi(hPrinter, 2&, BUFFER(0), UBound(BUFFER), pbSizeNeeded)
         ReDim Preserve BUFFER(0 To (pbSizeNeeded / 4) + 3) As Long
         GETPRINTER = GetPrinterApi(hPrinter, 2&, BUFFER(0), UBound(BUFFER) * 4, pbSizeNeeded)
         If GETPRINTER = 0 Then              'ie. some problem with printer access
             Form1.PRINTERREADY = 0
             GoTo Line100
         End If

         'If we get here then GETPRINTER = 1, ie. printer found and accessed OK
         With PRINTERINFO '\\ This variable is of type PRINTER_INFO_2
            'These quantities are defined here because the Merrion article
            'so specifies. However they are not used by this program, and most
            'have been found to be void

            .pServerName = StringFromPointer(BUFFER(0), 1024)
            .pPrinterName = StringFromPointer(BUFFER(1), 1024)
            .pShareName = StringFromPointer(BUFFER(2), 1024)
            .pPortName = StringFromPointer(BUFFER(3), 1024)
            .pDriverName = StringFromPointer(BUFFER(4), 1024)
            .pComment = StringFromPointer(BUFFER(5), 1024)
            .pLocation = StringFromPointer(BUFFER(6), 1024)
            .pDevMode = BUFFER(7)
            .pSepFile = StringFromPointer(BUFFER(8), 1024)
            .pPrintProcessor = StringFromPointer(BUFFER(9), 1024)
            .pDatatype = StringFromPointer(BUFFER(10), 1024)
            .pParameters = StringFromPointer(BUFFER(11), 1024)
            .pSecurityDescriptor = BUFFER(12)
            .Attributes = BUFFER(13)
            .Priority = BUFFER(14)
            .DefaultPriority = BUFFER(15)
            .StartTime = BUFFER(16)
            .UntilTime = BUFFER(17)
            .Status = BUFFER(18)
            .JobsCount = BUFFER(19)
            .AveragePPM = BUFFER(20)
        End With



        'This next code is for interest and program development only.
        'It writes into List1 the value of each buffer 1 - 20
        'To by-pass it, add a "Go To Line15" statement at this point.

        Form1.List1.Clear
        N = 0
Line5:
        On Error GoTo Line15
        Form1.List1.AddItem "Buffer No. " & N & "  Buffer Value " & BUFFER(N)
        N = (N + 1)
        If N = 21 Then GoTo Line15
        GoTo Line5

        'Now to convert the decimal value of Buffer(13) into a binary
        'bit pattern and store this in BUF13BINARY
Line15: 'and to show Buffer(13) as a binary bit pattern at Form1.Label1

        N = BUFFER(13)
        BUF13BINARY = ""
        M = 4196
Line16:
        If N < M Then
            BUF13BINARY = BUF13BINARY & "0"
            GoTo Line20
        End If

        BUF13BINARY = BUF13BINARY & "1"
        N = (N - M)
Line20:
        If M = 1 Then GoTo Line10
            M = M / 2
            GoTo Line16

Line10: 'BUF13BINARY is now the 13 bit binary value of Buffer(13)
        'eg. 0011000100010

        Form1.Label1.Caption = BUF13BINARY  'display this binary value at form 1

        'we now examine the value of the third binary bit in BUF13BINARY
        If Mid$(BUF13BINARY, 3, 1) = "0" Then Form1.PRINTERREADY = 1
        If Mid$(BUF13BINARY, 3, 1) = "1" Then Form1.PRINTERREADY = 0
Line100:
        ClosePrinter (hPrinter)
Line1000:
End Function

Option Explicit
Public PRINTERREADY As Integer

Private Sub Command1_Click()
    IsPrinterReady ("Brother QL-500")
    'IsPrinterReady ("EPSON Stylus CX5400")
    MsgBox PRINTERREADY                     '0 = Not Ready   1 = Ready
End Sub

2 个答案:

答案 0 :(得分:1)

您无法转换VarPtr,StrPtr或ObjPtr,,因为在.NET中您不直接控制内存。这些函数用于从实例,变量或Unicode字符串中提取指针。但是在.NET中,内存中的对象位置由垃圾收集器管理,GC可以随时在内存中移动对象。

请考虑以下代码,但不要使用!我把它放在这里只是为了解释为什么.NET中不存在这些函数。

Private Function VarPtr(ByVal obj As Object) As Integer
    ' Obtain a pinned handle to the object
    Dim handle As GCHandle = GCHandle.Alloc(obj, GCHandleType.Pinned)
    Dim pointer As Integer = handle.AddrOfPinnedObject.ToInt32

    ' Free the allocated handle. At this point the GC can move the object in memory, this is 
    ' why this function does not exist in .NET. If you were to use this pointer as a destination 
    ' for memcopy for example, you could overwrite unintended memory, which would crash the 
    ' application or cause unexpected behavior. For this function to work you would need to
    ' maintain the handle until after you are finished using it.
    handle.Free()

    Return pointer
End Function

编辑:

获取打印机状态的正确方法是通过托管界面,在本例中通过WMI:

Imports System.Management

Public Class Form1

    Private Enum PrinterStatus As Integer
        Other = 1
        Unknown = 2
        Idle = 3
        Printing = 4
        Warmup = 5
        Stopped = 6
        Offline = 7
    End Enum

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Dim mos = New ManagementObjectSearcher("SELECT * FROM Win32_Printer")

        For Each p In mos.Get()
            Debug.Print(p.Properties("Name").Value.ToString() & " : " & CType(CInt(p.Properties("PrinterStatus").Value), PrinterStatus).ToString())
        Next
    End Sub

End Class

您可以在此处获取有关Win32_Printer类的更多信息:https://msdn.microsoft.com/en-us/library/aa394363(v=vs.85).aspx

特别要注意这一点:

  

注意如果要检索PrinterStatus = 3或PrinterState = 0,则   打印机驱动程序可能无法将准确的信息输入WMI。 WMI   从spoolsv.exe进程检索打印机信息。它是   可能打印机驱动程序不会将其状态报告给假脱机程序。   在这种情况下,Win32_Printer将打印机报告为空闲。

从那里,您可以获得有关任何外围连接的信息和管理。只需弄清楚相应的WMI类并阅读文档。

答案 1 :(得分:0)

感谢所有人,特别是Drunken Code Monkey提供的所有信息,在阅读https://msdn.microsoft.com/en-us/library/aa394363(v=vs.85).aspx之后我终于实现了我想要的东西需要的是布尔值WorkOffline; Pew ..使它比VB6语言更简单,即使使用它感觉有点嗯老。同样幸运的是,我发现代码与我想要的相同,是链接到VB.NET&#34; https://bytes.com/topic/visual-basic-net/answers/524957-detecting-if-printer-connected-pc&#34;我修改了下面的代码

Imports System.Management
Public Class Form1
Public Class CheckPrinterStatus
    Public Function PrinterIsOnline(ByVal sPrinterName As String) As Boolean
        '// Set management scope
        Dim scope As ManagementScope = New ManagementScope("\root\cimv2")
        scope.Connect()

        '// Select Printers from WMI Object Collections
        Dim searcher As ManagementObjectSearcher = New ManagementObjectSearcher("SELECT * FROM Win32_Printer")

        Dim printerName As String = String.Empty
        For Each printer As ManagementObject In searcher.Get()
            printerName = printer("Name").ToString() '.ToLower()
            If (printerName.Equals(sPrinterName)) Then
                MsgBox(printerName)
                If (printer("WorkOffline").ToString().ToLower().Equals("true")) Then

                    MsgBox("Offline")
                    ' Printer is offline by user
                    Return False
                Else
                    ' Printer is not offline
                    MsgBox("Online")
                    Return True
                End If
            End If
        Next
        Return False
    End Function ' PrinterIsOnline
End Class
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    Dim PrinterSatus As New CheckPrinterStatus
    PrinterSatus.PrinterIsOnline("Brother QL-500") 'Name of The printer HERE
End Sub
End Class