I would like to give back to the community here by posting some code on how to use WIA for an ADF scanner.

The lack of C# examples makes it difficult for the average coder to figure out. Firstly, please understand that I am relatively new to csharp and this is my first attempt at coding with WIA. I am sure there are parts that could be done better and I'm still not convinced I'm doing it the correct way, however it works which is better than any other example I could find.

An Important note for those who are not aware: WIA only works on windows ME, XP and Vista. Vista uses a newer version of WIA and I have not tested this code on Vista yet. I have only tested with XP. TWAIN is more compatible with different operating systems.

Please note that if you are planning on using WIA for a digital camera, then the example over here - http://www.codeproject.com/dotnet/wi...tingdotnet.asp - should be sufficient enough.

Unfortunately when using a flatbed scanner with an ADF (Auto Document Feeder) tray the example does not work. My project required using an HP scanjet 5590 scanner. The users would be scanning up to 100 pages at a time.

Firstly, you will need the WIA Automation Library 2.0 to be added as a reference in your project. This library can be downloaded from Microsoft's website. You are looking for wiaaut.dll.

Once you've got the library installed and added as a reference in your project you may need the following variables in your class:

string DeviceID;

const string wiaFormatBMP ="{B96B3CAB-0728-11D3-9D7B-0000F81EF32E}";		
const string wiaFormatPNG ="{B96B3CAF-0728-11D3-9D7B-0000F81EF32E}";
const string wiaFormatGIF ="{B96B3CB0-0728-11D3-9D7B-0000F81EF32E}";
const string wiaFormatJPEG ="{B96B3CAE-0728-11D3-9D7B-0000F81EF32E}";
const string wiaFormatTIFF ="{B96B3CB1-0728-11D3-9D7B-0000F81EF32E}";
These are probably in an enum somewhere in the class as well if you look hard enough. Please take note of the DeviceID string. I initially coded my scanning to select which scanning device on one button's event and then scan on another button's event. To be able to determine which scanner was selected you will need to remember the DeviceID.

The following code is part of some code that gave me a breakthrough in how to determine if there is another page waiting to be scanned in the ADF tray. It is required in order for the main code to work.

		public const uint FEEDER = 0x00000001;
		public const uint FLATBED = 0x00000002;

		public const uint FEED_READY = 0x00000001;

		public const uint WIA_RESERVED_FOR_NEW_PROPS = 1024;
		public const uint WIA_DIP_FIRST = 2;
		// Scanner only device properties (DPS)
		public const uint WIA_DPS_FIRST    =                      WIA_DPC_FIRST + WIA_RESERVED_FOR_NEW_PROPS;
		public const uint WIA_DPS_DOCUMENT_HANDLING_STATUS  =     WIA_DPS_FIRST + 13;
		public const uint WIA_DPS_DOCUMENT_HANDLING_SELECT  =     WIA_DPS_FIRST + 14;

		public const uint BASE_VAL_WIA_ERROR = 0x80210000;
		public const uint WIA_ERROR_PAPER_EMPTY  = BASE_VAL_WIA_ERROR + 3;
Now comes the most important part. The actual scanning. Most of it should be commented sufficiently enough.

void ADFScan()
			//Choose Scanner
			CommonDialogClass class1 = new CommonDialogClass();
			Device d = class1.ShowSelectDevice(WiaDeviceType.UnspecifiedDeviceType, true,false);
			if (d != null)
				this.DeviceID = d.DeviceID;
				//no scanner chosen
			WIA.CommonDialog WiaCommonDialog = new CommonDialogClass();
			bool hasMorePages = true;
			int x = 0;
			int numPages = 0;
			while (hasMorePages)
				//Create DeviceManager
				DeviceManager manager = new DeviceManagerClass();
				Device WiaDev = null;
				foreach (DeviceInfo info in manager.DeviceInfos)
					if (info.DeviceID == this.DeviceID)
						WIA.Properties infoprop = null;
						infoprop = info.Properties;
						//connect to scanner
						WiaDev = info.Connect();

				//Start Scan
				WIA.ImageFile img = null;
				WIA.Item Item = WiaDev.Items[1] as WIA.Item;

					img = (ImageFile)WiaCommonDialog.ShowTransfer(Item,wiaFormatJPEG,false);

					//process image:
					//one would do image processing here

					//Save to file
					string varImageFileName = "c:\\test" + x.ToString() + ".jpg";
					if (File.Exists(varImageFileName))
						//file exists, delete it
					img = null;
				catch (Exception ex)
					MessageBox.Show("Error: " + ex.Message);
					Item = null;
					//determine if there are any more pages waiting
					Property documentHandlingSelect = null;
					Property documentHandlingStatus = null;
					foreach (Property prop in WiaDev.Properties)
							documentHandlingSelect = prop;
							documentHandlingStatus = prop;

					hasMorePages = false; //assume there are no more pages
					if (documentHandlingSelect != null)
						//may not exist on flatbed scanner but required for feeder
						//check for document feeder
						if ((Convert.ToUInt32(documentHandlingSelect.get_Value()) & WIA_DPS_DOCUMENT_HANDLING_SELECT.FEEDER) != 0)
							hasMorePages = ((Convert.ToUInt32(documentHandlingStatus.get_Value()) & WIA_DPS_DOCUMENT_HANDLING_STATUS.FEED_READY) != 0);
On the HP scanjet I'm using if it does not find any pages in the ADF then it does a single scan from the glass tray. This still works. In the example above I am just saving the images to the root of c: drive and overwriting any existing images with the same name.

In the comments where I've put "Image Processing" you can do you image manipulation like cropping, resizing, rotating, etc. before saving the image. There are supposedly built in functions to do this in the WIA automation library but I have been unsuccessful in getting them to work. I am instead using the multitude of image editing examples available on the net to do all those things.

The only thing that concerns me with this code is that on every loop it reconnects to the scanner. I would have thought the logical thing would be to connect once and then tell it to scan another page. As much as I tried I could not get that to work. In the end this was the only way that seemed to work correctly and I have not had any issues with it.

I hope this code helps someone