Hello !

I'm the ultimate beginner in programming. I have some experience in php and vba, doing my own scripts as I need them, especially in excel.

Recently, for a project at works, I need to be able to scan AUTOMATICALLY (say every 2 minutes) from multiple scanners (say 2 for starters) both connected to the same computer.
I decided to use this project as a start point for me to get a feeling of Visual Basic.
So here we go, I installed visual studio express 2010 and started writing my script trying to find here and there bits of codes that could help me. I found that WIA could help with that (Twain could as well but it seems much more obscure to the newbie I am)

Anyway, I finally came up with an app that is able to automatically scan at the set interval when only one scanner is connected. The trouble arrives when I connect more than one scanner. then, the first scan occurs correctly (Scanner 1 scans, then scanner 2 scans), but when the second scan is supposed to start, nothing happens and the scanners become inaccessible (busy).
I though maybe I forgot to "release" or "disconnect" the last scanner used. Or maybe, something remains in the scanner's buffer memory ?

I have been stuck on this issue for the last 3 days and don't know how to make it work.

here is the function that scans : (i don't paste the rest as it is the UI and folder management)

 Public Sub scannerloop()

    'format constants
    Const wiaFormatBMP = "{B96B3CAB-0728-11D3-9D7B-0000F81EF32E}"
    Const wiaFormatPNG = "{B96B3CAF-0728-11D3-9D7B-0000F81EF32E}"
    Const wiaFormatGIF = "{B96B3CB0-0728-11D3-9D7B-0000F81EF32E}"
    Const wiaFormatJPEG = "{B96B3CAE-0728-11D3-9D7B-0000F81EF32E}"
    Const wiaFormatTIFF = "{B96B3CB1-0728-11D3-9D7B-0000F81EF32E}"


    'file format
    Dim fileformat As String = wiaFormatTIFF


    'colors
    Dim colorcode As Integer
    If Me.Colorbox.SelectedItem = "Black and white" Then colorcode = 4
    If Me.Colorbox.SelectedItem = "Greyscale" Then colorcode = 2
    If Me.Colorbox.SelectedItem = "Colour" Then colorcode = 1

    'Resolution
    Dim dpi As Integer
    dpi = Me.dpiBox.SelectedItem
    Dim horizextent = dpi * 8.2
    Dim vertextent = dpi * 11.6


    Dim j As String = 1
    Dim DeviceManager1 = CreateObject("WIA.DeviceManager")   'wia device manager

    For i = 1 To DeviceManager1.DeviceInfos.Count 'loop through all devices

        If DeviceManager1.DeviceInfos(i).Type = 1 Then  'Select only scanners, not webcams etc...

            'Directory + file
            Dim targetdir = Me.ProjectFolderBox.Text & "\scans\Scanner" & j & "\S" & j & "_" & Me.FilePrefix.Text & Me.CurrFileIndex & "." & Me.FileExt.SelectedItem
            Form2.CurrentActionLabel.Text = "Scanning from scanner #" & j


            Dim Scanner As WIA.Device = DeviceManager1.DeviceInfos(i).connect


            If IsNothing(Scanner) Then
                Log(Me.logfilename, Now & " | Scanner #" & j & " not found")
            Else
                Try
                    Dim Img As WIA.ImageFile

                    With Scanner.Items(1)
                        .Properties("6146").Value = colorcode '4 is Black-white,gray is 2, color 1 (Color Intent)
                        .Properties("6147").Value = dpi  'dots per inch/horizontal
                        .Properties("6148").Value = dpi 'dots per inch/vertical
                        .Properties("6149").Value = 0 'x point where to start scan
                        .Properties("6150").Value = 0 'y-point where to start scan

                        'Following is A4 paper size. (Not 100% accurate because real A4 Ht errors)
                        .Properties("6151").Value = horizextent 'horizontal exent DPI x inches wide
                        .Properties("6152").Value = vertextent 'vertical extent DPI x inches tall
                        '  .Properties("4104").Value = 8 'bits per pixel

                    End With

                    'transfer image
                    Img = Scanner.Items(1).Transfer(fileformat) 'scans the image.

                    'kill previous file if exists to avoid errors
                    If System.IO.File.Exists(targetdir) = True Then
                        Kill(targetdir)
                    End If

                    Img.SaveFile(targetdir)


                Catch ex As Exception
                    MsgBox(ex.Message)
                Finally

                    Scanner = Nothing
                End Try
            End If

            j = j + 1

    Next
    DeviceManager1 = Nothing


    Me.CurrFileIndex = Me.CurrFileIndex + 1
    Me.ScanCount = Me.ScanCount + 1

End Sub

I've tried so many different things !
the other notable thing I've tried was, instead of declaring Dim Scanner As WIA.Device = DeviceManager1.DeviceInfos(i).connect inside the loop, I declared all devices once and for all (scanner(1), scanner(2) etc and then referred to them later. This doesn't solve the problem at all)

So basically, the rest of the program is a form where I enter the target directory for the scan, the filenames, resolution etc, and when I click on 'start scanning', it
- runs scannerloop one first time
- starts a 'scantimer' which launches scannerloop each time it ticks.

As I said, it works perfectly with 1 scanner (files created as expected, in time, logfile updated, etc) but as soon as I have 2 scanners, only the first scan works (for each scanner) and then, when scanner#1 is supposed to start scanning, it doesn't and the led of scanner#2 starts flashing (as if it was scanning, but it's not scanning)

It looks like WIA is happy to switch from scanner 1 to 2 but refuses to come back to scanner 1 for the next round. also, I should precise, when the second scan is supposed to occur, scanner #2 blinks (and not 1 which surprises me).
Is it possible that scanner#2 is selected as "default scanner" or something like that and if so, is there a way to revert that ?

One precision about timing that puzzles me :
IF I want both scanners to scan every minute or every two minutes : they each perform one scan and never manage to scan for the second time.
If i want them to scan every 5 minutes, the manage to perform the first two scans and then crash again for the third !. So far it seemed to be a timing problem, except that if I ask them to scan every hour, it's the same, they each scan twice, but never perform the third scan !
I doesn't make sense... It looks like I am allowed to have a max of 4 connections to devices, whatever happens

Please help me ! :s

Dani AI

Generated

Short diagnosis and focused fixes for 's setup (and building on ' "connect once" idea):

Common causes when two scanners work once and then become "busy" are: timer re-entrancy (a new scan starts before the prior transfer finished), COM Runtime Callable Wrapper (RCW) references left alive so the driver keeps the device open, and running WIA calls from an MTA/threadpool thread (WIA is apartment-threaded and behaves best on STA). Connecting once at startup can help only if every COM wrapper is explicitly released between cycles; otherwise the device handle stays held.

Concrete steps that reliably fix this class of problems:

  • Prevent overlapping runs: disable the scan timer (or use a boolean "isScanning" guard) at the start of the scan routine and always re-enable it in Finally so ticks never overlap an in-progress transfer.
  • Ensure WIA calls execute on an STA thread (use System.Windows.Forms.Timer on WinForms or run the work on a dedicated Thread with ApartmentState.STA). ThreadPool timers are MTA and can cause unpredictable behavior.
  • Explicitly release COM wrappers after each transfer: call Marshal.FinalReleaseComObject on the ImageFile, the Device, and the DeviceManager (in that order or device-first), set variables to Nothing, then force GC.Collect(); GC.WaitForPendingFinalizers() so RCWs are cleaned before the next cycle. Wrap the whole sequence in Try/Finally to guarantee release.

Example pattern (simplified):

ScanTimer.Enabled = False
Try
    Dim dm As New WIA.DeviceManager()
    For Each di As WIA.DeviceInfo In dm.DeviceInfos
        If di.Type = 1 Then
            Dim dev As WIA.Device = di.Connect()
            Dim img As WIA.ImageFile = dev.Items(1).Transfer(wiaFormatTIFF)
            img.SaveFile(targetPath)
            System.Runtime.InteropServices.Marshal.FinalReleaseComObject(img)
            System.Runtime.InteropServices.Marshal.FinalReleaseComObject(dev)
        End If
    Next
    System.Runtime.InteropServices.Marshal.FinalReleaseComObject(dm)
Finally
    ScanTimer.Enabled = True
    GC.Collect()
    GC.WaitForPendingFinalizers()
End Try

Additional diagnostics: run each scanner alone to confirm driver behavior, try different USB ports/hubs (some drivers don't like identical devices on the same controller), and inspect the WIA service if a device remains locked. If driver limitations persist, a vendor SDK or TWAIN driver that explicitly supports multiple devices may be needed.

Recommended Answers

All 2 Replies

I am not really experienced with WIA but...

I understood that the problema arises when connecting the second time. I this is true, then connecting only once may do the trick.

Did you tryed to connect to the scanners only once, at main program level, then pass (by ref) the device infos for the loop?

Hope this helps

Hi lolafuertes,
I indeed tried something similar : 1 loop that creates the connections once and for all and then referring to these connections later in a different loop.
Unfortunately, this doesn't work. (in that case, the scanners block even before performing the first scans)
Thanks

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.