Introduction
In general, .NET ActiveX Wrappers are painful to build and deploy. This is because there are a large number of steps involved in the building of signed .NET ActiveX Web Applications:
- Define a set of ActiveX Interfaces to your Control
- Define appropriate attributes for each accessible object and interface
- Define unique Guids for each accessible object and interface
- Mark your control as “Safe for Scripting”
- Configure your control to be Self-Registering
- Build an installer to register your control and add your references
- Build a CAB file which contains your installer and an INF file which executes it
- Generate Public/Private Keys in the appropriate format for your signing utility
- Configure Signing for Control Assembly and CAB files
- Place your Object in said Web Application
- Wire up Javascript and Events Correctly
As you can see, this process can be both difficult and time consuming. Additionally, in each of these cases there are a number of pitfalls which can take days to resolve. Indeed, the creation of ActiveX controls has been the bane of many a .NET programmer’s existence.
In order to reduce the complexity of this problem, we’ve created a sample solution which works out of the box. It contains a reference implementation of a UserControl which interacts with Javascript via both method calls and events. Additionally, it takes care of the entire installer and cab file building process for you. Simply download the control, hit F5 and, if Internet Explorer is your default browser, it will run without issue.
http://www.atalasoft.com/download/articles/Initial-ActiveX-Deploy.zip
http://www.atalasoft.com/download/articles/Twain-ActiveX-Deploy.zip
Building a Twain Scanner ActiveX Control
Even without the ActiveX component of the project, TWAIN is quite a complex API on its own. Thankfully, our .NET Scanning SDK makes it as simple as dropping a control on a page. To this end, head on over to our site and download a free evaluation copy of DotTwain. Once you have it installed and registered we can begin building our ActiveX Control by opening the Initial ActiveX Deploy solution.
Step 1 – Add the Acquisition Object
The first simple step is to drag the Acquisition onto the ExampleControl’s design view.
This will add an Acquisition Class object definition named acquisition1 to our ExampleControl class and, in addition, add all necessary references to our project. The Acquisition class takes care of everything you need for simple to moderately complex scanning solutions in .NET WinForms. Now it’s just a matter of a little wiring to make it scan.
Step 2 – Initialization of the Acquisition Object
For error handling and messaging we can use the SomethingHappenedEvent
via our provided d method.
public ExampleControl()
{
InitializeComponent();
acquisition1.AcquireCanceled += new EventHandler(acquisition1_AcquireCanceled);
acquisition1.ImageAcquired += new Atalasoft.Twain.ImageAcquiredEventHandler(
acquisition1_ImageAcquired);
}
void acquisition1_ImageAcquired(object sender, Atalasoft.Twain.AcquireEventArgs e)
{
SetLabelText("Image Acquired”);
}
void acquisition1_AcquireCanceled(object sender, EventArgs e)
{
SetLabelText("Acquire Canceled");
}
When SetLabelText
is called, the SomethingHappenedEvent
will be invoked with the specified string.
Step 3 – Add Scanning Code to the Control
For the sake of simplicity, we’re going to use the already existing InternalClickButton()
method for our scan button and use the default scanner.
private void Scan()
{
if (!acquisition1.SystemHasTwain || acquisition1.Devices.Count < 0)
{
SetLabelText("No Twain devices found on the System");
}
else if (!acquisition1.Devices.Default.CanOpen())
{
SetLabelText("Cannot open default device");
}
else
{
acquisition1.Devices.Default.ModalAcquire = true;
acquisition1.Devices.Default.Acquire();
}
}
private void InternalClickButton(string textlabel)
{
SetLabelText(textlabel);
Scan();
}
By pasting these two code snippets in and overwriting the existing ExampleControl()
and InternalClickButton()
methods, you now have a working ActiveX Twain Solution.
Deployment
While the previous result will work locally, some steps still need to be taken before deployment. This is due to two factors outside of our control: Guids must be unique to the control/interface and keys must be unique to the user.
The following three steps are necessary to ensure that both your Guids are unique and your files are securely signed.
- Set Unique Guids.
- Set the Guid in the Default.aspx file’s object tag must match the control.
- Generate new keys and configure signing your Assembly and Cab file.
Thankfully, these are both relatively easy tasks to accomplish.
Step 1 – Setting Unique Guids
The ExampleControl class and each of its declared interfaces must have unique Guids. This is because the Guid is what windows uses to identify these constructs under the hood. To accomplish this task we must replace each existing Guid with a fresh one made with Visual Studio’s Guid generator.
In my example we have three Guids: One for IExposedComMembers, one for IExposedComEvents
and one for the ExampleControl itself. Each of these three Guids must be replaced.
Note that there is an additional Guid tag in the ExampleControl.ActiveX.cs file. Do not replace this Guid! It specifies the IObjectSafety
interface to be imported. In fact, without further research on the exact repercussions, I suggest not changing anything in the ExampleControl.ActiveX.cs file as it will work perfectly well if left as-is in the vast majority of cases.
[Guid("B7C65243-6002-45fe-B9B0-27316F289646")]
public interface IExposedComMembers
{
…
}
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
[Guid("0F05ECBA-A254-4bd3-973F-C6145A3D2082")]
public interface IExposedComEvents
{
…
}
[ProgId("ExampleControl")]
[ClassInterface(ClassInterfaceType.None),
ComSourceInterfaces(typeof(IExposedComEvents))]
[ComVisible(true)]
[Guid("56113B3E-0616-4e68-BABC-7CAE3352DF68")]
public partial class ExampleControl : UserControl
{
…
}
The Guid generator can be found under Visual Studio’s Tools menu under the title Create Guid.
To use the Guid Generator, first ensure that “4. Registry Format” is selected. Then, for each Guid to be replaced, click “New Guid” and then “Copy”. You can then simply highlight the text portion of the attribute. The result will look like this.
[Guid("{C025FB74-9813-4dcf-B2EE-9AF475769E93}")]
You must then delete the braces { } from both sides of each pasted Guid:
[Guid("C025FB74-9813-4dcf-B2EE-9AF475769E93")]
Step 2 – Setting the correct Guid for your control
After changing your control’s Guid the Default.aspx must be changed to match it. The definition inside the Default.aspx like the following:
<object id="ActiveXExample" name="ActiveXExample"
classid="clsid:56113B3E-0616-4e68-BABC-7CAE3352DF68"
codebase="ActiveX.cab#version=1,0,0,0" VIEWASTEXT></object>
All that is needed here is for the text following clsid: to match the Guid you generated for your control. So if, for example, your control now looks like:
[ProgId("ExampleControl")]
[ClassInterface(ClassInterfaceType.None),
ComSourceInterfaces(typeof(IExposedComEvents))]
[ComVisible(true)]
[Guid("C025FB74-9813-4dcf-B2EE-9AF475769E93")]
public partial class ExampleControl : UserControl
{
…
}
Your object tag should appear as follows:
<object id="ActiveXExample" name="ActiveXExample"
classid="clsid:C025FB74-9813-4dcf-B2EE-9AF475769E93"
codebase="ActiveX.cab#version=1,0,0,0" VIEWASTEXT></object>
Step 3 – Signing you Application
To ease initial development I’ve included a pre-generated key with my solution. However, deploying your application with the included key is a terrible idea. This is because if anyone else were to find this example and my pre-generated key set, they would be able to spoof your control and compromise your client’s machines.
The first step is to generate your own set of cer, pfx, pvka and spc key files. This is not a trivial task. However, a very well written walkthrough on how to do this can be found here.
Once you have these files generated only three things remain to be done.
- Take these resulting files and place them in the \ActiveXExample\Tools directory of your solution.
- Put the name of your .pfx file in filename.txt and your signing password in password.txt.
- In Visual Studio, go to the signing tab in the properties of your ActiveXExample project and change the strong name key file to your newly generated .snk.
Once you have completed this, rebuild your solution. At this point you will have a working ActiveX Twain Solution which is ready for deployment.
Going Further
With this, we’ve hidden most of the complexity in ActiveX deployment. However, for a reasonably sized application it will likely be necessary to learn about the details of this implementation. For additional information, I suggest reading the following excellent articles:
Michal Kosmala’s Create ActiveX in .NET Step by Step
Anand Todkar’s Downloading C# ActiveX Components through CAB File
Sharon Salmon’s Handling HTML Events from .NET, using C#
HOWTO: Deploy DotTwain from Internet Explorer
Conclusion
With this article, I hope we’ve been able to reduce your Twain ActiveX deployment from a month long ordeal to a day-long project. Should you run into any bumps in the road along the way, our fantastic support team is available to help you through any problem you might have. Also, if you find yourself in need of an ActiveX document imaging solution, our .NET Imaging SDK is similar to our Twain toolkit in terms of ease of use and deployment.
Archives