Olav Aukan Getting information off the Internet is like taking a drink from a fire hydrant…

31Aug/10

Creating an ActiveX control in .Net using C#

A while back I had a client request that I write an ActiveX control for use on their corporate intranet. I had never done this before, and most of the examples I could find online were either really old, incomplete or based on using C++ and MFC. It's safe to say that my C++ skills are not quite up to the job, so for me it was really a requirement to be able to do this with C#. It took me about an hour or two to write the code for the control, but it took almost three days to successfully package and deploy it as a .cab file... So to save others from wasting their time like I did, I'll document my findings in this post.

Steps

  1. - Create a new Class Library project in Visual Studio
  2. - Create a new class that inherits from UserControl
  3. - Create a new interface that exposes the controls methods and properties to COM interop
  4. - Make the control class implement the new interface
  5. - Mark the control as safe for scripting and initialization
  6. - Create a .msi installer for the control
  7. - Package the control in a .cab file for web deployment
  8. - Initialize and test the control with JavaScript

1. Create a new Class Library project in Visual Studio

I'm using Visual Studio 2008, but other versions should work as well.

  1. After starting Visual Studio click File -> New -> Project and select Class Library under C#.
  2. Call the project 'AxControls' and click OK.

2. Create a new class that inherits from UserControl

  1. Rename 'Class1.cs' to 'HelloWorld.cs', making sure to rename the class name as well.
  2. Add a project reference to System.Windows.Forms.
  3. Make the HelloWorld class inherit UserControl.

3. Create a new interface that exposes the controls methods and properties to COM interop

  1. Right click the project in Visual Studio and click Add -> New Item.
  2. Select 'Interface' from the list of components, name it 'IHelloWorld.cs' and click Add.
  3. Edit the 'IHelloWorld.cs' file so it looks like this:
    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Runtime.InteropServices;
    
    namespace AxControls
    {
        [ComVisible(true)]
        [InterfaceType(ComInterfaceType.InterfaceIsDual)]
        [Guid("41E85D5D-C57A-4386-B722-4031D0B1E1B7")]
        public interface IHelloWorld
        {
            string GetText();
        }
    }
    

We now have a COM visible interface with a single method 'GetText()'.

[ComVisible(true)] makes the interface visible to COM.
[InterfaceType(ComInterfaceType.InterfaceIsDual)] sets the COM interface type to Dual, see InterfaceTypeAttribute Class on MSDN.
[Guid("41E85D5D-C57A-4386-B722-4031D0B1E1B7")] let's us manually assign a GUID to the interface. Use guidgen.exe to generate your own.

4. Make the control class implement the new interface

Make the HelloWorld class implement the IHelloWorld interface and have the GetText() method return a string of your choice. This is what the file might look like:

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace AxControls
{
    [ComVisible(true)]
    [ClassInterface(ClassInterfaceType.None)]
    [Guid("1FC0D50A-4803-4f97-94FB-2F41717F558D")]
    [ProgId("AxControls.HelloWorld")]
    [ComDefaultInterface(typeof(IHelloWorld))]
    public class HelloWorld : UserControl, IHelloWorld
    {
        #region IHelloWorld Members

        public string GetText()
        {
            return "Hello ActiveX World!";
        }

        #endregion
    }
}

We now have a COM visible control that implements the IHelloWorld interface.

[ComVisible(true)] makes the control visible to COM, see ComVisibleAttribute Class on MSDN.
[ClassInterface(ClassInterfaceType.None)] indicates that no class interface is generated for this class, see ClassInterfaceType Enumeration on MSDN.
[Guid("1FC0D50A-4803-4f97-94FB-2F41717F558D")] let's us manually assign a GUID to the control, see GuidAttribute Class on MSDN. Use guidgen.exe to generate your own.
[ProgId("AxControls.HelloWorld")] is a "user friendly" ID that we'll use later from JavaScript when initiating the control, see ProgIdAttribute Class on MSDN.
[ComDefaultInterface(typeof(IHelloWorld))] sets IHelloWorld as the default interface that will be exposed to COM, see ComDefaultInterfaceAttribute Class on MSDN.

5. Mark the control as safe for scripting and initialization

By default IE will not allow initializing and scripting an ActiveX control unless it is marked as safe. This means that we won't be able to create instances of our ActiveX class with JavaScript by default. We can get around this by modifying the browser security settings, but a more elegant way would be to mark the control as safe. Before you do this to a "real" control, be sure to understand the consequences. I found an ancient (1996) MSDN article that explains this here. We will mark the control as safe by implementing the IObjectSafety interface.

  1. Right click the project in Visual Studio and click Add -> New Item.
  2. Select 'Interface' from the list of components, name it 'IObjectSafety.cs' and click Add.
  3. Edit the 'IObjectSafety.cs' file so it looks like this:
    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Runtime.InteropServices;
    
    namespace AxControls
    {
        [ComImport()]
        [Guid("CB5BDC81-93C1-11CF-8F20-00805F2CD064")]
        [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
        interface IObjectSafety
        {
            [PreserveSig()]
            int GetInterfaceSafetyOptions(ref Guid riid, out int pdwSupportedOptions, out int pdwEnabledOptions);
    
            [PreserveSig()]
            int SetInterfaceSafetyOptions(ref Guid riid, int dwOptionSetMask, int dwEnabledOptions);
        }
    }
    
  4. Make the HelloWorld class implement the IObjectSafety interface. The end result should look something like this:
    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Windows.Forms;
    using System.Runtime.InteropServices;
    
    namespace AxControls
    {
        [ComVisible(true)]
        [ClassInterface(ClassInterfaceType.None)]
        [Guid("1FC0D50A-4803-4f97-94FB-2F41717F558D")]
        [ProgId("AxControls.HelloWorld")]
        [ComDefaultInterface(typeof(IHelloWorld))]
        public class HelloWorld : UserControl, IHelloWorld, IObjectSafety
        {
            #region IHelloWorld Members
    
            public string GetText()
            {
                return "Hello ActiveX World!";
            }
    
            #endregion
    
            #region IObjectSafety Members
    
            public enum ObjectSafetyOptions
            {
                INTERFACESAFE_FOR_UNTRUSTED_CALLER = 0x00000001,
                INTERFACESAFE_FOR_UNTRUSTED_DATA = 0x00000002,
                INTERFACE_USES_DISPEX = 0x00000004,
                INTERFACE_USES_SECURITY_MANAGER = 0x00000008
            };
    
            public int GetInterfaceSafetyOptions(ref Guid riid, out int pdwSupportedOptions, out int pdwEnabledOptions)
            {
                ObjectSafetyOptions m_options = ObjectSafetyOptions.INTERFACESAFE_FOR_UNTRUSTED_CALLER | ObjectSafetyOptions.INTERFACESAFE_FOR_UNTRUSTED_DATA;
                pdwSupportedOptions = (int) m_options;
                pdwEnabledOptions = (int) m_options;
                return 0;
            }
    
            public int SetInterfaceSafetyOptions(ref Guid riid, int dwOptionSetMask, int dwEnabledOptions)
            {
                return 0;
            }
    
            #endregion
        }
    }
    

[ComImport()] IObjectSafety is a native interface so we have to redefine it for managed .Net use. This is done with the ComImport() attribute, see ComImportAttribute Class on MSDN.
[Guid("CB5BDC81-93C1-11CF-8F20-00805F2CD064")] This is the GUID of the original IObjectSafety interface. Do not change it.
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] sets the COM interface type to Unknown, see InterfaceTypeAttribute Class on MSDN.

This is just a simple implemetation of the IObjectSafety interface that will mark the control as safe. In "real life" there would probably be some sort of logic to determine if the control is safe or not.

6. Create a .msi installer for the control

Before an ActiveX control can be used it must be installed and registered on the client. This can be done in a number of ways, from manually editing the registry to using regasm.exe, but we're going to create a Vistual Studio setup project to handle the installation for us.

  1. Right click the Visual Studio solution, select Add -> New Project and select Setup Project under Other Project Types.
  2. Call the project 'AxControlsInstaller' and click OK.
  3. Right click the 'AxControlsInstaller' project, select Add -> Project Output, select 'Primary output' from the 'AxControls' project and click OK.
  4. Right click 'Primary output from AxControls (Active)' and select Properties.
  5. Change the Register property from 'vsdrpDoNotRegister' to 'vsdrpCOM'.
  6. Right click the 'AxControlsInstaller' project and select Build.

The installer should now be located in the AxControlsInstaller's output folder (bin\Debug or bin\Release). In the corporate domain this .msi file can de run manually on the client, or automatically with a Group Policy.

7. Package the installer in a .cab file for web deployment

For public web sites we obviously can't deploy our ActiveX control to the client with a Group Policy. In this case we're gonna have to use Internet Explores built-in ability to download and install controls that are packaged in .cab files.

  1. Download the Microsoft Cabinet Software Development Kit.
  2. Unpack the kit to a local folder and copy Cabarc.exe to the 'AxControlsInstaller' folder.
  3. Create a new file named 'AxControls.inf' in the 'AxControlsInstaller' folder and add the following content:
    [version]
    signature="$CHICAGO$"
    AdvancedINF=2.0
    
    [Add.Code]
    AxControlsInstaller.msi=AxControlsInstaller.msi
    
    [AxControlsInstaller.msi]
    file-win32-x86=thiscab
    clsid={1FC0D50A-4803-4f97-94FB-2F41717F558D}
    FileVersion=1,0,0,0
    
    [Setup Hooks]
    RunSetup=RunSetup
    
    [RunSetup]
    run="""msiexec.exe""" /i """%EXTRACT_DIR%\AxControlsInstaller.msi""" /qn
    
  4. Click the AxControlsInstaller project and then click the Properties window (View -> Properties Window if it's not visible).
  5. Click the '...' button next to the PostBuildEvent property and add the following content:
    "$(ProjectDir)\CABARC.EXE" N "$(ProjectDir)AxControls.cab" "$(ProjectDir)AxControls.inf" "$(ProjectDir)$(Configuration)\AxControlsInstaller.msi"
    
  6. Right click the 'AxControlsInstaller' project and select Build.
  7. There should now be a 'AxControls.cab' file in the 'AxControlsInstaller' folder.

NB! Make sure you use ANSI encoding for the 'AxControls.inf' file or you will be unable to install the control.

8. Initialize and test the control with JavaScript

  1. Right click the AxControls solution, select Add -> New Project and select 'ASP.Net Web Application' under 'Web'.
  2. Call the project 'WebAppTest' and click OK.
  3. Right click the 'WebAppTest' project, select Add -> New Item and select 'HTML Page'.
  4. Call it 'index.html' and click OK.
  5. Add the following content to index.html:
    <html>
        <head>
    
            <object name="axHello" style='display:none' id='axHello' classid='CLSID:1FC0D50A-4803-4f97-94FB-2F41717F558D' codebase='AxControls.cab#version=1,0,0,0'></object>
    
          <script language="javascript">
    
            <!-- Load the ActiveX object  -->
            var x = new ActiveXObject("AxControls.HelloWorld");
    
            <!-- Display the String in a messagebox -->
            alert(x.GetText());
    
          </script>
        </head>
        <body>
        </body>
    </html>
    

    Note that 'classid' matches the GUID of the HelloWorld control.

  6. Right click 'index.html' and select 'Set as start page'.
  7. Right click the 'WebAppTest' project and select 'Set as startup project'.
  8. Copy 'AxControls.cab' from the 'AxControlsInstaller' folder to the same folder as index.html.
  9. Uninstall the control from the client by going to Control Panel -> Programs and Features, selecting 'AxControlsInstaller' on the list and clicking Uninstall. This forces Internet Explorer to download and install the .cab file and is an important step in case you've already installed the control.
  10. Run the application (F5). This will open 'index.html' in Internet Explorer.
  11. Internet Explorer will display a security warning, asking if you want to install 'AxControls.cab'. Click Install.
  12. When the page loads it should display a message box with the string you defined in HelloWorld's GetText() method.

If the message box displayed without any more warnings or errors we've implemented everyting correctly.

UPDATE

I forgot to write that you have to register the assembly containing the ActiveX control for COM interop. Right-click the project, select Properties, go to Build and check the "Register for COM interop" checkbox. This should solve the error some of you are seeing about "Automation Server can’t create this object" and similar error messages. You might need to add the [ComVisible(true)] attribute to the methods and properties you are exposing as well, but I haven't had time to test this.

Comments (1892) Trackbacks (8)
  1. 免許合宿
    パンチラ
    合宿免許
    panchira-gazo.biz
    別れさせ屋 静岡県
    別れさせ屋 栃木県

  2. Все утро исследовал контент сети, случайно к своему удивлению заметил хороший сайт. Вот: масло моторное мобил 1 . Для моих близких этот веб-сайт явился довольно полезным. До свидания!

  3. Если не затруднит можно по подробнее.
    П.С.
    Прошёл недавно мрт химки цены приемлимые.

  4. Если не затруднит можно по подробнее.
    П.С.
    Прошёл недавно мрт химки цены приемлимые.

  5. Целый день изучал содержимое сети, и неожиданно к своему восторгу увидел неплохой ресурс. Вот ссылка: автозапчасти киев . Для меня данный сайт явился весьма полезным. Успехов всем!

  6. Весь день разглядывал материалы сети, и неожиданно к своему удивлению заметил неплохой ресурс. Ссылка на него: перила для балкона . Для моих близких этот сайт явился довольно важным. Пока!

  7. Почти час изучал данные инет, неожиданно к своему восторгу заметил четкий ресурс. Вот: научный центр . Для моих близких этот ресурс произвел хорошее впечатление. Всего наилучшего!

  8. Link goo.gl/T03SNa
    Link lix.in/-18c5a9f
    Link lix.in/-18ad3fe

    loli CP full Lolita
    Sho tc lips Video lolicp
    Best Stickam ,Webcam , Solo, Teen
    loliCP full Lolita
    Sho tc lips Video lolicp
    Best Stickam ,Webcam , Solo, Teen
    >

    Link goo.gl/T03SNa
    Link lix.in/-18c5a9f
    Link lix.in/-18ad3fe
    l
    l

  9. Good piece of information improvingpost…Thanks a lot for the sharing.

  10. MexGear Buy Anabolic Steroids Usa – Oral Steroids For Sale In Usa ! http://1mexgear.org – Click here>>>

  11. Хай админу. Предлагаю обсудить статью – программы стипендий США. Кто где учится?

  12. Накануне просматривал контент сети, и неожиданно к своему восторгу увидел интересный ресурс. Гляньте: пускозарядное устройство . Для меня этот ресурс показался довольно привлекательным. Хорошего дня!

  13. Прошлым вечером мониторил содержимое сети, и к своему удивлению заметил нужный ресурс. Посмотрите: аккумулятор топла отзывы . Для моих близких данный сайт оказался весьма оригинальным. Хорошего дня!

  14. Час назад смотрел содержание инета, неожиданно к своему удивлению заметил красивый веб-сайт. Посмотрите: suzuki grand vitara купить . Для меня вышеуказанный ресурс оказался весьма полезным. До встречи!

  15. Perhaps anyone could have always wanted to have a baby, maybe you’re getting a bit older and won’t feel like you can wait any longer, or maybe you just desire a child as soon as possible. Whatever the reason, you desire how to get pregnant quickly. If you had a approach to “make a newborn eventually” or “make a newborn fast” end up being definitely regarding the quicker option. Here are some tips if getting pregnant fast is your goal.

    To increase and also have healthy sperm during ovulation try this trick. Try foreplay many days a person ovulate, easy right? Well, heres tough part your husband or wife cant unload. He needs to keep the sperm for it to work at its full expected.

    As you relax, you would possibly be reminded of weed times whenever you had to head through the pain and anguish over enough sleep . pregnant each passing pretty good period now. That was the time when everything seemed to center to the topic of babies and your inability to obtain pregnant naturally, despite all tests being positive. Ended up being when you repeatedly prayed and asked God, “can i get pregnant?” However, now you have reached the final term of your pregnancy, place shun away these thoughts and instead think very good things to ones baby and yourself.

    Stop Smoking – Certainly for any couple who are trying to conceive giving up smoking ought to a precedence. The chemicals of which alternatives here . 2,000 variations find in cigarettes can decrease an individual’s fertility levels. In fact women who smoke when however trying to have a baby are 60% more prone to be infertile to be able to women that do not. Women who smoke rapidly realize that the sheer number of eggs their ovaries produced is reduced.

    You can track if ovulate using three various methods. The first one involves checking your cervical mucous for egg white texture and consistancy. This is referred to as cervical mucous observation. You have to keep checking your cervical mucous it is possible notice healthy step . in look and feel. This will better give you an idea of when you ovulate. Important method involves charting and monitoring your basal body temperature. You simply check your temperature each and every morning and publish the temp. When you notice a temperature shift close to .4 degrees F, ovulation is near or probably occurring. Lastly you should purchase an ovulation predictor kit that will tell you when you are near ovulation.

    As I told you earlier, herpes can be transmitted through skin to skin functionality. To eliminate the odds of your better half to get transmitted, it is preferable to find the best medication to cure the disease before developing a sexual sex. Besides, it is better if consider the medication prior to having pregnant. Certain medications being pregnant most likely good inside your baby. Actually, the transmission of genital herpes to your significant other is more unlikely that to occur if you’ve no outbreak. But, you need be careful because you can have no symptoms in any way when the suffering from herpes.

    Now all the details are ready. Are usually thing to make sure you do is test your ovulation menstrual cycle. It is the time wherever you are most fertile. The problem is how realize when. If you’d like to get it to more precise and exact, there is ovulation kit to aid you figure out when you’ll have ovulate, and also can tell an ovulation 36 hours earlier. In this particular way, seek it . guarantee you will be having sex on the days that you ovulate. All in all, take period and and have fun! Follow these and discover you’re having a baby in not enough available time!
    can i get pregnant right after my period early pregnancy

  16. pid=6842525&profile_id=86846344&profile_name=happywheelsdemoy&user_id=86846344&username=happywheelsdemoy
    My brother recommended I may like this website. He was once totally right. This publish actually made my day. You can not consider just how a lot time I had spent for this information! Thank you!
    http://www.purevolume.com/listeners/happywheelsdemooo/posts/5972542/Happy+Wheels+Racing+Game

  17. Три дня назад познавал содержимое инет, вдруг к своему удивлению заметил хороший ресурс. Посмотрите: гравировка на стекле . Для моих близких данный сайт произвел хорошее впечатление. Удачи!

  18. На днях осматривал содержание сети, случайно к своему удивлению открыл хороший вебсайт. Посмотрите: centra futura . Для меня данный сайт оказался очень оригинальным. Всех благ!

  19. Сегодня утром осматривал контент сети интернет, и к своему удивлению заметил нужный ресурс. Вот гляньте: оксандролон купить . Для нас вышеуказанный вебсайт произвел хорошее впечатление. Успехов всем!

  20. Прошлой ночью осматривал контент интернет, при этом к своему восторгу заметил поучительный веб-сайт. Посмотрите: стромбафорт . Для нас вышеуказанный ресурс явился очень привлекательным. Пока!

  21. Frumos spus. Te invit sa citesti si articolul meu despre hotelurile din bucuresti:
    http://earticole.com/locuri-de-vizitat-in-bucuresti.html – Ce locuri sa vizitezi in Bucuresti
    <a href=http://www.articole.bia-director.ro/ce-hotel-am-ales-cand-am-fost-in-bucuresti/"Ce hotel am ales cand am fost in Bucuresti

  22. Полчаса изучал контент инет, и неожиданно к своему восторгу увидел прелестный сайт. Вот ссылка: купить книгу . Для моих близких данный веб-сайт показался очень привлекательным. Всего наилучшего!

  23. http://safe-water.ru – Купить пергидроль для бассейна инновационная защита от цветения – успейте купить первым и купайтесь в чистой воде. Бесплатная доставка по Москве.

  24. Each and every person wants to be happy, and dreams of find a soul mate, namely, the person with whom you want to build a serious relationship and to start a family , a happy family .
    Exactly this assistance offers our Marriage Agency in Ukraine “Happy Dating”.

  25. Приветки, сетевой народ!
    Загляните в презанятный проект,
    Задача интернет проекта коды мобильных операторов.
    По видимому прикольно.
    Всем удачи в сети, посетители вебсайта.
    Тарас

  26. Прошлой ночью разглядывал содержимое интернет, и неожиданно к своему удивлению заметил прекрасный сайт. Я про него: натуральный камень . Для меня данный веб-сайт оказал хорошее впечатление. Хорошего дня!

  27. Недавно изучал материалы сети, при этом к своему восторгу увидел интересный сайт. Смотрите: укладка тротуарной плитки . Для нас вышеуказанный веб-сайт оказал радостное впечатление. Всего хорошего!

  28. large soft play equipment
    large soft play equipment
    soft play manufacturers
    soft play equipment for sale
    indoor play centre suppliers
    indoor playground suppliers

  29. Весь день наблюдал контент инет, при этом к своему удивлению заметил восхитительный вебсайт. Вот посмотрите: грузчики киев . Для нас этот вебсайт произвел хорошее впечатление. Всем пока!

  30. Сегодня утром исследовал содержание сети интернет, случайно к своему восторгу заметил прекрасный ресурс. Ссылка на него: стулья из дерева . Для меня вышеуказанный веб-сайт произвел хорошее впечатление. Успехов всем!

  31. Forgot Windows 10 password and unable to change it? Use this windows 10 password reset tool to reset windows 10 password instantly.
    reset windows 10 password

  32. Прошлым вечером просматривал содержание инета, неожиданно к своему удивлению обнаружил интересный веб-сайт. Вот смотрите: стоимость наливного пола . Для нас этот веб-сайт показался довольно привлекательным. Удачи!

  33. получено совет политическое убежище в штатах фото firma vygodno politicheskoe ubezhishhe v tol’ko Soedinennyh Shtatah veb-stranica ::> !
    купить замена политического убежища в США Вот

  34. http://canph01.com canada pharmacy drugs prices

  35. Доброго дня, уважаемые господа!
    Профиль вебсайта playonlinux.
    Всем счастья .
    Ефим

  36. Почти час анализировал контент интернет, неожиданно к своему удивлению обнаружил важный ресурс. Вот посмотрите: зрелые проститутки . Для нас данный ресурс показался весьма полезным. Успехов всем!

  37. Заработок на бинарных опционах – Как совместить торговлю бинарными опционами и работу в офисе?, Принцип бинарных опционов.

  38. http://www.bmw-navigation-update.ovh israeli oil cast pl england wisdom dance advantages pepper adobe television remedy ontario flex wool gains gas bone pokemon goto cb void store copy widespread quotations asp installing forty zus

  39. Cherche ultram en 24h en pharmacie. augmenter la libido homme,baisse de libido chez l’homme. achat de cialis en pharmacie.
    como aumentar el libido femenino,augmenter libido femme,. pilule pour augmenter la libido homme,baisse de libido chez l’homme.. como aumentar el apetito sexsual.Perte libido masculine,, comment augmenter la libido d’une femme.augmenter libido femme, tarif cialis en pharmacie xxx viagra.
    augmenter la libido chez l’homme, cialis lilly sans ordonnance Tramadol online Codeine pharmacie vente de viagra. plantes pour stimuler la libido,capsules libido masculine,. medicament pour impuissance masculine.medicament viagra pour homme,. medicament pour homme impuissant,baisse de libido homme,, manque de libido homme,como recuperar el libido, peut ton acheter du viagra en pharmacie sans ordonnance.
    viagra homme prix kamagra oral jelly kokemuksia. pilule pour homme fonctionnement,pilule pour homme 2015,. medicament pour baisse de libido,, medicament viagra pour homme,acheter pilule pour chat, generique sildenafil.
    perte de libido que faire, acheter sildenafil en pharmacie, comprar viagra mercadolivre, tramadol prix.


Leave a comment