Wednesday, April 6, 2011

Is there a way to force IE to unload an ActiveX control?

We have some dynamic HTML pages which include an <OBJECT> tag that instantiates an ActiveX control. The user may then navigate to another page, which contains an <OBJECT> tag that points to a newer version of the ActiveX control.

IE will download and install the new ActiveX on the second page, which is what that page is there for. The problem is that since IE loaded the ActiveX on the first page, it will now force the user to reboot before it will fully install the downloaded ActiveX, since it's being used by a process (IE).

In a normal container I would simply unload the ActiveX before trying to upgrade. Is there a way to force IE to do that? Going through a page which doesn't use the control would be acceptable if that would do the trick.

Edit:

Solutions that require the ActiveX itself to do something won't work simply because the problem is that the ActiveX is still in memory when IE starts installing the new version of the ActiveX. What I'm trying to do is to NOT have the ActiveX in memory when IE starts that process, so obviously I can't rely on anything in the ActiveX control itself.

From stackoverflow
  • Stupid answer, sorry. I'm guessing the redirect didn't work if you still have this question open. If you didn't try tho, just create a page that redirects to your updated ActiveX page and link there instead.

    middleman.html:

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
    <html>
    <head>
    <title>blank page</title>
    <meta http-equiv="REFRESH" content="0;url=http://www.newactivexcontrol.com"></HEAD>
    <BODY>
    </BODY>
    </HTML>
    
    Ori Pessach : I'm sorry, I just don't see how this is relevant to the question.
  • I think it is not possible.

  • One thing you may try is having your installer call CoFreeUnusedLibraries() and then respond with S_OK in DllCanUnloadNow() in your ActiveX control. This might get you unloaded, though I wonder if IE may still try calling back into your unloaded module. Simple enough to try.

    You could also just write a stub DLL that implements all the Interfaces you have that touch IE and then just thunks through to your real DLL that actually implements the functionality. Then you could have your installer broadcast a message that says "unload the real DLL". Then you broadcast another message when your done and it loads the new one. While the update is ocurring your stub draws a "Please wait while I update..." message.

    jeffamaphone : But the answer to your uber-question is, no, IE does not expose a way for you to force unload any extensions. It's very annoying.
    Ori Pessach : What installer? IE downloads the cab file (pointed to by the CODEBASE property in the OBJECT tag) and registers it. There's no installer code involved outside possibly some self registration code in the .ocx file, but when that's loaded, it's too late.
    jeffamaphone : You should be able to specify in the cab file an .exe to run first, unless they've tightened the security on that.
    Ori Pessach : Who's "they?"
    jeffamaphone : They is the IE team.
    Ori Pessach : Hmmm... I'm having trouble finding that bit in the documentation.
  • Apparently yes and no.

    It can happen but only if you "Hack" it via a security vulnerability. So not through any legitimate process, no.

    Here's an article describing the vulnerability state: http://www.juniper.net/security/auto/vulnerabilities/vuln16409.html

    And here's an article on Technet discussing how the DWORD ActiveX kills the process http://support.microsoft.com/default.aspx?scid=KB;EN-US;Q240797&sd=tech

    This is a quote from the MSDN website about ActiveX controls:

    "Users cannot directly interact with Microsoft ActiveX controls loaded by the APPLET, EMBED, or OBJECT elements. Users can interact with such controls after activating their user interfaces." http://msdn.microsoft.com/en-us/library/ms537508.aspx

    Ori Pessach : I'm sorry, but that's not exactly relevant to the question, although certainly an interesting topic in itself.
    EricLaw -MSFT- : Killbits have nothing to do with his question.
  • Have you tried using Javascript to kill the DOM element that your ActiveX control lives in? If you do this, IE will tell the control to unload, but you have to make sure the control WILL in fact unload. Then, you should be able to hit the page with the newer object reference, which will launch the newer object....

    Failing that, you may try opening a popup window that directs you to a page that never loads your object, and at the same time, using a named reference to the main browser, redirect it to a page that does not reference your object, giving it a chance to unload, then re-referencing your updated ActiveX. This should load your newer control.

    It's a sticky issue no matter which way you go, but you may be able to get it to do what you want.

    If your control does not behave properly, it may not unload properly, so that's something you have to watch out for.

    Larry

  • Can't you change the workflow? Check for the update first and avoid the whole problem!

    Whatever solution you implement, the browser is controlled by the client and any (security) updates or new versions can break your system.

    Ori Pessach : This isn't really an option. The problem is that some customers use an outdated version of the ActiveX (due to strict IT policies) and on some of their misconfigured machines IE tries to download the new ActiveX despite not having sufficient permissions to install it, so the application...
    Ori Pessach : gives a different version of the ActiveX to those users, but the ActiveX is also present on the login page, but that's the outdated version. There is a workaround, but it's not ideal. I'm still interested in an answer to my question.
  • Try the javascript delete statement:

    function unloadObject(objId) {
    
        var obj = document.getElementById(objId);
    
        obj.parentNode.removeChild(obj);
    
        delete obj;
    }
    

    Call unloadObject(targetActiveXTagId) before opening your second page.

    Ideally, you should build the upgrade mechanism into your ActiveX itself. I've seen several online game platforms does this with good results.

  • While I do not know of a way to get IE to unload a DLL (it keeps the DLL file handle open -- I hope it releases the objects themselves correctly...) one solution I use is to copy the DLL over to a temporary file (based on the Assembly version) before opening it and then explicitly breaking the IE/COM/whatever caching. Thus, I can get a "new" version loaded even though the old DLL filehandles are kept open.

    I have only been able to break the caching when all of these are met:

    1. Different ProgID (dynamically generated, may differ from DLL)
    2. Different CLSID (also dynamically generated -- works like a charm)
    3. Different DLL name (by making a copy of the orig. file and using the assembly version this avoids the DLL-in-use-access errors)
    4. Different Assembly version (this is for .NET)

    I am developing for a Sidebar Gadget so I can do the above with just some privileged ActiveX script-friendly components but a pre-loader (non-updated) ActiveX component may be able to do the job as well.

    I am relying on .NET/mscoree.dll to handle the COM stuff, so there might be a cleaner method going to a lower level.

    The different "versioning" is handled with temporal loads into the HKCU\Software\Classes structure.

0 comments:

Post a Comment