Using WIA for scanning

I was playing around this morning with scanning images and put together an adapter class that uses the Windows automation library (WIAAUT.DLL) which is part of the WIA automation SDK — WIA means Windows Image Acquisition.

Here are the imports I used for the code file:

 

using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Runtime.InteropServices;
using System.Security.Permissions;
using WIA;

 

I created a simple enumeration for some of the more common errors that I expected.

public enum WiaScannerError : uint
{
LibraryNotInstalled = 0x80040154,
OutputFileExists = 0x80070050,
ScannerNotAvailable = 0x80210015,
OperationCancelled = 0x80210064
}

Instead of throwing a COMException I created a special exception class that provides an error code from the aforementioned enumeration.

[Serializable]
public class WiaOperationException : 
Exception
{
private WiaScannerError _errorCode;

     public WiaOperationException(WiaScannerError errorCode)
base()
{
ErrorCode = errorCode;
}

     public WiaOperationException(string message, WiaScannerError errorCode)
base(message)
{
ErrorCode = errorCode;
}

public WiaOperationException(string message, Exception innerException)
base(message, innerException)
{
COMException comException = innerException as COMException;

if (comException != null)
ErrorCode = (WiaScannerError)comException.ErrorCode;
}

     public WiaOperationException(string message, Exception innerException, WiaScannerError errorCode)
base(message, innerException)
{
ErrorCode = errorCode;
}

public WiaOperationException(System.Runtime.Serialization.SerializationInfo info,
System.Runtime.Serialization.StreamingContext context)
base(info, context)
{
info.AddValue(“ErrorCode”, (uint)_errorCode);
}

public WiaScannerError ErrorCode
{
get return _errorCode; }
protected set { _errorCode = value; }
}

public override void GetObjectData(System.Runtime.Serialization.SerializationInfo info,
System.Runtime.Serialization.StreamingContext context)
{
base.GetObjectData(info, context);
ErrorCode = (WiaScannerError)info.GetUInt32(“ErrorCode”);
}
}

The actual class I created is just for scanners, but you can adapt it to any device that supports WIA.  I’ve pulled out comments and removed some extra stuff like providing a friendly message for errors for the sake of brevity.

public sealed class WiaScannerAdapter : IDisposable
{
private CommonDialogClass _wiaManager;
private bool _disposed; 
// indicates if Dispose has been called

    public WiaScannerAdapter()
{
}

~WiaScannerAdapter()
{
Dispose(false);
}

     private CommonDialogClass WiaManager
{
get return _wiaManager; }
set { _wiaManager = value; }
}

[SecurityPermission(SecurityAction.Demand, UnmanagedCode = true)]
     public Image ScanImage(ImageFormat outputFormat, string fileName)
{
if (outputFormat == null)
throw new ArgumentNullException(“outputFormat”);

FileIOPermission filePerm =
new FileIOPermission(FileIOPermissionAccess.AllAccess, fileName));
filePerm.Demand();

ImageFile imageObject = null;

try
{
if (WiaManager == null)
WiaManager = new CommonDialogClass();

imageObject =
WiaManager.ShowAcquireImage(WiaDeviceType.ScannerDeviceType,
WiaImageIntent.ColorIntent, WiaImageBias.MinimizeSize,
outputFormat.Guid.ToString(“B”), falsetruetrue);

imageObject.SaveFile(fileName);
return Image.FromFile(fileName);
}
catch (COMException ex)
{
string message = “Error scanning image“;
throw new WiaOperationException(message, ex);
}
finally
{
if (imageObject != null)
Marshal.ReleaseComObject(imageObject);
}
}

public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}

     private void Dispose(bool disposing)
{
if (!_disposed)
{
if (disposing)
{
// no managed resources to cleanup
}

// cleanup unmanaged resources
if (_wiaManager != null)
Marshal.ReleaseComObject(_wiaManager);

_disposed = true;
}
}
}

Calling the adapter is really easy.  Here’s an example that puts the image into a picturebox:

using (WiaScannerAdapter adapter = new WiaScannerAdapter())
{
try
{
Image image = adapter.ScanImage(ImageFormat.Bmp, @”c:\temp\test.bmp”);
pictureBox1.Image = image;
}
catch (WiaOperationException ex)
{
MessageBox.Show(ex.Message + “ Error Code: “ + ex.ErrorCode);
}
}

      Ref:

http://geekswithblogs.net/tonyt/archive/2006/07/29/86608.aspx

VS 2010 compiler error: Interop type XXX cannot be embedded. Use the applicable interface instead.

In most cases (such as error for the usage of UPnPNATClass as noted in one of the comments) this error is the result of code which tries to instantiate a COM object e.g. here piece of code starting up Excel:

Excel.ApplicationClass xlapp = new Excel.ApplicationClass();

Here it is enough to say that Excel.ApplicationClass derives from Excel.Application interface and one can even instantiate Excel using Excel.Application interface. Rewriting this code as below produces exact same results:

Excel.Application xlapp = new Excel.Application();

Ref: http://blogs.msdn.com/b/mshneer/archive/2009/12/07/interop-type-xxx-cannot-be-embedded-use-the-applicable-interface-instead.aspx

VS2010: IntelliSense: #error directive: Please use the /MD switch for _AFXDLL builds

สร้าง Project ใหม่แบบ MFC และเลือก Shared Library พอสั่งรันแล้วเกิด Error ดังนี้

IntelliSense: #error directive: Please use the /MD switch for _AFXDLL builds

ให้แก้ไขโดยคลิกขวาที่ Project เลือก properties > Configuration Properties > C/C++ > Code Generation

จากนั้นให้ดูที่ Runtime Libraryจะมีค่า default เป็น Multi-threaded Debug DLL (/MDd) แต่ไม่ใช่ตัวหนา

จากนั้นให้เปลี่ยนเป็นค่าอื่นก่อน แล้วเลือกกลับมาเป็น Runtime Library ให้เป็น Multi-threaded Debug DLL (/MDd) อีกครั้ง จะสังเกตุเห็นได้ว่า คำว่า Multi-threaded Debug DLL (/MDd) กลายเป็นตัวหนาแล้ว เป็นอันเสร็จ

อันนี้เข้าใจว่าเป็น Bug ของ VC 2010

vs2010

ที่มา: connect.microsoft.combasharatspace.blogspot.com

Integrate image scanning within a C# application

Now, include the WIA library (C:\Windows\System32\wiaaut.dll) within your project by adding a reference to it :

 

Figure 2.

Add a new class to your project and name it Scanner:

using System;
using WIA;

namespace ScanImage
{
public class Scanner
{
Device oDevice;
Item oItem;
CommonDialogClass dlg;
public Scanner()
{
dlg = new CommonDialogClass();
oDevice = dlg.ShowSelectDevice(WiaDeviceType.ScannerDeviceType, true, false);
}
public void Scann()
{
dlg.ShowAcquisitionWizard(oDevice);
}
}
}

In order to consume the services of this very simple class add a button and a picture box to your form as your project is Windows form one, the form should looks like this bellow:

 

Figure 3.

Do implement the button1_click as follow:

private void button1_Click(object sender, EventArgs e)
{
   Scanner oScanner = new Scanner();
oScanner.Scann();
button1.Text = “Image scanned”;
  OpenFileDialog dlg = new OpenFileDialog();
if (dlg.ShowDialog() == DialogResult.OK)
{
pictureBox1.Image = Image.FromFile(dlg.FileName);
}
}

Now run the application and observe:

 

Figure 4.

Click OK

 

Figure 5.

Then the below windows appears :

Figure 6.

Choose the colored photo, and then click next:

 

Figure 7.

In the above window, select JPG then click next

 

Figure 8 .

As showed above, the scanning process will be lunched as normally, click next then finish and the paper will be scanned as bellow:

 

Figure 9

You can browse to the emplacement of the given scanned image and display it using the picture box.

 

Figure 10

That’s it

 

Ref: http://www.c-sharpcorner.com/uploadfile/yougerthen/integrate-image-scanning-within-a-C-Sharp-application-part-vi/

Unable to start Debugging.The SilverLight Developer Runtime Not Installed. Please Install a matching version

Sat, 12/25/2010 – 18:58 — jack

ปัญหา คือ สร้างโปรเจ็กส์ Silverlight ขึ้นมา แต่ไม่สามารถรันได้ โดยเกิด Error ดังนี้
Unable to start Debugging.The SilverLight Developer Runtime Not Installed. Please Install a matching version
สาเหตุ คือ Silverlight version มี 2 version คือ เวอร์ชั่นสำหรับใช้งาน และเวอร์ชั่นสำหรับ developer
ทางแก้ คือ ติดตั้ง Silverlight managed debugging package
ที่มา: blogs.msdn.com/