使用WIA和VB自动扫描同一台计算机上的多个扫描仪

5

你好,Stack Overflow!

我是编程的终极新手。我有一些php和vba方面的经验,在需要的时候会自己编写一些脚本,特别是在Excel中。

最近,在工作项目中,我需要能够从连接到同一台计算机的多个扫描仪(起始使用两个)中自动扫描(例如每2分钟扫描一次)。 我决定将这个项目作为我了解Visual Basic的起点。 于是,我安装了Visual Studio Express 2010,并开始编写我的脚本,试图找到可以帮助我的代码片段。我发现WIA可以帮助解决这个问题(Twain也可以,但对于我这样的初学者来说,它似乎更加晦涩)。

无论如何,我最终得出了一个应用程序,它能够在连接了一个扫描仪时以设置的间隔自动扫描。当连接超过一个扫描仪时,问题就出现了。第一次扫描正确进行(扫描仪1扫描,然后扫描仪2扫描),但是在第二次扫描应该开始时,什么都没有发生,扫描仪变得不可访问(繁忙)。 我想也许我忘记了“释放”或“断开”上一个使用的扫描仪。或者,扫描仪的缓冲器中可能还有一些东西?

我已经卡在这个问题上3天了,不知道怎样才能使它工作。

以下是扫描函数:(我没有粘贴其余部分,因为那是用户界面和文件夹管理)

 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
    If Me.FileExt.SelectedItem = "TIF" Then fileformat = wiaFormatTIFF
    If Me.FileExt.SelectedItem = "JPEG" Then fileformat = wiaFormatJPEG
    If Me.FileExt.SelectedItem = "BMP" Then fileformat = wiaFormatBMP
    If Me.FileExt.SelectedItem = "PNG" Then fileformat = wiaFormatPNG
    If Me.FileExt.SelectedItem = "GIF" Then fileformat = wiaFormatGIF

    '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...

            'startpoint to calculate how long it is to scan
            Dim ScanStart = DateAndTime.Second(Now) + (DateAndTime.Minute(Now) * 60) + (DateAndTime.Hour(Now) * 3600)


            '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)

                    'last scan
                    Form2.LastFileLabel.Text = "\Scanner" & j & "\S" & j & "_" & Me.FilePrefix.Text & Me.CurrFileIndex & "." & Me.FileExt.SelectedItem
                    Form2.LastScanLabel.Text = Now

                Catch ex As Exception
                    MsgBox(ex.Message)
                Finally

                    Scanner = Nothing
                End Try
            End If

            'End time for the scan
            Dim ScanEnd = DateAndTime.Second(Now) + (DateAndTime.Minute(Now) * 60) + (DateAndTime.Hour(Now) * 3600)

            'log
            Log(Me.logfilename, Now & " | Scanner #" & j & " | Scanned " & targetdir & " | duration: " & (ScanEnd - ScanStart))

            j = j + 1



    Next
    DeviceManager1 = Nothing


    Me.CurrFileIndex = Me.CurrFileIndex + 1

    Me.ScanCount = Me.ScanCount + 1
    Me.NextScan = DateAdd("n", Me.IntervalBox.Value, Now)

    Form2.ScanCountLabel.Text = Me.ScanCount
    Form2.NextScanLabel.Text = Me.NextScan
    Form2.CurrentActionLabel.Text = "Waiting..."

    'Increment next file index and update in config file
    Me.FileIndexBox.Value = Me.CurrFileIndex
    SaveCfg()

End Sub

请谅解,我意识到这段代码对于有很多糟糕事情的编程专家来说可能是一场噩梦,但这实际上是我的第一个VB程序,并且我渴望学习。
基本上,程序的其余部分是一个表单,我在其中输入扫描的目标目录,文件名,分辨率等,当我点击“开始扫描”时, - 首先运行scannerloop one - 启动“scantimer”,每次滴答声都会启动scannerloop。
正如我所说,它可以使用1个扫描仪完美运行(文件按预期创建,日志文件更新等),但是一旦有2个扫描仪,只有第一个扫描起作用,然后当扫描仪#1应该开始扫描时,它不会并且扫描仪#2的LED开始闪烁(好像正在扫描,但实际上没有扫描)。
希望有人能够帮助我。
提前致谢。
文森特
更新- 我尝试过的东西可能很有趣: 我刚刚尝试添加一个循环,以便使其从两个扫描仪多次扫描(因此,与计时器和程序的其余部分无关)。
Dim DeviceManager1 = CreateObject("WIA.DeviceManager")   'wia device manager
 For k = 1 To 3
            Dim j As String = 1
            For i = 1 To DeviceManager1.DeviceInfos.Count 'loop through all devices
[...]
          Next i
        Next k
        DeviceManager1 = Nothing

这表明第一次循环有效(每个扫描仪都会扫描一次),但此后扫描仪不会再次扫描并开始闪烁,因此问题基本相同。 我还尝试在新循环中包含Devicemanager声明:

 For k = 1 To 3 
Dim DeviceManager1 = CreateObject("WIA.DeviceManager")   'wia device manager
            Dim j As String = 1
            For i = 1 To DeviceManager1.DeviceInfos.Count 'loop through all devices
[...]
          Next i
        DeviceManager1 = Nothing
        Next k

但是它并没有改变任何事情。

接下来我做的事情是记录循环中的事件,以便我可以知道事情停止的确切位置:

Dim DeviceManager1 = CreateObject("WIA.DeviceManager") 'wia 设备管理器 Dim j As String = 1

For i = 1 To DeviceManager1.DeviceInfos.Count 'loop through all devices
    If DeviceManager1.DeviceInfos(i).Type = 1 Then  'Select only scanners, not webcams etc...

        'startpoint to calculate how long it is to scan
        Dim ScanStart = DateAndTime.Second(Now) + (DateAndTime.Minute(Now) * 60) + (DateAndTime.Hour(Now) * 3600)


        '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

                'log
                Log(Me.logfilename, Now & " | Scanner #" & j & " | Img initialized")

                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

                'log
                Log(Me.logfilename, Now & " | Scanner #" & j & " | properties initialized")

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

                'log
                Log(Me.logfilename, Now & " | Scanner #" & j & " |Transfer done")

                'kill previous file if exists to avoid errors
                If System.IO.File.Exists(targetdir) = True Then
                    Kill(targetdir)
                    'log
                    Log(Me.logfilename, Now & " | Scanner #" & j & " | deleted existing " & targetdir)

                End If

                Img.SaveFile(targetdir)
                'log
                Log(Me.logfilename, Now & " | Scanner #" & j & " | saved " & targetdir)

                'last scan
                Form2.LastFileLabel.Text = "\Scanner" & j & "\S" & j & "_" & Me.FilePrefix.Text & Me.CurrFileIndex & "." & Me.FileExt.SelectedItem
                Form2.LastScanLabel.Text = Now

            Catch ex As Exception
                MsgBox(ex.Message)
            Finally

                Scanner = Nothing
            End Try
        End If

        'End time for the scan
        Dim ScanEnd = DateAndTime.Second(Now) + (DateAndTime.Minute(Now) * 60) + (DateAndTime.Hour(Now) * 3600)

        'log
        Log(Me.logfilename, Now & " | Scanner #" & j & " | Scanned " & targetdir & " | duration: " & (ScanEnd - ScanStart))

        j = j + 1

    End If

Next i

下面是生成的日志文件:

Scan starts 29/11/2012 9:24:31 AM | Interval :Start scanning with 5 min | Res:100 DPI | 
29/11/2012 9:24:31 AM | Scanner #1 | Img initialized
29/11/2012 9:24:31 AM | Scanner #1 | properties initialized
29/11/2012 9:24:49 AM | Scanner #1 |Transfer done
29/11/2012 9:24:49 AM | Scanner #1 | saved C:\__2\scans\Scanner1\S1_img_1.TIF
29/11/2012 9:24:49 AM | Scanner #1 | Scanned C:\__2\scans\Scanner1\S1_img_1.TIF | duration: 18
29/11/2012 9:24:49 AM | Scanner #2 | Img initialized
29/11/2012 9:24:49 AM | Scanner #2 | properties initialized
29/11/2012 9:25:08 AM | Scanner #2 |Transfer done
29/11/2012 9:25:08 AM | Scanner #2 | saved C:\__2\scans\Scanner2\S2_img_1.TIF
29/11/2012 9:25:08 AM | Scanner #2 | Scanned C:\__2\scans\Scanner2\S2_img_1.TIF | duration: 19
29/11/2012 9:25:08 AM | Scanner #1 | Img initialized
29/11/2012 9:25:08 AM | Scanner #1 | properties initialized

似乎问题出在这一行代码:
Img = Scanner.Items(1).Transfer(fileformat) 'scans the image.

看起来WIA很高兴从扫描仪1切换到2,但拒绝在下一轮返回扫描仪1。另外,我应该明确,当第二次扫描应该发生时,扫描仪#2闪烁(而不是1,这让我感到惊讶)。 是否可能选择了扫描仪#2作为“默认扫描仪”或类似的东西?如果是这样,是否有办法恢复它? 感谢您的帮助。

我不确定,但也许在http://codereview.stackexchange.com/上发布您的代码会更好。 - Nianios
1个回答

0

这段代码用于扫描图像:"不要忘记将wiaaut.DLL从windows\sys32添加到解决方案引用中。"首先检查扫描设备是否已连接。

Dim tempfile As String
Dim mydevice As WIA.Device
Dim item As WIA.Item
Dim imfile As WIA.ImageFile
Dim Commondialog1 As WIA.CommonDialog
sub check()
  On Error Resume Next
    Commondialog1 = New WIA.CommonDialog
    mydevice = Commondialog1.ShowSelectDevice
    MsgBox(mydevice.Type)

  On Error GoTo Err_btnTakePicture_click

end sub
'then connect to scanner

sub scan()
    'put the path and name for the location of your temp file here.
    tempfile = ("d:\filename.jpg")

    'the next 4 lines deletes the old temp file if it exists
    Dim filesystemobject = CreateObject("Scripting.FileSystemObject")
    If filesystemobject.fileExists(tempfile) Then
        Kill(tempfile)
    End If

    'the next two lines set up the configuration
    Dim Commondialog1 As New WIA.CommonDialog
    mydevice = Commondialog1.ShowSelectDevice

    Dim wiaFormatJPEG As String = "{B96B3CAE-0728-11D3-9D7B-0000F81EF32E}"

    item = mydevice.Items(1)


    imfile = DirectCast(Commondialog1.ShowTransfer(item, wiaFormatJPEG, False), WIA.ImageFile)

    'this line saves the picture to a specified file
    imfile.SaveFile(tempfile)


    MsgBox("Picture taken")
    PictureBox1.ImageLocation = tempfile

  Exit_btnTakePicture_click:
    mydevice = Nothing
    item = Nothing
    Exit Sub

  Err_btnTakePicture_click:
    MsgBox(Err.Description, vbOKOnly + vbCritical, "Error Taking Picture")
    Resume Exit_btnTakePicture_click
   end sub

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接