C# – Signing .NET DLL used as ActiveX Control

activexccode-signinginternet explorernet

I have a COM visible .NET DLL file that is being used as an ActiveX control within a webpage shown in Internet Explorer.

The control itself is working perfectly (though with some caveats) when called via JavaScript code from a webpage.

The problem comes with signing the DLL and having it reliably accessible. I am (as far as I can tell) signing the project within Visual Studio. In the properties for the project's 'Signing', I created a .pfx file and am using it to sign the DLL.

Within Internet Explorer, no matter what I do, I cannot get Internet Explorer to let the ActiveX control load without manually going into the security settings and changing the 'Download unsigned ActiveX controls' and 'Initialize and script ActiveX controls not marks as safe for scripting' options to Enable/prompt.

Best Answer

Seems the original issue had nothing to do with the signature of the file, but in the implementation of IObjectSafety. For IE to allow it to be loaded, I needed to properly implement that interface, and it worked fine (even without a valid signature).

Simple example:

[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);
}

And the class itself:

[ProgId("Testing.Test")]
[ClassInterface(ClassInterfaceType.AutoDispatch)]
[ComVisible(true)]
public sealed class Test : IObjectSafety
{
    #region Saftey Interface
    private const int INTERFACESAFE_FOR_UNTRUSTED_CALLER = 0x00000001;
    private const int INTERFACESAFE_FOR_UNTRUSTED_DATA = 0x00000002;
    private const int S_OK = 0;

    [ComVisible(true)]
    public int GetInterfaceSafetyOptions(ref Guid riid, out int pdwSupportedOptions, out int pdwEnabledOptions)
    {
        pdwSupportedOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA;
        pdwEnabledOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA;
        return S_OK;
    }

    [ComVisible(true)]
    public int SetInterfaceSafetyOptions(ref Guid riid, int dwOptionSetMask, int dwEnabledOptions)
    {
        return S_OK;
    }
    #endregion

    [ComVisible(true)]
    public string TestString
    {
        get
        {
            return 'A Test';
        }
    }
}