Flash Detect

Flash cannot be detected in Netscape 2, Explorer 3 and 4 on Mac, Konqueror and Ice Browser.

The Flash version cannot be detected in Opera 5 on Mac and Linux and Hotjava.

I have heard, but not tested, that detecting the Flash version works in iCab 2.7.1.

I have heard, but not tested, that this script works in Konqueror 3.2

This combination of JavaScript and VBScript will detect if your users have installed the Flash plugin and, if so, which version. After you have detected the presence/absence of the plugin, you can take appropriate measures.

First of all, let's see if you have Flash installed and, if so, which version:

JavaScript and VBScript

The theoretical way to detect the Flash plugin is to check either the array navigator.plugins or navigator.mimeTypes. These arrays are filled with all plugins and mime types the browser can handle and you can check them to see if it can deal with Flash movies.

Netscape 2 and Konqueror do not support either array, so you cannot detect Flash in those browsers.

The plugins array is by far the most interesting because it also contains version information, while the mimeTypes array only tells us whether the browser can handle the application/x-shockwave-flash mime type (= if Flash is installed). The mime type hasn't changed with Flash versions, though, so you cannot tell which version of Flash the user has.

Since Opera on Mac and Linux, iCab and Hotjava only support the mimeTypes array, detecting which Flash version is present is not possible in these browsers.

Explorer confuses the issue by leaving the arrays empty, even though both exist, so that according to JavaScript Explorer never has any plugins and does not support any mime types. The only exception to this rule is Explorer 5 on Mac, which supports both arrays (sensible decision!).

The only way to check for plugins in Explorer is by using VBScript. Here we encounter a new complication: Explorers on Mac do not support VBScript, so it is fundamentally impossible to detect any plugin in Explorer 3 and 4 on Mac. As I said, Explorer 5 on Mac supports the Netscape way.

Finally, the VBScript is supposed to produce error messages, so it is not exactly an example of clean coding. Until now I have found no better way.

The script

That said, let's go to the script:

<SCRIPT LANGUAGE="Javascript">
<!--

var flashinstalled = 0;
var flashversion = 0;
MSDetect = "false";
if (navigator.plugins && navigator.plugins.length)
{
	x = navigator.plugins["Shockwave Flash"];
	if (x)
	{
		flashinstalled = 2;
		if (x.description)
		{
			y = x.description;
			flashversion = y.charAt(y.indexOf('.')-1);
		}
	}
	else
		flashinstalled = 1;
	if (navigator.plugins["Shockwave Flash 2.0"])
	{
		flashinstalled = 2;
		flashversion = 2;
	}
}
else if (navigator.mimeTypes && navigator.mimeTypes.length)
{
	x = navigator.mimeTypes['application/x-shockwave-flash'];
	if (x && x.enabledPlugin)
		flashinstalled = 2;
	else
		flashinstalled = 1;
}
else
	MSDetect = "true";

// -->
</SCRIPT>

<SCRIPT LANGUAGE="VBScript">

on error resume next

If MSDetect = "true" Then
	For i = 2 to 6
		If Not(IsObject(CreateObject("ShockwaveFlash.ShockwaveFlash." & i))) Then

		Else
			flashinstalled = 2
			flashversion = i
		End If
	Next
End If

If flashinstalled = 0 Then
	flashinstalled = 1
End If

</SCRIPT>

Explanation

After the detect, the variable flashinstalled can have three values:

The variable flashversion contains the version of Flash. If the version is unknown, it is 0.

In this page I document.write a little message based on the value of these two variables. You'll have to decide exactly what to do with the information this script provides, especially what to do if you don't know if Flash is installed.

The JavaScript

First of all, make flashdetect and flashversion 0 (we don't yet know if Flash is installed and which version it is) and make MSDetect false. If we need the VBScript, it will be set to true.

var flashinstalled = 0;
var flashversion = 0;
MSDetect = "false";

We start the detect by seeing if navigator.plugins exists and, if it exists, if its length is larger than zero. After all, the array itself exists in Explorer, but it does not contain any data so its length is zero. The Netscape-style detect script that follows should only be executed if the array is actually filled with data.

if (navigator.plugins && navigator.plugins.length)
{

Then we try to find the plugin Shockwave Flash.

	x = navigator.plugins["Shockwave Flash"];

If it exists

	if (x)
	{

we know that Flash is installed, so we set flashinstalled to 2.

		flashinstalled = 2;

Then we see if the plugin object has a property description. (As far as I know every browser that supports navigator.plugins also supports description, but let's be careful)

		if (x.description)
		{

If it's supported, we extract the Flash version from it. The description is always something like Flash 4.0 r47. Therefore we take the number before the dot and put it in flashversion.

			y = x.description;
			flashversion = y.charAt(y.indexOf('.')-1);
		}
	}

If navigator.plugins["Shockwave Flash"] does not exist, Flash is probably not installed so we set flashinstalled to 1.

	else
		flashinstalled = 1;

Finally a special case: Flash 2 has a special plugin name Shockwave Flash 2.0. If this plugin is present, set the variables to Flash 2 detected:

	if (navigator.plugins["Shockwave Flash 2.0"])
	{
		flashinstalled = 2;
		flashversion = 2;
	}
}

If the plugins array is not supported, we see if the browser supports navigator.mimeTypes. Again check the length for Explorer's sake.

else if (navigator.mimeTypes && navigator.mimeTypes.length)
{

Now we see if navigator.mimeTypes['application/x-shockwave-flash'] exists, that is if this MIME type can be handled by the browser. If it can, we check its property .enabledPlugin, which is true if the plugin is actually installed (I don't really understand why there is an enabledPlugin property, in my view any plugin that's present is enabled by definition).
If it is, we set flashinstalled to 2, if it isn't we set it to 1. Unfortunately, navigator.mimeTypes doesn't tell us which version is installed.

	x = navigator.mimeTypes['application/x-shockwave-flash'];
	if (x && x.enabledPlugin)
		flashinstalled = 2;
	else
		flashinstalled = 1;
}

Netscape and the minor browsers are ready now.

If neither array is supported we make MSDetect true so that the VBScript will be executed. Of course this doesn't help Netscape 2, Konqueror and Explorer 3 and 4 on Mac a bit, since they don't support VBScript. Too Bad.

else
	MSDetect = "true";

The VBScript

The VBScript is not exactly an example of beautiful coding. In fact, the script is supposed to produce errors.

The main problem is that the detect is done by trying to create an object ShockwaveFlash.ShockwaveFlash.[versionNumber]. If this is done succesfully, the browser supports this version of Flash. If this version of the plugin is not installed, however, Explorer gives an error message because it cannot create the object.

Therefore we need to use the VBScript on error event handler to tell Explorer to continue the script, no matter what.

<SCRIPT LANGUAGE="VBScript">

on error resume next

Then for the actual detect. First of all we check if MSDetect is true. If it is, we execute the rest of the VBScript.

If MSDetect = "true" Then

Now we try to create objects. Flash 2 is called ShockwaveFlash.ShockwaveFlash.2, Flash 3 is called ShockwaveFlash.ShockwaveFlash.3 etc. So what we need to do is create all these objects and see which one of them doesn't give an error.

So we go through the versions

	For i = 2 to 6

and try to create an object for Flash version i

		If Not(IsObject(CreateObject("ShockwaveFlash.ShockwaveFlash." & i))) Then

Now we come to the dirty bit. If Flash version i is not supported, the browser gives an error, but since we told it to resume next it will nonetheless execute the next command. However, if the Flash version is not supported, we don't want anything to happen. That's why we check if the object is not present (Not(IsObject(etc))) and if it isn't (if the error occurs) nothing should be done:

[that's right, nothing]

If the object can be created and is present, we've found the installed Flash version. We set flashinstalled to 2 and flashversion to i.

		Else
			flashinstalled = 2
			flashversion = i

End all stuff, this is required in VBScript, it's the equivalent of closing brackets } in JavaScript.

		End If
	Next
End If

If, after we've checked all possible versions, flashinstalled is still 0, it means that Flash is not installed. Therefore we make it 1. We've tried to find Flash, but didn't find it.

If flashinstalled = 0 Then
	flashinstalled = 1
End If

That's it. Now you only have to write a little script that reads out flashinstalled and flashversion and gives commands for the several situations. Think carefully about what should happen if you don't know if Flash is installed.

Flash detect without JavaScript

There is a way of detecting Flash without JavaScript. You have to create a tiny Flash movie that redirects the user to the Flash page and place it on a page with a META refresh that redirects the user to the non-Flash page. If Flash works, the Flash redirect comes first, if it doesn't work the browser executes the META refresh. For more details see the Macromedia site.

Detecting other plugins

Theoretically, using this script you should be able to detect other plugins. However, it rarely succeeds. You have to find the correct MIME type for the Netscape style detect and the correct VB Object for the Explorer style detect. Find the object by starting up your registry editor (Start -> Run -> Regedit), opening to HKEY_CLASSES_ROOT and selecting the file extension of the plugin you want to detect. The 'Content Type' entry holds the MIME type, the 'Default' entry contains the VB Object we need.

Rewrite the function for the new objects, then try it. Unfortunately I cannot guarantee anything, some plugins work differently.

Real Player

However, a reader has succeeded in implementing this detect for Real Player:

Acrobat

It's also rumoured to work for Adobe Acrobat:

So to detect a specific version of Acrobat you have to use a loop similar to the one in the VBScript above.

If you succesfully use this script to detect another plugin, please let me know.

Pure JavaScript

A reader proposed the following script to get rid of the VBScript:

// IE flash detection.
	for(var i=7; i>0; i--){
		flashVersion = 0;
		try{
			var flash = new ActiveXObject("ShockwaveFlash.ShockwaveFlash." + i);
			flashVersion = i;
			return;
		}
		catch(e){
		}
	}

I haven't actually tried it myself yet, and it uses the try/catch construct that I want to avoid for older browsers' sake, but this solution is certainly interesting.