Detecting plugins in Internet Explorer (and a few hints for all the others)

There’s a lot of bad information out there about detecting plugins in Internet Explorer. I know; I spent days crawling through it all in order to create a plugin detection tool for a client. It’s not that the code you’ll find in the crevices of those forgotten pages doesn’t work. It does. The problem is that virtually all of it is grossly inefficient and almost immediately outdated because it’s version-based and has to be updated with each new plugin release. On top of that, some of it still uses VBScript, or even worse, JavaScript that writes VBScript. Since plugin detection itself continues to be necessary in some unique situations, I was determined to find a way to do it that didn’t require constant maintenance.

The problem is that no one quite knows what to look for when dealing with Internet Explorer’s plugins. Plugins in IE are ActiveX-based, so there’s no single API for them all—each has its own method of returning, for example, version information. What this basically means is that while Firefox and other browsers are putting all of their plugin information in one handy place, Internet Explorer is jealously guarding its plugin-related secrets. It’s like the Dick Cheney of browsers. And we are, um, the Information Security Oversight Office in that analogy.

Er… let’s just jump right in with some working detection code.

Adobe Reader

Detecting Adobe Reader (formerly Acrobat Reader) is pretty straightforward, except for the hitch that the ActiveX control was renamed in version 7. The key for version detection here is GetVersions(). Unfortunately, no version information is available for Adobe Reader 8 and later for non-IE browsers.

var isInstalled = false;
var version = null;
if (window.ActiveXObject) {
  var control = null;
  try {
    // AcroPDF.PDF is used by version 7 and later
    control = new ActiveXObject('AcroPDF.PDF');
  } catch (e) {
    // Do nothing
  }
  if (!control) {
    try {
      // PDF.PdfCtrl is used by version 6 and earlier
      control = new ActiveXObject('PDF.PdfCtrl');
    } catch (e) {
      return;
    }
  }
  if (control) {
    isInstalled = true;
    version = control.GetVersions().split(',');
    version = version[0].split('=');
    version = parseFloat(version[1]);
  }
} else {
  // Check navigator.plugins for "Adobe Acrobat" or "Adobe PDF Plug-in"*
}

* Nicole Lucas adds that “Adobe Acrobat” won’t work with Adobe Reader 8 because Adobe changed the name to “Adobe PDF Plug-In for Firefox and Netscape”. Thanks, Nicole.

Flash Player

Flash is even easier. The version method in this case is GetVariable('$version').

var isInstalled = false;
var version = null;
if (window.ActiveXObject) {
  var control = null;
  try {
    control = new ActiveXObject('ShockwaveFlash.ShockwaveFlash');
  } catch (e) {
    return;
  }
  if (control) {
    isInstalled = true;
    version = control.GetVariable('$version').substring(4);
    version = version.split(',');
    version = parseFloat(version[0] + '.' + version[1]);
  }
} else {
  // Check navigator.plugins for "Shockwave Flash"
}

Java Runtime Environment

The JRE (formerly Java Virtual Machine, or JVM) is actually more difficult to handle than you would think. Determining if Java is installed is easy—a quick call to navigator.javaEnabled() returns a simple Boolean.* The problem is detecting the version and provider (Microsoft or Sun).

I never found a satisfactory solution to this. The gist is this: to get this information, you must load a Java applet. To load the Java applet, you must do it externally. But when an applet is loaded externally, it doesn’t load right away, so any programmatic calls to the exposed class methods must be delayed. And dealing with this with setTimeout() is awkward.

Nevertheless, here’s what I ended up with:

var isInstalled = navigator.javaEnabled();
if (!isInstalled) {
  return;
}

// Get version
var version = null;
if (/*@cc_on ! @*/ false) { // This JRE check does not depend on ActiveX, only IE
  // IE requires the 'classid' attribute upon object creation.
  var element = '<object classid="clsid:8AD9C840-044E-11D1-B3E9-00805F499D93">';
  var applet  = document.createElement(element);
  applet.id = 'applet';

  // IE requires that objects be displayed in order to interact with them
  applet.style.width  = '1px';
  applet.style.height = '1px';

  // Create and append the object's 'code' parameter
  var param = document.createElement('param');
  param.name  = 'code';
  param.value = 'JavaDetector.class';
  applet.appendChild(param);

  // Append the applet to <body>
  document.body.appendChild(applet);

  // Attempt to get the version
  var window.java = new Object();

  // Synchronous calls to getVendor(), etc. result in an exception, but despite
  // the timeout of 0 this call will not execute immediately
  setTimeout(function() {
    try {
      var applet = document.getElementById('applet');
      window.java.vendor  = applet.getVendor();
      window.java.version = parseFloat(applet.getVersion());
    } catch (e) {
      // Do nothing
    }
  }, 0);
} else {
  if (typeof java != 'undefined') {
    version = java.lang.System.getProperty('java.version');
  } else {
    // Look for "Java Plug-in", "Java (version) Plug-in", and "Java Plug-in for Cocoa"
  }
  version = parseFloat(version);
}

And your Java class looks something like this:

public class JavaDetector extends java.applet.Applet {
    public static String getVendor() {
        String vendor = null;
        try {
            vendor = System.getProperty("java.vendor");
        } catch (Exception e) {
            vendor = "Microsoft Corp.";
        }
        return vendor;
    }

    public static String getVersion() {
        return System.getProperty("java.version");
    }
}

* Eric Gerds adds that “navigator.javaEnabled() does not reveal whether Java is installed or not in IE.” Apparently disabling Java in IE merely disables the applet tag. Applets can still be loaded with the object tag despite javaEnabled() returning false. As such, you may want to modify this code. See his complete comment below.

QuickTime Player

QuickTime is another one that poses difficulty for IE. Detecting it is simple enough: just check for QuickTime.QuickTime. But detecting the version poses other problems. The ActiveX control that returns version information for QuickTime must be enabled manually in Internet Explorer 7. When called, the user is prompted. Although it saves that information for all future visits to that page, the code that follows will typically return null for the version number the first time around. Unfortunately, I’ve found no good way to reliably detect the version through ActiveX alone.

The version number that you do receive isn’t immediately useful. The QuickTimeVersion property is in hexadecimal (for whatever reason), so you’ll need to convert it by calling QuickTimeVersion.toString(16) and then manually assembling the number.

var isInstalled = false;
var version = null;
if (window.ActiveXObject) {
  var control = null;
  try {
    control = new ActiveXObject('QuickTime.QuickTime');
  } catch (e) {
    // Do nothing
  }
  if (control) {
    // In case QuickTimeCheckObject.QuickTimeCheck does not exist
    isInstalled = true;
  }

  try {
    // This generates a user prompt in Internet Explorer 7
    control = new ActiveXObject('QuickTimeCheckObject.QuickTimeCheck');
  } catch (e) {
    return;
  }
  if (control) {
    // In case QuickTime.QuickTime does not exist
    isInstalled = true;

    // Get version
    version = control.QuickTimeVersion.toString(16); // Convert to hex
    version = version.substring(0, 1) + '.' + version.substring(1, 3);
    version = parseFloat(version);
  }
} else {
  // Check navigator.plugins for "QuickTime Plug-in"
}

RealPlayer

Because it’s had so many names (five, that I can count), RealPlayer is still one of the more inefficient plugins to check for. Thankfully, they’ve kept the API the same, however, so checking for the version is still just GetVersionInfo().

var isInstalled = false;
var version = null;
if (window.ActiveXObject) {
  var definedControls = [
    'rmocx.RealPlayer G2 Control',
    'rmocx.RealPlayer G2 Control.1',
    'RealPlayer.RealPlayer(tm) ActiveX Control (32-bit)',
    'RealVideo.RealVideo(tm) ActiveX Control (32-bit)',
    'RealPlayer'
  ];

  var control = null;
  for (var i = 0; i < definedControls.length; i++) {
    try {
      control = new ActiveXObject(definedControls[i]);
    } catch (e) {
      continue;
    }
    if (control) {
      break;
    }
  }
  if (control) {
    isInstalled = true;
    version = control.GetVersionInfo();
    version = parseFloat(version);
  }
} else {
  // Check navigator.plugins for "RealPlayer" and "RealPlayer Version"
}

Shockwave Player

Thankfully, Macromedia always made an effort to remain consistent with their naming. Thus, one simple call can detect any version of Shockwave. The version check here is ShockwaveVersion('')—yes, you must pass it an empty string.

var isInstalled = false;
var version = null;
if (window.ActiveXObject) {
  var control = null;
  try {
    control = new ActiveXObject('SWCtl.SWCtl');
  } catch (e) {
    return;
  }
  if (control) {
    isInstalled = true;
    version = control.ShockwaveVersion('').split('r');
    version = parseFloat(version[0]);
  }
} else {
  // Check navigator.plugins for "Shockwave for Director"
}

Windows Media Player

Windows Media Player is probably the easiest one to detect of them all, but also the most unreliable on non-Internet Explorer browsers. Firefox users will typically be missed here unless they’ve installed the WMP for Firefox plugin. The relevant version property is versionInfo.

var isInstalled = false;
var version = null;
if (window.ActiveXObject) {
  var control = null;
  try {
    control = new ActiveXObject('WMPlayer.OCX');
  } catch (e) {
    return;
  }
  if (control) {
    isInstalled = true;
    version = parseFloat(control.versionInfo);
  }
} else {
  // Check navigator.plugins for "Windows Media"--this also detects the Flip4Mac plugin
}

Phew! That’s that. I can’t guarantee these are the best methods of detecting plugins in Internet Explorer, but they’re the best I came up with. If you’re aware of easier solutions, let me know and I’ll update this post.

Incidentally, if you need a comprehensive solution, I recommend putting these into a class structure—for my project, I used an abstract base class that each plugin class extended, and an overall plugin detection class that called each class’s self-detection method. Extensible, self-contained, and unobtrusive.

Like this post? You might also like Coalmine, my centralized error tracking service for your apps. Coalmine captures errors and all kinds of helpful debugging information, notifies you, and makes it all searchable. Check it out!

Tags: , , , ,

34 comments

  1. navigator.javaEnabled() does not reveal whether Java is installed or not in IE. It merely tells you if the applet tag is enabled or disabled.

    You can disable the applet tag in the IE security settings … Tools -> Internet Options -> Security -> Custom Level -> Java Permissions -> Disable Java

    This will cause javaEnabled() to be false, yet Java is still installed. For that matter, it isn’t disabled either. Only the applet tag is disabled.

    You can still display a Java applet using the object tag (with a classid/ActiveX) while javaEnabled() is false.

  2. Great resource, saved my day.

  3. Check navigator.plugins for “Adobe Acrobat” won’t work with Adobe Reader 8 as it’s name changed to “Adobe PDF Plug-in for Firefox and Netscape” instead of it’s previous name “Adobe Acrobat…”

  4. I found ur flash detection script very usefull…Thx for the stuff

  5. this is great! it’s so nice to find a script that simply does what you need without all the bloat. thank you.

  6. Instead of “Adobe PDF Plug-in for Firefox and Netscape” should be “Adobe PDF Plug-In for Firefox and Netscape”

  7. the detectQuickTime() function returns a number like 7.3.1 for Firefox, but 7.31 for IE. I think I see why you can’t get the correct version number of 7.3.1. It makes it incorrect though. 7.10.1 would become 7.10 which would also be equal to 7.1.0

    So, there is know way to know what version they have installed without making assumptions. And you know what assumptions make… and ass out of u and me. Arrgggh. Thanks for the resource and providing the best available solution.

  8. In case someone needs it. I think this will solve the problem of how IE returns the version in QuickTime. Replace these two lines

    version = version.substring(0, 1) + '.' + version.substring(1, 3);
    version = parseFloat(version);

    with these two

    version = parseInt(version.substring(0, 1),16) + '.' + parseInt(version.substring(1, 2),16) + "." + parseInt(version.substring(2, 3),16);
    version = version;
  9. Thanks for the info. The Adobe PDF stuff works like a charm, and I’m definitely bookmarking this for the Flash rollout. I don’t suppose there’s a way I can figure out the properties and methods of Adobe’s SVG viewer? I’ve combed the Adobe developer center with no luck so far.

    Again, thanks for sharing the awesome info!

    - cubiclegrrl

  10. Just found the answer here (http://wiki.svg.org/Interface_Definition_For_ASV) after a little more digging and a lot more dumb luck. So I thought I’d pass it on for anyone else who might have the same issue/question.

    Thanks again!

  11. Thanks for this blog – unfortunately I found it after much digging myself into this and sorting out something similar. I’m still left with a problem which is this: although detecting whether something is installed is a great way towards solving my problem, how can I find out whether a plug-in is enabled in IE. In Netscape-based browsers you can use navigator.mimeTypes['video/quicktime'].enabledPlugins. Is there anything for IE?

  12. @Steve

    Sorry, I don’t think there’s a way to check that in IE. If you find a way, please post it!

  13. Thanks for the tutorial.
    Any idea if it’s possible to install a plugin using JAVASCRIPT ?

  14. Great text, thank you.

    Loved the remark about Dick Cheney and IE. :)

    I have an error, when I start the code in IE I get “‘return’ statement outside of function.”.

  15. Interesting work. How you find the name of the activeX plugin? Specifically, I’m trying to find what the GoogleEarth plugin is named. Is it in the registry somewhere? Or is there someplace obvious in IE?

    Thanks.

  16. This is definitely one of the best tutorial i ever came across with. Nice tip, thanks for shaing with us.

  17. @Carl

    Research on Google. Some of the harder-to-find ones I found on mailing list archives.

  18. Are the try-catches necessary? Will the compiler stop if ActiveX is disabled?

  19. if (navigator.plugins) {
      var n = navigator;
      var l = n.plugins.length;
      var d = document;
      if (l < 0) {
        for (i = 0; i < l; i++) {
          var pl = n.plugins[i];
          var f = pl.filename.substring(pl.filename.lastIndexOf('\') + 1, pl.filename.length);
          document.write('
    <b>name:</b> ' + pl.name + ' <b>description:</b> ' + pl.description + ' ' + i + ' <b>file:</b> ' + f + '');
        }
      }
    }
  20. “Adobe Acrobat” as the plugin nam works for all versions

  21. Great article, I incorporated the above into a script for all major browsers to detect pdf reading capabilities. Even distinguishes between Chrome’s PDF Viewer and Acrobat. you can get the code here:

    Detecting Adobe Acrobat in all browsers

  22. @apostol:

    That won’t work for IE and you’ve got a code typo.

    if (l < 0) {
  23. Thanks for your useful scripts!

  24. How to use the Adobe Acrobat plugin for windows phone 7 applications? Can anyone help me with this? Thanks in advance for your hard work!

  25. Wow! QuickTime player detection script for IE works like a charm. Thanks again!

  26. Please let me know how to detect if Adobe Acrobat X Pro is installed?

    I tried with ‘AcroPDF.PDF’ & ‘PDF.PdfCtrl’ is goven above but it is not working.

  27. I find ur flash and it’s version detection logic very useful. I have a ques for u. Similar to GetVariable(“version”) is there any way to find out whether the flash plugin is currently enabled or disabled by the user ? Do we have any properties or method supported by Ie to get more info other than version with an shockwave aactiveX object

  28. Hi there, I check your blogs like every week. Your
    story-telling style is witty, keep it up!

    Feel free to surf to my blog post … Adobe Crobat XI Pro Crack

  29. Aw, this was an extremely good post. Spending some time and actual effort to make a
    very good article… but what can I say… I procrastinate a lot
    and don’t manage to get nearly anything done.

Leave a comment