none
64 bit compatibility RRS feed

  • Question

  • The following is a 32 bit function to list printers taken from http://word.mvps.org/FAQs/MacrosVBA/AvailablePrinters.htm I need to convert it for 64 bit use, but without easy access to a 64 bit version of Office, and with very little experience of programming for the 64 bit version of Office, it has so far eluded me. Is there any kind soul out there with ready access to the 64 bit version who can make the required changes please?

    Option Explicit

    Const PRINTER_ENUM_CONNECTIONS = &H4
    Const PRINTER_ENUM_LOCAL = &H2

    Private Declare Function EnumPrinters Lib "winspool.drv" Alias "EnumPrintersA" _
            (ByVal flags As Long, ByVal name As String, ByVal Level As Long, _
            pPrinterEnum As Long, ByVal cdBuf As Long, pcbNeeded As Long, _
            pcReturned As Long) As Long

    Private Declare Function PtrToStr Lib "kernel32" Alias "lstrcpyA" _
            (ByVal RetVal As String, ByVal Ptr As Long) As Long

    Private Declare Function StrLen Lib "kernel32" Alias "lstrlenA" _
           (ByVal Ptr As Long) As Long


    Public Function
    ListPrinters() As Variant

    Dim bSuccess As Boolean
    Dim iBufferRequired As Long
    Dim iBufferSize As Long
    Dim iBuffer() As Long
    Dim iEntries As Long
    Dim iIndex As Long
    Dim strPrinterName As String
    Dim iDummy As Long
    Dim iDriverBuffer() As Long
    Dim strPrinters() As String

    iBufferSize = 3072

    ReDim iBuffer((iBufferSize \ 4) - 1) As Long

    'EnumPrinters will return a value False if the buffer is not big enough
    bSuccess = EnumPrinters(PRINTER_ENUM_CONNECTIONS Or _
            PRINTER_ENUM_LOCAL, vbNullString, _
            1, iBuffer(0), iBufferSize, iBufferRequired, iEntries)

    If Not bSuccess Then
        If iBufferRequired > iBufferSize Then
            iBufferSize = iBufferRequired
            Debug.Print "iBuffer too small. Trying again with "; _
            iBufferSize & " bytes."
            ReDim iBuffer(iBufferSize \ 4) As Long
        End If
        'Try again with new buffer
        bSuccess = EnumPrinters(PRINTER_ENUM_CONNECTIONS Or _
                PRINTER_ENUM_LOCAL, vbNullString, _
                1, iBuffer(0), iBufferSize, iBufferRequired, iEntries)
    End If

    If Not bSuccess Then
        'Enumprinters returned False
        MsgBox "Error enumerating printers."
        Exit Function
    Else
        'Enumprinters returned True, use found printers to fill the array
        ReDim strPrinters(iEntries - 1)
        For iIndex = 0 To iEntries - 1
            'Get the printername
      
         strPrinterName = Space$(StrLen(iBuffer(iIndex * 4 + 2)))
            iDummy = PtrToStr(strPrinterName, iBuffer(iIndex * 4 + 2))
            strPrinters(iIndex) = strPrinterName
        Next iIndex
    End If

    ListPrinters = strPrinters

    End Function


    Graham Mayor - Word MVP
    www.gmayor.com

    Thursday, July 3, 2014 5:03 AM

Answers

  • This is so bizarre, I get the same result I tried the code in 32 bit environment it came up the way it should and then in 64 bit it is messed up !

    Although did a quick check on the internet. Chip Pearsons method of listing printer names seems to return the expected result. You might want to check it out. http://www.cpearson.com/excel/GetPrinters.aspx

    Even the MSDN Article seems to work : http://msdn.microsoft.com/en-us/library/office/ff835733%28v=office.15%29.aspx


    Happy to help ! When you see answers and helpful posts, please click Vote As Helpful, Propose As Answer, and/or Mark As Answered


    Friday, July 4, 2014 9:56 AM
  • Okay I did not check the MSDN was Access specific. I tried Chip's method on the Word 64 and 32 it worked just fine. Good luck ! :)

    Happy to help ! When you see answers and helpful posts, please click Vote As Helpful, Propose As Answer, and/or Mark As Answered

    Friday, July 4, 2014 11:17 AM

All replies

  • Hello Graham, This is the piece of coding you need to edit,

    Option Explicit
    
    Const PRINTER_ENUM_CONNECTIONS = &H4
    Const PRINTER_ENUM_LOCAL = &H2
    
    #If Win64 Then
        Private Declare PtrSafe Function EnumPrinters Lib "winspool.drv" Alias "EnumPrintersA" _
                (ByVal flags As Long, ByVal name As String, ByVal Level As Long, _
                pPrinterEnum As Long, ByVal cdBuf As Long, pcbNeeded As Long, _
                pcReturned As Long) As LongLong
    
        Private Declare PtrSafe Function PtrToStr Lib "kernel32" Alias "lstrcpyA" _
                (ByVal RetVal As String, ByVal Ptr As Long) As LongLong
    
        Private Declare PtrSafe Function StrLen Lib "kernel32" Alias "lstrlenA" _
               (ByVal Ptr As Long) As LongLong
    #Else
        Private Declare Function EnumPrinters Lib "winspool.drv" Alias "EnumPrintersA" _
                (ByVal flags As Long, ByVal name As String, ByVal Level As Long, _
                pPrinterEnum As Long, ByVal cdBuf As Long, pcbNeeded As Long, _
                pcReturned As Long) As Long
    
        Private Declare Function PtrToStr Lib "kernel32" Alias "lstrcpyA" _
                (ByVal RetVal As String, ByVal Ptr As Long) As Long
    
        Private Declare Function StrLen Lib "kernel32" Alias "lstrlenA" _
               (ByVal Ptr As Long) As Long
    #End If

    Please note, the above code will work both on 32 and 64 bit Access. Hope this helps.


    Happy to help ! When you see answers and helpful posts, please click Vote As Helpful, Propose As Answer, and/or Mark As Answered


    Thursday, July 3, 2014 9:44 AM
  • Hi Paul

    Thanks for jumping in. The code will be required to work in Word 2013, and while your version takes us a little further than my efforts, it fails at

    strPrinterName = Space$(StrLen(iBuffer(iIndex * 4 + 2)))

    Compile Error, Type Mismatch

    Any more ideas?


    Graham Mayor - Word MVP
    www.gmayor.com

    Thursday, July 3, 2014 10:44 AM
  • Are you sure that the error is thrown at that line? Because by the looks of it, the return value is an Array, so the error could occur at the point of assigning the function to a variable persay?

    Happy to help ! When you see answers and helpful posts, please click Vote As Helpful, Propose As Answer, and/or Mark As Answered

    Thursday, July 3, 2014 12:36 PM
  • Below is the screen shot from my correspondent who has been testing for me:


    Graham Mayor - Word MVP
    www.gmayor.com

    Thursday, July 3, 2014 1:57 PM
  • Investigating further, I have produced a version which doesn't crash the 64 bit version, but it doesn't read the printer list correctly in that version either.

    The sample document with the code is at https://dl.dropboxusercontent.com/u/57986755/Test%20Printers%20Module%2064%20bit.docm

    The macro enabled document has an autoopen macro that will present one to three message boxes and writes a list of the printers to a document variable displayed by a docvariable field on the document itself.

    In the 32 bit version it correctly produces a list as follows.


    However in the 64 bit version the list has some printers on the same line and there is an empty line.


    What am I missing?


    Graham Mayor - Word MVP
    www.gmayor.com

    Friday, July 4, 2014 8:51 AM
  • This is so bizarre, I get the same result I tried the code in 32 bit environment it came up the way it should and then in 64 bit it is messed up !

    Although did a quick check on the internet. Chip Pearsons method of listing printer names seems to return the expected result. You might want to check it out. http://www.cpearson.com/excel/GetPrinters.aspx

    Even the MSDN Article seems to work : http://msdn.microsoft.com/en-us/library/office/ff835733%28v=office.15%29.aspx


    Happy to help ! When you see answers and helpful posts, please click Vote As Helpful, Propose As Answer, and/or Mark As Answered


    Friday, July 4, 2014 9:56 AM
  • I'm glad it's not just me :)

    I had seen Chip's article, but as it didn't have the changes for 64 bit, I didn't feel the inclination to attack it. I am testing with his module that calls the function. If that doesn't work I will try and modify Chip's "GetPrinterFullNames" Function and see where that leads.

    The MSDN article I had dismissed as it uses Access specific variable types and this has to work in Word.


    Graham Mayor - Word MVP
    www.gmayor.com

    Friday, July 4, 2014 10:57 AM
  • Okay I did not check the MSDN was Access specific. I tried Chip's method on the Word 64 and 32 it worked just fine. Good luck ! :)

    Happy to help ! When you see answers and helpful posts, please click Vote As Helpful, Propose As Answer, and/or Mark As Answered

    Friday, July 4, 2014 11:17 AM
  • I have now checked Chips code and it works for both, with a few minor mods for my own requirements. Thanks for the hand holding :)

    Graham Mayor - Word MVP
    www.gmayor.com

    Friday, July 4, 2014 11:25 AM
  • Code walk through proved some many lines could be made redundant as they really did not serve much purpose like the port, as they did not seem to match exactly what it was actually ported to. So a small mod is a sure thing. Am glad you finally got it working. :) Happy to be of some minor assistance.

    Happy to help ! When you see answers and helpful posts, please click Vote As Helpful, Propose As Answer, and/or Mark As Answered

    Friday, July 4, 2014 11:29 AM
  • Hi, all.

    I know that this thread is too old, but I'm porting code to 64 bits and facing the same problem of Type Mismatch above; Space$ is a Long...

    I saw at GMayor's site the same 32 bit code (gmayor.com/get_available_printer_names).

    The link posted by Graham Mayor @ Dropbox on Friday, July 4, 2014 8:51 AM is no more, of course.

    MS has a 64 bit compatible code that uses; this is a last resort for me.

    So, anyone get luck trying to fix it? 
    Or should I pursue adapting Chip's digging registry method (cpearson.com => Excel/GetPrinters)?

    TIA

    Thursday, July 25, 2019 2:58 PM
  • Just looking at Graham's example and the x64 API declarations suggested by Paul, it looks like a lot needs changing. I could have a go with this but you say using x64 code is a last resort...?

    Chip Pearson's code is a different approach though the APIs also need adapting for x64. The registry approach won't return the port names, if you don't need them go with that.

    Friday, July 26, 2019 1:17 PM
    Moderator
  • Hi, all.

    I know that this thread is too old, but I'm porting code to 64 bits and facing the same problem of Type Mismatch above; Space$ is a Long...

    I saw at GMayor's site the same 32 bit code (gmayor.com/get_available_printer_names).

    The link posted by Graham Mayor @ Dropbox on Friday, July 4, 2014 8:51 AM is no more, of course.

    MS has a 64 bit compatible code that uses; this is a last resort for me.

    So, anyone get luck trying to fix it? 
    Or should I pursue adapting Chip's digging registry method (cpearson.com => Excel/GetPrinters)?

    TIA

    So, I gave up port the code at gmayor.com/get_available_printer_names   to 64 bits... it functions on 32 bits but returns garbage at 64 bits.
    For anyone that stops by here, here is the ported CPearson GetPrinters code to 64 bits  - only declaration, because the Function itself needs no alteration.

    #If Win64 Then Private Declare PtrSafe Function RegCloseKey Lib "advapi32.dll" ( _ ByVal HKey As Long) As Long Private Declare PtrSafe Function RegEnumValue Lib "advapi32.dll" _ Alias "RegEnumValueA" ( _ ByVal HKey As Long, _ ByVal dwIndex As Long, _ ByVal lpValueName As String, _ lpcbValueName As Long, _ ByVal lpReserved As Long, _ lpType As Long, _ lpData As Byte, _ lpcbData As Long) As Long Private Declare PtrSafe Function RegOpenKeyEx Lib "advapi32" _ Alias "RegOpenKeyExA" ( _ ByVal HKey As Long, _ ByVal lpSubKey As String, _ ByVal ulOptions As Long, _ ByVal samDesired As Long, _ phkResult As Long) As Long #Else

    ...

    Work as a charm...

    Cheers

     

    Saturday, October 19, 2019 10:57 PM
  • ... The registry approach won't return the port names, if you don't need them go with that ...

    Hi, CPearson's approach returned port names, in this format:

    Microsoft XPS Document Writer on Ne02:
    HP7E5B21 (HP OfficeJet Pro 8720) on Ne05:
    Microsoft Print to PDF on Ne03:
    ...
    ...

    HP Officejet 100 Mobile L411 BT on Ne04:
    Google Cloud Printer on 
    OneNote on Ne09:

       MS has a 64 bit compatible code that uses; this is a last resort for me.

    Above clearly is a wrong phrase... I do not remember what I tried to say then :)

    Saturday, October 19, 2019 11:24 PM