Creating a scanning application in C#
By FoxLearn 2/17/2025 7:43:02 AM 92
WIA (also known as Windows Imaging Architecture) is a Microsoft API that allows communication between graphics software and imaging hardware, such as scanners, digital cameras, and video equipment.
Why WIA?
The WIA API simplifies device interaction for developers, manufacturers, and end users. It provides functionality such as:
- Listing available image acquisition devices (scanners).
- Managing multiple devices simultaneously.
- Querying device properties in a standardized manner.
- Acquiring data using high-performance transfer mechanisms.
- Maintaining image properties across transfers.
- Handling device status notifications and scan events.
Start by creating a new WinForms project in Visual Studio.
After that, you'll need to add the WIA COM component:
- In Visual Studio, right-click on your project in Solution Explorer.
- Select Add > Reference.
- In the opened window, select COM from the left-hand menu.
- Search for “Microsoft Windows Image Acquisition Library v2.0” and click OK.
Now, set the Embed Interop Types property of the WIA component to False:
- In Solution Explorer, select your project, then expand the References node.
- Find the WIA reference and in the Properties panel, set Embed Interop Types to False.
List Available Scanners
To list all connected scanners, you need to access the DeviceManager
object from WIA.
var deviceManager = new DeviceManager(); for (int i = 1; i <= deviceManager.DeviceInfos.Count; i++) { if (deviceManager.DeviceInfos[i].Type != WiaDeviceType.ScannerDeviceType) continue; Console.WriteLine(deviceManager.DeviceInfos[i].Properties["Name"].get_Value()); }
Scanning and Saving Images
Once you have listed the available scanners, you can select one to connect to.
var deviceManager = new DeviceManager(); DeviceInfo firstScannerAvailable = null; for (int i = 1; i <= deviceManager.DeviceInfos.Count; i++) { if (deviceManager.DeviceInfos[i].Type != WiaDeviceType.ScannerDeviceType) continue; firstScannerAvailable = deviceManager.DeviceInfos[i]; break; } var device = firstScannerAvailable.Connect(); var scannerItem = device.Items[1]; var imageFile = (ImageFile)scannerItem.Transfer(FormatID.wiaFormatJPEG); var path = @"C:\Users\<username>\Desktop\scan.jpeg"; if (File.Exists(path)) { File.Delete(path); } imageFile.SaveFile(path);
This code will connect to the first available scanner, scan the document, and save it as a JPEG on your desktop.
Adjust Scanner Properties
You can modify scanner settings such as resolution, brightness, contrast, and scan area before scanning.
private static void AdjustScannerSettings(IItem scannerItem, int resolutionDPI, int leftPixel, int topPixel, int widthPixels, int heightPixels, int brightness, int contrast, int colorMode) { SetWIAProperty(scannerItem.Properties, "6147", resolutionDPI); SetWIAProperty(scannerItem.Properties, "6148", resolutionDPI); SetWIAProperty(scannerItem.Properties, "6149", leftPixel); SetWIAProperty(scannerItem.Properties, "6150", topPixel); SetWIAProperty(scannerItem.Properties, "6151", widthPixels); SetWIAProperty(scannerItem.Properties, "6152", heightPixels); SetWIAProperty(scannerItem.Properties, "6154", brightness); SetWIAProperty(scannerItem.Properties, "6155", contrast); SetWIAProperty(scannerItem.Properties, "6146", colorMode); } private static void SetWIAProperty(IProperties properties, object propName, object propValue) { Property prop = properties.get_Item(ref propName); prop.set_Value(ref propValue); }
To ensure the scan starts correctly, simply call the AdjustScannerSettings
method before initializing the scanner.
// Create a DeviceManager instance var deviceManager = new DeviceManager(); // Create an empty variable to store the scanner instance DeviceInfo firstScannerAvailable = null; // Loop through the list of devices to choose the first available for (int i = 1; i <= deviceManager.DeviceInfos.Count; i++) { // Skip the device if it's not a scanner if (deviceManager.DeviceInfos[i].Type != WiaDeviceType.ScannerDeviceType) continue; firstScannerAvailable = deviceManager.DeviceInfos[i]; break; } // Connect to the first available scanner var device = firstScannerAvailable.Connect(); // Select the scanner var scannerItem = device.Items[1]; int resolution = 150; int width_pixel = 1250; int height_pixel = 1700; int color_mode = 1; AdjustScannerSettings(scannerItem, resolution, 0, 0, width_pixel, height_pixel, 0, 0, color_mode); // Retrieve a image in JPEG format and store it into a variable var imageFile = (ImageFile)scannerItem.Transfer(FormatID.wiaFormatJPEG); // Save the image in some path with filename var path = @"C:\Users\<username>\Desktop\scan.jpeg"; if (File.Exists(path)) File.Delete(path); imageFile.SaveFile(path);
Exception Handling
WIA methods can throw exceptions. Handle these by wrapping your code in a try-catch block. Catch the COMException
to identify specific error codes:
using System.Runtime.InteropServices; try { // WIA scanning code } catch (COMException e) { uint errorCode = (uint)e.ErrorCode; if (errorCode == 0x80210006) { Console.WriteLine("Scanner is busy or not ready."); } else if (errorCode == 0x80210064) { Console.WriteLine("Scanning process was cancelled."); } // Add more error handling as necessary }
Show Scanning Progress
To display scanning progress, you can use the ShowTransfer
method from the CommonDialogClass
:
using WIA; using System.Runtime.InteropServices; var dlg = new CommonDialogClass(); try { object scanResult = dlg.ShowTransfer(scannerItem, WIA.FormatID.wiaFormatPNG, true); if (scanResult != null) { ImageFile image = (ImageFile)scanResult; // Process the image as needed } } catch (COMException e) { Console.WriteLine(e.ToString()); // Handle errors as previously shown }
With the steps above, you can create a basic scanning application in C#.
- Using the OrderBy and OrderByDescending in LINQ
- Querying with LINQ
- Optimizing Performance with Compiled Queries in LINQ
- MinBy() and MaxBy() Extension Methods in .NET
- SortBy, FilterBy, and CombineBy in NET 9
- Exploring Hybrid Caching in .NET 9.0
- Using Entity Framework with IDbContext in .NET 9.0
- Primitive types in C#