Getting the WIA scripting automation to remember scanner settings in C#

This is a bit of a hack, but maybe it will help someone in the future when they discover that the Windows XP Scanner and Camera wizard doesn't remember the previous settings in subsequent scans. Very frustrating.

Get the Windows Image Acquisition Automation Library v2.0 and install wiaaut.dll and download the WindowFinder class from http://www.thecodeproject.com/csharp/InteropSignon.asp to simplify working with the dialogs and sending window messages to the controls on the dialog.

Add the "Microsoft Windows Image Acquisition Library v2.0" COM reference to your project.

The simplest code to select a scanner and connect to it is as follows, where WIACommonDialog is an instance of the CommonDialogClass.

Device d = this.WIACommonDialog.ShowSelectDevice(WiaDeviceType.ScannerDeviceType,true,false);

We need the name of the device to capture the window handle later

string deviceName = "";
foreach (Property property in d.Properties)
{
    
if (property.Name == "Name")
    {
        deviceName = ((IProperty)property).get_Value().ToString();
    }
}

To get items from the scanner we use the following code

Items items = WIACommonDialog.ShowSelectItems(d);

foreach (Item item in items)
{
    ImageFile imageFile = (ImageFile)WIACommonDialog.ShowTransfer(item);
    Vector vector = imageFile.FileData;                    
    
byte[] bin = (byte[])vector.get_BinaryData();
    
//do something with the image data
}

Which will show a dialog like this

If we change the radio button to Custom Settings then it remembers the settings, but by default it always goes back to Color picture. Just before ShowSelectItems we start a new thread using this function and assign _dialogTitle = "Scan using " + deviceName;

public void WaitForWindow()
{
    
try
    
{
        WindowFinder scanWindowFinder = 
new WindowFinder();
        IntPtr wizardHandle = IntPtr.Zero;

        
while (wizardHandle == IntPtr.Zero)
        {
            Thread.Sleep(50);
            wizardHandle = scanWindowFinder.Find("#32770",_dialogTitle);                    
        }
        scanWindowFinder.UseWindow(wizardHandle);

        WindowFinder customButton = 
new WindowFinder();
        IntPtr buttonPtr = IntPtr.Zero;

        buttonPtr = customButton.Find(wizardHandle,"Button","&Custom Settings");
        customButton.UseWindow(buttonPtr);
        customButton.ClickButton();                
    }
    
catch (ThreadAbortException)
    {
        
//swallow the exception
    
}
}

The values are obtained using SPY++

Published Tuesday, March 15, 2005 5:52 PM by colin
Filed under:

Comments

# re: Getting the WIA scripting automation to remember scanner settings in C#

Hi,

I am trying to control ADF scanner (HP Scanjet 6300) using WIA and VB6. I can get it to scan once but when the next document loads I get an error. The code is below. Are you willing to do some paid work to troubleshoot this?

Regards,

Lee
lwright@intercoast.com.au

Dim WiaObj As New WIA.CommonDialog
Dim WiaItm As WIA.Item
Dim WiaImg As New WIA.ImageFile
Dim wiadev As WIA.Device

'wiadev = "{6BDD1FC6-810F-11D0-BEC7-08002BE2092F}\0003"

If wiadev Is Nothing Then
' WiaDev is defined globally
Set wiadev = WiaObj.ShowSelectDevice(WIA.WiaDeviceType.ScannerDeviceType, True, False)
End If

Dim itm As WIA.Item
Dim ItmProp As WIA.Property
For Each itm In wiadev.Items
For Each ItmProp In itm.Properties
Select Case ItmProp.PropertyID
Case 6147: ' Horizontal Resolution
ItmProp.Value = 150
Case 6148: ' Vertical Resolution
ItmProp.Value = 150
Case 6151: ' Horizontal Extent (Scanning Area)
ItmProp.Value = 1275
Case 6152: ' Vertical Extent (Scanning Area)
ItmProp.Value = 550
Case 6149: ' Horizontal Starting Position (Scanning Area)
ItmProp.Value = 0
Case 6150: ' Vertical Starting Position (Scanning Area)
ItmProp.Value = 0
Case 6146: ' Current Intent
ItmProp.Value = 4
' Text or Line Art
End Select
NextNextWiaImg = WiaObj.ShowTransfer(itm)
Next







Wednesday, June 15, 2005 1:26 PM by Lee Wright

# re: Getting the WIA scripting automation to remember scanner settings in C#

try this

Dim items As WIA.items
Set items = WiaObj.ShowSelectItems(wiadev)
For Each itm In items

instead of this line

For Each itm In wiadev.Items

Wednesday, June 15, 2005 3:15 PM by Colin

# re: Getting the WIA scripting automation to remember scanner settings in C#

Thanks Colin,

I still get error: "Object does not support this property or method" when it gets to this line:

NextNextWiaImg = WiaObj.ShowTransfer(itm)

Appreciate any help.

Regards,


Lee.

Thursday, June 16, 2005 12:07 AM by Lee Wright

# re: Getting the WIA scripting automation to remember scanner settings in C#

That should be

set NextNextWiaImg = WiaObj.ShowTransfer(itm)

because it returns an object.

Thursday, June 16, 2005 10:08 AM by Colin

# Dog Leak

Monday, September 19, 2005 4:52 PM by TrackBack

# re: Getting the WIA scripting automation to remember scanner settings in C#

I downloaded Windows Image Acquisition Library v2.0 from the MS website.

I used it with MS C# 2005.





Device d = CamInitDialog.ShowSelectDevice(WiaDeviceType.UnspecifiedDeviceType, true,false);

...

WIA.Item RawPic = d.ExecuteCommand(CommandID.wiaCommandTakePicture);




However, the image acquisition take way too much time (6-10 seconds). When I use the same webcam with any other application (or from My Computer), it takes less than a second to take 1 image.

Does anybody know whats wrong with it?

Sudip

Sunday, April 16, 2006 4:41 AM by Sudip Shrestha

# re: Getting the WIA scripting automation to remember scanner settings in C#

Hi

I have been using this example not only to remember settings but also to (hopefully) bypass the common WIA UI as well.

In the WaitForWindow() function I have added the following code at the end

WindowFinder customButton2 = new WindowFinder();
IntPtr buttonPtr2 = IntPtr.Zero;

buttonPtr2 = customButton2.Find(wizardHandle,"Button","&Scan");
customButton2.UseWindow(buttonPtr2);
customButton2.ClickButton();

The idea is that when the common UI appears the 'Custom settings' radio is clicked and then the 'Scan' button is clicked.

The problem I have is that I get an error message that the scan button is unable to be clicked/found. (I will get the error message tomorrow and post it as I don't have it on me at the moment).

Does anyone know how to fix this problem?

My other problem is that I wish the program to remember what scanner was selected and us that in future instead of being prompted to select the scanner every time. Does anyone know how to do this?

Thanks.

Tuesday, April 18, 2006 10:38 AM by Bob

# re: Getting the WIA scripting automation to remember scanner settings in C#

Bob: I had problems with clicking some of the buttons too. I never found a solution, although I didn't try very hard at the time. You could try putting a short delay before the button is clicked as the buttons may be disabled when the dialog is displayed initially.

Tuesday, April 18, 2006 12:23 PM by colin

# re: Getting the WIA scripting automation to remember scanner settings in C#

Colin: Thanks for the quick reply. I have not had time to look into it yet, but will do before the weekend.

And if anybody is interested I found out the answer to my second question about remembering what scanner had been chosen. Take a look at http://msdn.microsoft.com/coding4fun/someassemblyrequired/lookatme/default.aspx

Wednesday, April 19, 2006 10:07 AM by Bob

# re: Getting the WIA scripting automation to remember scanner settings in C#

I've founded your code very interesting because I'm trying to bypass the WIA UI. But I'm having some problems...

That's my code:

<...>

CommonDialogClass WIACommonDialog = new CommonDialogClass();
_dialogTitle = "Scan using  " + deviceName;
Thread t1 = new Thread(new ThreadStart(WaitForWindow));
t1.Start();

<...>

And I'm obtaining a "System.Threading.ThreadAbortException" every time the "WaitForWindow" function is called, I've commented all, just leaving a simple statement (int dummy = 0) and still happens. Any idea what's going on? It's also strange, because the try-catch clause doens't catch this  exception...

By the way, it's quite strange that the WIA API doesn't give support to set those properties (color, size, etc...) to the image that's gonna be scanned.

Thanks in advance.

Friday, April 28, 2006 12:32 PM by mcfarlane

# re: Getting the WIA scripting automation to remember scanner settings in C#

mcfarlane:

Here is some code that I use in conjunction with the WaitForWindow function above:
//------Code starts----------
Thread finderThread = new Thread(new ThreadStart(WaitForWindow));

finderThread.Start();
while (!finderThread.IsAlive)Thread.Sleep(1);
Items items = WIACommonDialog.ShowSelectItems(device);

if (finderThread.IsAlive)
{
finderThread.Abort();
finderThread.Join();
}
//------Code Ends----------

The only reason for the threadabort exception is because I abort the thread explicitly when it's no longer needed. There may be cleaner ways to end the thread but the above code does work.

The WIA API does allow you to set the properties, but we are not using the WIA API directly here. This is a scripting API that has been provided to simplify working with WIA devices.

Friday, April 28, 2006 3:54 PM by colin

# re: Getting the WIA scripting automation to remember scanner settings in C#

Colin,

I'm a bit lost.

You say that the WIA API does allow to set the image properties, but I've been unable to find how. Do you mean that the WIA Automation Library doesn't provide this support?

How can I use the WIA API and not the WIA Automation Library? Does it also provide a COM interface?

Thanks in advance

Tuesday, May 02, 2006 11:39 AM by mcfarlane

# re: Getting the WIA scripting automation to remember scanner settings in C#

Colin,

Thanks for your help previously.   I am working on this project again.   I used your code as suggested (see below).  There are a couple of problems:

(1) It prompts me for settings like, document feeder or flatbed.   I just want to set this in code and have no user interaction.

(2) When it runs out of paper it gives a message: -2145320957 The user requested a scan and there are no documents left in the document feeder.    How do I trap this condition and exit the program?

Appreciate any help.   Again if you want to do some paid consulting let me know.

Dim WiaObj As New WIA.CommonDialog
Dim WiaItm As WIA.Item
Dim WiaImg As New WIA.ImageFile
Dim wiadev As WIA.Device

'wiadev = "{6BDD1FC6-810F-11D0-BEC7-08002BE2092F}\0003"

If wiadev Is Nothing Then
' WiaDev is defined globally
Set wiadev = WiaObj.ShowSelectDevice(WIA.WiaDeviceType.ScannerDeviceType, True, False)
End If

Dim itm As WIA.Item
Dim ItmProp As WIA.Property
Dim items As WIA.items
Set items = WiaObj.ShowSelectItems(wiadev)
For Each itm In items
   For Each ItmProp In itm.Properties
       Select Case ItmProp.PropertyID
       Case 6147:   ' Horizontal Resolution
                   ItmProp.Value = 150
       Case 6148:   ' Vertical Resolution
                   ItmProp.Value = 150
       Case 6151:   ' Horizontal Extent (Scanning Area)
                   ItmProp.Value = 1275
       Case 6152:   ' Vertical Extent (Scanning Area)
                   ItmProp.Value = 550
       Case 6149:   ' Horizontal Starting Position (Scanning Area)
                   ItmProp.Value = 0
       Case 6150:   ' Vertical Starting Position (Scanning Area)
                   ItmProp.Value = 0
       Case 6146:   ' Current Intent
                   ItmProp.Value = 4
                   ' Text or Line Art
       End Select
    Next
WiaImg = WiaObj.ShowTransfer(itm)

Next

Thursday, June 08, 2006 1:30 AM by lwright