Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Shaun E on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Printers.Count Not Counting Right

Status
Not open for further replies.

CassandraR

Programmer
Aug 10, 2001
346
CA
Hi:

I have a little problem. The Printers collection returns one too few printers. I have four installed, but Printers.Count returns 3.

I check the Printers entry under the Control Panel and find all four printers. Word finds all four. Several other (non-MS) applications find all four. The common dialog control finds all four printers.

However, Printers is always short by one.

I have tried removing the suspect printer driver software, cleaned the registry, rebooted and reloaded the driver software. All to no avail.

I have checked with other programs that I have written and tested. They all now fail to show all the printers (previously worked okay) -- the same printer goes missing.

Any suggestions?

Many thanks,
Cassandra
[neutral]
 

Have you tried to enum through the printers collection to see if you can find all four names?

Good Luck

 
Hi vb5prgrmr:

Thanks for your reply.

I have tried the following:

1.
Code:
    For each prtr in Printers
        Debug.Print prtr.DeviceName
    Next prtr

and 2.
Code:
    For I = 0 to 3
        Debug.Print Printers(I).DeviceName
    Next I

In the first case, only three of the four printers showed up. In the second case, an error occurs when I gets to 3 (i.e. the fourth printer). The error indicates index out of range.

Cassandra
 

Hmmm.... Odd

Sorry I cannot help you further since I cannot recreate your problem on this machine. For further information for other readers of this thread... What OS? What OS SP? What SP for VB6 do you have?

Good Luck

 
Can you also list the printers, are they all physical ones (i.e. things that will produce paper)

Take Care

Matt
If at first you don't succeed, skydiving is not for you.
 
Hi:

Microsoft Windows 98 SE 4.10.2222 A
Which SP I do not know. Just ran Windows Update and there is only the .NET Framework 1.1 update to be installed.

Visual Basic 6 Professional Edition, SP5

Printers:
Samsung ML-1200 Series <-- this is the problematic one
Generic / Text Only
Brother MFC-7100 Series
Brother MFL Pro Fax
Only the Generic / Text Only "printer" is non-paper; the other have physical printers attached. (The Pro Fax uses the Brother multifunction centre as a fax machine.)

Something that I forgot to mention was I was testing a new program. The program allows (or supposed to allow) one to change the name of a printer. It was after a run of this program that the printer went missing. My first suspicion was that a registry entry was modified, but I cannot locate any suspect entry. I also deleted all known files associated with the driver (manually.)

My suspicions is that I will need to remove VB6 and reinstall it -- something that I would prefer not to do.

Many Thanks,
Cassandra
 
Hi Cassandra,

The implication here is that the printer has in fact been deleted, if you test code is complaining of being out of range.

All I can suggest it to reinstall the printer, test your code, if the results are what you expect then, then rerun the other application that "renames" the printer. After that rerun your own code again.

If it fails again then it indeed puts the blame on the renaming program.


HTH


William
Software Engineer
ICQ No. 56047340
 
Hi William:

Per my original post above, I had fully removed and reinstalled the printer software. This did not change the symptoms. The printer is "deleted" only to the Printers collection -- not to the common dialog control, not to other applications and not to the system.

Also, not only the renaming program is failing. Other programs that use the Printers collection are failing -- even a simple one that does nothing other than list what is in the Printers collection.

Thanks,
Cassandra
 
Ok, then. You may want to download SP6 that is available here. But please read the info on the download page first. It may or may not change the symptoms you are getting.

William
Software Engineer
ICQ No. 56047340
 
Hi William:

I am holding off on the SP6 upgrade. I usually wait to see what problems others have with SPs. The download page's description of the fixes have little, if any impact, on the issues that I work with.

The other issue is that the problem exists with code that previously worked flawlessly. The printer renaming code has obviously made some changes somewhere (either in Windows or VB); I just need to find where and correct the changes.

Cassandra
 
Is this your code? If it is you may want to post it here (under a new thread) so that members can see it and offer possible solutions. If it's not your code or you do not have access to it then all I can suggest is that you contact the vendor yourself.

Sorry, not much but the obvious, but it's all I can suggest for the moment.


William
Software Engineer
ICQ No. 56047340
 
Hi:

The following is the printer renaming code.

Code:
Public Function SetPrinterNameA2(ByVal strOldPrinterName As String, ByVal strPrinterName As String) As Boolean
    
    Dim I As Integer
    Dim lngDummy As Long
    Dim blnBailOut As Boolean
    Dim hPrinter As Long
    Dim udtPD As PRINTER_DEFAULTS
    Dim udtPrinterInfo As PRINTER_INFO_2
    Dim udtDM As DEVMODE
    Dim lngBytesNeeded As Long
    Dim lngRet As Long
    Dim bytBuffer() As Byte
    
    SetPrinterNameA2 = True
    udtPrinterInfo.pDevMode = VarPtr(udtDM)

'(1) Open printer handle . . .
    udtPD.DesiredAccess = PRINTER_ALL_ACCESS
    lngRet = OpenPrinter(strOldPrinterName, hPrinter, udtPD)
    If (lngRet = 0) Or (hPrinter = 0) Then Exit Function

'(2) The first GetPrinter tells you how big the buffer should be in order to hold all of
'   PRINTER_INFO_2. Note that this should fail with ERROR_INSUFFICIENT_BUFFER. If
'   GetPrinter fails for any other reason or lngBytesNeeded isn't set for some reason,
'   then there is a problem . . .
    Err.Clear
    lngBytesNeeded = 0&
    lngRet = GetPrinter(hPrinter, 2, 0, 0, lngBytesNeeded)      ' okay
    If (lngBytesNeeded = 0) Then
        ClosePrinter hPrinter
        Exit Function
    End If
    On Error GoTo SetPrinterNameA_Error

'(3) The second GetPrinter fills in all the current settings, so all you need to do is
'   modify what you're interested in . . .
    ReDim bytBuffer(lngBytesNeeded) As Byte
    lngRet = GetPrinter(hPrinter, 2, bytBuffer(0), lngBytesNeeded, lngBytesNeeded)
    If lngRet = 0 Then
        ClosePrinter hPrinter
        Exit Function
    End If
    Call CopyMemory(udtPrinterInfo, bytBuffer(0), Len(udtPrinterInfo))

'(4) If GetPrinter did not return DeviceMode structure, then use a more direct method.
    If udtPrinterInfo.pDevMode = 0 Then
'    If Not udtPD.pDevMode Then
        lngBytesNeeded = DocumentProperties(0, hPrinter, strOldPrinterName, 0, 0, 0)
        If (lngBytesNeeded <= 0) Then
            ClosePrinter hPrinter
            Exit Function
        End If
        ReDim bytBuffer(lngBytesNeeded) As Byte
'(5)
        lngRet = DocumentProperties(0, hPrinter, strOldPrinterName, VarPtr(bytBuffer(0)), VarPtr(bytBuffer(0)), DM_OUT_BUFFER)
        If (lngRet <> IDOK) Then ' lost check
            ClosePrinter hPrinter
            Exit Function
        End If
        
        Call CopyMemory(udtDM, bytBuffer(0), Len(udtDM))
'(6)
        udtPrinterInfo.pDevMode = VarPtr(udtDM)
    End If


'(7) Specify exactly what we are attempting to change . . .
    With udtPrinterInfo
        strPrinterName = strPrinterName & Chr(0)

        ReDim bytBuffer(Len(strPrinterName)) As Byte
        Dim II As Integer
        For II = 1 To Len(strPrinterName)
            bytBuffer(II - 1) = Asc(Mid(strPrinterName, II, 1))
        Next II
        .pPrinterName = VarPtr(bytBuffer(0))
        .pPrinterName = VarPtr(strPrinterName)
'(8)
        .pSecurityDescriptor = 0
    End With


'(9) make sure the driver-dependent part of devmode is updated . . .
     lngRet = DocumentProperties(0, hPrinter, strOldPrinterName, udtPrinterInfo.pDevMode, udtPrinterInfo.pDevMode, DM_IN_BUFFER Or DM_OUT_BUFFER)
     If (lngRet <> IDOK) Then
        ClosePrinter hPrinter
        Exit Function
    End If

'(10) update printer information . . .
    ReDim bytBuffer(Len(udtPrinterInfo)) As Byte
    Call CopyMemory(bytBuffer(0), udtPrinterInfo, Len(udtPrinterInfo))
    
    lngRet = SetPrinter(hPrinter, 2, bytBuffer(0), 0)
    If (lngRet = 0) Then
        ClosePrinter hPrinter
        Exit Function
    End If


'(11) Tell other apps that there was a change . . .
    Call SendMessageTimeout(HWND_BROADCAST, WM_DEVMODECHANGE, 0, strOldPrinterName, SMTO_NORMAL, 1000, 0)
    If hPrinter Then ClosePrinter hPrinter
    
    SetPrinterNameA2 = False
    ClosePrinter hPrinter
    Exit Function

SetPrinterNameA_Error:
    Debug.Print "mdlPrinterAccess : SetPrinterNameA :: " & Err.Number & " : " & Err.Description
    Err.Clear
    On Error GoTo 0
    If hPrinter Then ClosePrinter hPrinter
    For I = 1 To 20
        DoEvents
    Next I
    SetPrinterNameA2 = True

End Function

The following are the API function declarations:

Code:
Public Declare Function ClosePrinter Lib "winspool.drv" _
    (ByVal hPrinter As Long) As Long
'

Public Declare Function GetPrinter Lib "winspool.drv" _
    Alias "GetPrinterA" ( _
    ByVal hPrinter As Long, _
    ByVal Level As Long, _
    pPrinter As Byte, _
    ByVal cbBuf As Long, _
    pcbNeeded As Long _
    ) As Long
'

Public Declare Function OpenPrinter Lib "winspool.drv" _
    Alias "OpenPrinterA" ( _
    ByVal pPrinterName As String, _
    phPrinter As Long, _
    pDefault As PRINTER_DEFAULTS _
    ) As Long
'

Public Declare Function SetPrinter Lib "winspool.drv" _
    Alias "SetPrinterA" ( _
    ByVal hPrinter As Long, _
    ByVal Level As Long, _
    pPrinter As Byte, _
    ByVal Command As Long _
    ) As Long
'

Public Declare Sub CopyMemory Lib "kernel32" _
    Alias "RtlMoveMemory" ( _
    Destination As Any, _
    Source As Any, _
    ByVal Length As Long)
'

Public Declare Function SendMessageTimeout Lib "user32" _
    Alias "SendMessageTimeoutA" ( _
    ByVal hwnd As Long, _
    ByVal msg As Long, _
    ByVal wParam As Long, _
    ByVal lParam As String, _
    ByVal fuFlags As Long, _
    ByVal uTimeout As Long, _
    lpdwResult As Long _
    ) As Long

Any required API constants are as per Win32API.txt.

Cassandra
 
Excuse my (VB) ignorance but what does this VarPtr() Function do?




William
Software Engineer
ICQ No. 56047340
 
It's OK, worked it out. An "undocumented" feature.


William
Software Engineer
ICQ No. 56047340
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top