ShellExecute with html document doesn't work reliably with Netscape 
Author Message
 ShellExecute with html document doesn't work reliably with Netscape

I frequently see the following code posted as an answer to the question of
how to start a Web Browser and have it display a particular Web page:

   hDeskTop = GetDesktopWindow();

   hBrowser = ShellExecute( hDeskTop,
                            "open",
                            pszUrl,  /* Document name and path. */
                            NULL,    /* No parameters, since this is a doc.
*/
                            NULL,    /* Default directory, NULL for doc. */
                            0);      /* Must be 0 for a document. */

Unfortunately, in my experience, this code does not work reliably with
Netscape unless Netscape has already been started by the user.  Version 3.x
of Netscape will start, but never displays the page (even if the page is in
a local html file.)  Version 4.0  of Netscape doesn't start at all on the
systems in a computer lab at a local university.  And yet, if the user
double-clicks on an .htm file in Explorer, Netscape does start and does
display the local htm file.

In these cases, ShellExecute does not return an error value. Has anyone
else run into this problem? Does anyone know why ShellExecute is unreliable
with Netscape?

The same code works every time with Internet Explorer.

TIA,
Al Margheim



Mon, 20 Dec 1999 03:00:00 GMT  
 ShellExecute with html document doesn't work reliably with Netscape

Quote:

>   hBrowser = ShellExecute( hDeskTop, "open", pszUrl,  /* Document name and path. */
>Unfortunately, in my experience, this code does not work reliably with
>Netscape unless Netscape has already been started by the user.

Al, I'm reposting an article originally sent by John Grant because it was
a very good and comprehensive one, and because it might well be related.

-------------

Subject: ShellExecuting a URL: Final Solution (?) & Bug Fix
Organization: Natural Resources Canada, Ottawa
Date: Mon, 21 Oct 1996 05:42:58 GMT

Synopsis:
--------
ShellExecuting a URL on Windows '95 will work for either Win16 or Win32 apps,
if your browser installed URL.DLL with the correct registry keys. Netscape
does it wrong, so you have to fix it first.

HCW breaks the ShellExecute() macro, so use the ExecFile() macro instead.

Introduction
------------
I'm finally getting around to posting this information. It concerns the
use of ShellExecute() to 'run' a URL on Windows '95 (not 3.x).  There are
5 parts:
  0. requirement
  1. false solutions
  2. the real solution
  3. Netscape installation bug
  4. WinHelp & ShellExecute + HCW bug

0. Requirement
   -----------
   A long time ago, the question of ShellExecuting a URL came up. Several
   solutions were posted. Raymond Chen (unofficial Microsoft guru here)
   said something like:

   "just use ShellExecute(hwnd,0,"http://your.web.page/here",0,0,SW_NORMAL)"

   There were also several other answers. So I tried ShellExecute() on a
   Windows '95 system and I could *not* get it to work. So I asked again.

1. False Solutions
   ---------------
   Several solutions were posted here and I received some by e-mail.
   But Ray Chen had stated quite clearly that ShellExecute() would work.
   Here are Ray's comments (marked RC) on some of the answers that appeared
   here:

   (a) "Create a .url file that looks like:
        [internetShortcut]
        URL=http://your.web.page/here"

        RC: Don't do this. The format of an internal shortcut file may change
            in the future. If you need to access the contents of .URL files,
            use the IUniformResourceLocator interface. But if all you want
            to do is exec a URL, just pass the URL to ShellExecute().

   (b)  "Use ShellExecuteEx instead"
        RC: ShellExecuteEx() also works, but isn't required

   (c)  "it only only works if you have Plus! or Internet Explorer"
                &
        "It will only launch Microsoft Internet Explorer, not Netscape"
        RC: Microsoft Internet Explorer installs URL.DLL, but is hardly
            the only program that does so.
            Internet Explorer 1.0 came with Plus!

   (d)  "You need wininet.dll"
        RC: red herring

   (e)  "It only works if you execute a shortcut"
        RC: it works with a shortcut, but it also works with a plain URL

   (f)  "You have to look up HKEY_CLASSES_ROOT\http\shell\open\command to
        get "c:\program files\plus!\Micros~`\iexplorer.exe -nohome %1"
        and then fiddle with that"
        RC: This is one of the registry steps that is supposed to have
            been done by the browser. This is one of the places where
            the default browser is registered, and it's one of the places
            where URL.DLL looks (you also register the browser in the
            DDEExec section of the http\shell\open key if your browser
            supports DDE). Normal applications shouldn't care.

   (g)  "You have to look up .html or .htm or http in the registry and
        WinExec it yourself"
        RC: sheer desperation

2. The Real Solution
   -----------------
   Here's what Ray said in earlier comments here:


     prefixes and runs the program that is recorded in the registry as "the
     program that handles this type of URL".  (Actually, ShellExecute asks
     URL.DLL to do this work, so if you don't have URL.DLL on your system,
     then ShellExecute'ing a URL won't work.  But all the popular web
     browsers install URL.DLL, so there shouldn't be a problem there)"

   and here he provides much more detail:

   "The file that teaches ShellExecute how to handle URLs is URL.DLL.
    URL.DLL is a redistributable DLL that IE and Netscape both install.

    URL.DLL weasels into the ShellExecute function by adding itself
    to HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\
    Explorer\ShellExecuteHooks.

    None of this information is supposed to concern you.

    The basic answer is: Any browser that is designed for Windows 95
    (or Windows NT 4.0) will install URL.DLL and do the magic registry goo.
    At which point, ShellExecute of a URL will launch the browser.

    If this isn't working, then it means that some step in the installation
    procedure isn't working."
                ---

  Ok, so I had installed Netscape and sure enough URL.DLL was there. But it
  *still* would *NOT* work for me. Why not? Well, because Netscape put the
  magic key in the wrong place! Read on.

3. Netscape Installation Bug
   -------------------------
   Fire up Regedit and do a search for ShellExecuteHooks. If you have
   installed Netscape you will find it in:
        HKEY_CURRENT_USER
        HKEY_USERS

   But Ray clearly states that the key must be located in HKEY_LOCAL_MACHINE.

   If you have installed Plus!, Internet Explorer or possibly Microsoft
   Office?), you will probably also find it in HKEY_LOCAL_MACHINE.

   If this works for you:
        c:\> start http://www.microsoft.com

   then you probably have the key in HKEY_LOCAL_MACHINE where Ray says it
   is supposed to be.  If not, then you need to fix it by putting the
   same key you find in HKEY_CURRENT_USER in the correct location, i.e.
   HKEY_LOCAL_MACHINE.

   I don't know what this looks like on a single-user Netscape setup, but
   for our network-licenced version, the file containing the error is in
        ...netscape\_istmp0.dir\reg.url

   There are 4 HKEY_CURRENT_USER keys in there. I don't know about all of
   them, but ShellExecuteHooks should be in HKEY_LOCAL_MACHINE.

   I have tried out several W95 systems around here. Some of them were ok
   (had installed Microsoft Office which probably fixed it), but most were
   broken because of this key.  When I fixed it, everything worked ok,
   including:
        - a Win16 program calling ShellExecute(.."http://...")
        - a Win32 program calling ShellExecute(.."http://...")
        c:\> start http://...

   where *NONE* of these worked before.

4. WinHelp, ShellExecute & HCW Bug
   -------------------------------
   First of all, none of this URL.DLL magic works on Windows 3.x. There
   are ways around that which involve a custom DLL function, but they
   do not concern me here (apparently there is a recent article in DDJ
   on doing this magic in Windows 3.x). I'm only concerned about Windows
   '95 & URL.DLL

   (a)  for a Win16 .HLP file on Windows '95
        add this to your .hpj:
                [config]
                RegisterRoutine("shell","ShellExecute","USSSSi")

        and in your .HLP file, just call the ShellExecute API function
        like so:
                !ShellExecute(hwndApp,"open","http://...","","",1)

        For some reason, "" doesn't work - use "open". The docs for
        the ShellExecute() API function say that NULL will give you the
        default verb which is "open", but they don't say that "" will also
        give you "open". NULL is not the same as "": it all depends on
        how ShellExecute() is written. Anyway the explicit "open" works.

        *IF* you have the ShellExecuteHooks key in the correct
        HKEY_LOCAL_MACHINE, you should be able to click on that link and
        run the browser. It works for me.

   (b)  for a Win32 .HLP file on Windows '95
        Remove any RegisterRoutine for ShellExecute from your .HPJ. You
        don't need it because there is a built-in ShellExecute() macro.

        This is where I had a lot of problems. I tried all combinations
        that I could imagine for ShellExecute() args and I couldn't even
        get it to ShellExecute() a 'hello.wri' file(!), let alone get it
        to work with a URL. Everytime I clicked on it, I got a runtime
        error: "missing ')' 1031".

        BaDge helped me out on this one. He pointed out the following bug
        (#19) from the WH 4 buglist:

        "Internal ShellExecute commands that use the 4th, 5th or 6th
        parameters (operation, path or topic ID) do not work. Only
        the first three parameters can be used. Reported by Microsoft"

        Well, not quite. I couldn't even get it to work using a single
        argument...

        My problems weren't related to incorrect operation of ShellExecute.
        The problems are caused by HCW screwing up when it compiles the
        code. It adds bogus `' arguments at the end of the macro call.
        For example, if I used:
                !ShellExecute("hello.wri")
        the .HLP file ended up containing:
                SE(`hello.wri'`'5)      (HCW translates it to SE)

        No compilation errors, but when you click on it, you get something
        like "missing ')' (1031)". I wasted several days on that before BaDge
        looked in the .HLP file and found it. HCW had inserted '`' and
        effectively trashed the .HLP file. I'm not sure if that's what bug
        #19 is referring to or not.

        If you're really a mechanic, you can fix the .HLP by using a hex
        editor on it, *if* you're really careful and know what you're doing.
        Not recommended.

        My solution? I discarded ShellExecute() & ended up using ExecFile()
        instead. Presumably it calls the ShellExecute API function which
        is what the ShellExecute() macro would do anyway.

        Once again: it won't work unless ShellExecuteHooks is in
        HKEY_LOCAL_MACHINE

        I shold note here that this is version 4.00.0950 of HCW that came
        with the Watcom compiler. What is the current version? Is there
        a way to obtain a newer version? From Watcom or Microsoft?

Summary:
-------
1. check your registry and make sure ShellExecuteHooks() is in
   HKEY_LOCAL_MACHINE. If not, copy it and insert it there.

2. c:\> start http://... should work ok

3. your Win16 or Win32 .exe apps can now ShellExecute() a URL directly

4. your Win16 .HLP files can also ShellExecute a URL directly (use
   RegisterRoutine in your .hpj)

5. your Win32 .HLP files can also ...

read more »



Mon, 20 Dec 1999 03:00:00 GMT  
 ShellExecute with html document doesn't work reliably with Netscape



Quote:
>And yet, if the user
>double-clicks on an .htm file in Explorer, Netscape does start and does
>display the local htm file.

That's strange, because all Explorer does when you double-click on a
filename is do a "ShellExecute" on the file!

Chris

----------------------------------------------------------------
Chris Marriott, Microsoft Certified Solution Developer.

Visit our web site at http://www.skymap.com



Mon, 20 Dec 1999 03:00:00 GMT  
 ShellExecute with html document doesn't work reliably with Netscape

: I frequently see the following code posted as an answer to the question of
: how to start a Web Browser and have it display a particular Web page:

:    hDeskTop = GetDesktopWindow();

:    hBrowser = ShellExecute( hDeskTop,
:                             "open",
:                             pszUrl,  /* Document name and path. */
:                             NULL,    /* No parameters, since this is a doc.
: */
:                             NULL,    /* Default directory, NULL for doc. */
:                             0);      /* Must be 0 for a document. */

: Unfortunately, in my experience, this code does not work reliably with
: Netscape unless Netscape has already been started by the user.  Version 3.x
: of Netscape will start, but never displays the page (even if the page is in
: a local html file.)  Version 4.0  of Netscape doesn't start at all on the
: systems in a computer lab at a local university.  And yet, if the user
: double-clicks on an .htm file in Explorer, Netscape does start and does
: display the local htm file.

: In these cases, ShellExecute does not return an error value. Has anyone
: else run into this problem? Does anyone know why ShellExecute is unreliable
: with Netscape?

: The same code works every time with Internet Explorer.

: TIA,
: Al Margheim

:  



Tue, 21 Dec 1999 03:00:00 GMT  
 ShellExecute with html document doesn't work reliably with Netscape




: >And yet, if the user
: >double-clicks on an .htm file in Explorer, Netscape does start and does
: >display the local htm file.
:
: That's strange, because all Explorer does when you double-click on a
: filename is do a "ShellExecute" on the file!
:
: Chris

I know.  Actually, I have to apologize because I mis-stated the problem.
The problem I'm having is with URLs on the net, not local html files, and
the problem occurs with both Internet Explorer and Netscape.  In other
words, if test.htm is present, the code below works everytime on the
systems I've tested with:

hBrowser = ShellExecute( HWND_DESKTOP,  "open",
                                       "c:\\test.htm",  
                                       NULL,  NULL,  0);  

but the code below works only if the browser was already started:

hBrowser = ShellExecute( HWND_DESKTOP,  "open",
                                       "http://www.microsoft.com/",  
                                       NULL,  NULL,  0);  

And, to further complicate the situation, it *does not work*  if the
browser was first started by double-clicking on a local html file in
Explorer.   In other words this sequence fails:

1.  Reboot system (just to start from a known state.)
2.  Double-click on a local html file in Explorer.
3.  Explorer will start and display the html file.
4.  Run a test program that performs the ShellExecute statement to display
www.microsoft.com.
5.  Watch Explorer as it attempts to connect to www.microsoft.com and
eventually times out.

However, this sequence works:

1.  Reboot system.
2.  Start Internet Explorer and goto some URL on the net.
3.  Run the same test program as in step 4 above.
4.  Watch Internet Explorer as it connects to www.microsoft.com.

After I posted my question, I searched DejaNews and found several threads
that confirm that quite a few other people have had similar problems.
Apparently, there are several known causes and perhaps a few unknown
causes.  Older versions of Netscape did not update the registry correctly,
corrupted or older versions of URL.DLL can cause the problem, and certain
configuration options in Netscape 4.0 can cause the problem.

All-in-all it appears to be a somewhat fragile mechanism for displaying
URLs.

Al Margheim



Tue, 21 Dec 1999 03:00:00 GMT  
 ShellExecute with html document doesn't work reliably with Netscape

: hBrowser =3D ShellExecute( HWND_DESKTOP,  "open",=20
:                                        "c:\\test.htm", =20
:                                        NULL,  NULL,  0);  =20

Just noticed something .... The MSDN states that "The Win32 API includes =
special constants that can replace a window handle in *certain =
functions*."=20

ShellExecute() doesn't list HWND_DESKTOP as an alternative available for =
this API.  SendMessage, SendMessageTimeout functions, and =
MapWindowPoints do provide for substituting a constant.  Not that this =
is necessarily contributing to your problems, but worth noting.

Also, again perhaps moot, is your use of the NULL word above.  I suspect =
it was for illustrative purposes, as the VB keyword Null can't be passed =
in place of an expected 0&.

--=20
Randy Birch, MVP Visual Basic

Moderator, Fidonet Visual Basic Programmer's Conference
VBnet, The Visual Basic Developers Resource Centre
http://home.sprynet.com/sprynet/rasanen/



: =20

:=20


: : >And yet, if the user
: : >double-clicks on an .htm file in Explorer, Netscape does start and =
does
: : >display the local htm file.
: :=20
: : That's strange, because all Explorer does when you double-click on a
: : filename is do a "ShellExecute" on the file!
: :=20
: : Chris
:=20
: I know.  Actually, I have to apologize because I mis-stated the =
problem.=20
: The problem I'm having is with URLs on the net, not local html files, =
and
: the problem occurs with both Internet Explorer and Netscape.  In other
: words, if test.htm is present, the code below works everytime on the
: systems I've tested with:
:=20
: hBrowser =3D ShellExecute( HWND_DESKTOP,  "open",=20
:                                        "c:\\test.htm", =20
:                                        NULL,  NULL,  0);  =20
:=20
: but the code below works only if the browser was already started:
:=20
: hBrowser =3D ShellExecute( HWND_DESKTOP,  "open",=20
:                                        "http://www.microsoft.com/", =20
:                                        NULL,  NULL,  0);  =20
:=20
: And, to further complicate the situation, it *does not work*  if the
: browser was first started by double-clicking on a local html file in
: Explorer.   In other words this sequence fails:
:=20
: 1.  Reboot system (just to start from a known state.)
: 2.  Double-click on a local html file in Explorer.
: 3.  Explorer will start and display the html file.
: 4.  Run a test program that performs the ShellExecute statement to =
display
: www.microsoft.com.
: 5.  Watch Explorer as it attempts to connect to www.microsoft.com and
: eventually times out.
:=20
: However, this sequence works:
:=20
: 1.  Reboot system.
: 2.  Start Internet Explorer and goto some URL on the net.
: 3.  Run the same test program as in step 4 above.
: 4.  Watch Internet Explorer as it connects to www.microsoft.com.
:=20
: After I posted my question, I searched DejaNews and found several =
threads
: that confirm that quite a few other people have had similar problems.=20
: Apparently, there are several known causes and perhaps a few unknown
: causes.  Older versions of Netscape did not update the registry =
correctly,
: corrupted or older versions of URL.DLL can cause the problem, and =
certain
: configuration options in Netscape 4.0 can cause the problem.
:=20
: All-in-all it appears to be a somewhat fragile mechanism for =
displaying
: URLs.
:=20
: Al Margheim
:=20
:=20
:=20
:=20
:



Tue, 21 Dec 1999 03:00:00 GMT  
 ShellExecute with html document doesn't work reliably with Netscape


Quote:
>   hBrowser = ShellExecute( hDeskTop,
>                            "open",
>                            pszUrl,  /* Document name and path. */
>                            NULL,    /* No parameters, since this is a doc.
>*/
>                            NULL,    /* Default directory, NULL for doc. */
>                            0);      /* Must be 0 for a document. */

Yes, the docs say "must be 0 for a document" ... I don't know why. The
following works for ANYTHING the shell knows how to execute, and fails
often (on documents, as you mentioned) when I replace SW_SHOW with 0.

//SE.CPP
#include <windows.h>
HINSTANCE main ( int argc, char * argv[] )
{
return ShellExecute(NULL, "open", argv[1],
        (argc > 2) ? argv[2] : NULL,
        (argc > 3) ? argv[3] : NULL,
        SW_SHOW);

Quote:
}

This raises another question about which I'm curious: I use the above
little program from the command line and batch files, and no matter
what SW_* flag I use in the above (SW_MINNOACTIVE, SW_SHOWNA,
SW_SHOWNOACTIVATE included) the app (doc, URL, dir, drive, whatever)
always starts in the foreground and with input focus. How do you
actually control how it starts. In many cases, I'd like it to start
without input focus and leaving my console in the foreground.

 - Vince
___
   Vincent Fatica
   Syracuse University Mathematics

   http://barnyard.syr.edu/~vefatica/



Tue, 21 Dec 1999 03:00:00 GMT  
 ShellExecute with html document doesn't work reliably with Netscape



: hBrowser = ShellExecute( HWND_DESKTOP,  "open",
:                                        "c:\\test.htm",  
:                                        NULL,  NULL,  0);  

:ShellExecute() doesn't list HWND_DESKTOP as an alternative available for
this API.  

I don't think the window is the problem because I've also tried
GetDesktopWindow and I've tried the window handle of the application
calling ShellExecute.  HWND_DESKTOP is just the latest variation I've
tried.  I've also tried using SW_SHOW and SW_RESTORE for the last parameter
and neither made a difference.

:Also, again perhaps moot, is your use of the NULL word above.  I suspect
it was for illustrative :purposes, as the VB keyword Null can't be passed
in place of an expected 0&.

The example code came from a dll I wrote in C, not a VB program, so the
NULL is OK.  I've tried calling the ShellExecute API from directly from VB
and it didn't make a difference either.

Thanks for your observations.

Al Margheim



Tue, 21 Dec 1999 03:00:00 GMT  
 ShellExecute with html document doesn't work reliably with Netscape

I'm happy to share what I wound up doing (16-bit API, but should be
applicable to 32-bit) and in turn would appreciate any further
refinements or suggestions:

    LONG lName = 256;
    LONG lValue = 256;
    char sName[256] = "";
    char sValue[256] = "";
    char sURL[] = "http://www.whatever.com/something.html";

    ::RegQueryValue(HKEY_CLASSES_ROOT, ".htm", sName, &lName);
    strcat(sName, "\\shell\\open\\command");
    ::RegQueryValue(HKEY_CLASSES_ROOT, sName, sValue, &lValue);

    if (sValue[0])
    {
        // If there is a blank following the last backslash in the
        // string, zap it to a null.
        //
        char * pTemp = strrchr(sValue, '\\');
        if (!pTemp) pTemp = sValue;
        pTemp = strchr(pTemp, ' ');
        if (pTemp) *pTemp = 0;

        HINSTANCE hi = ::ShellExecute(NULL, "open", sValue, sURL, "",
            SW_SHOWNORMAL);

        ...
    }

-- Rod


Quote:
>I know.  Actually, I have to apologize because I mis-stated the problem.
>The problem I'm having is with URLs on the net, not local html files, and
>the problem occurs with both Internet Explorer and Netscape.  In other
>words, if test.htm is present, the code below works everytime on the
>systems I've tested with:

>hBrowser = ShellExecute( HWND_DESKTOP,  "open",
>                                       "c:\\test.htm",  
>                                       NULL,  NULL,  0);  

>but the code below works only if the browser was already started:

>hBrowser = ShellExecute( HWND_DESKTOP,  "open",
>                                       "http://www.microsoft.com/",  
>                                       NULL,  NULL,  0);  

.....

Note: Remove the x from my address to reply by email.



Tue, 21 Dec 1999 03:00:00 GMT  
 ShellExecute with html document doesn't work reliably with Netscape


Fri, 19 Jun 1992 00:00:00 GMT  
 ShellExecute with html document doesn't work reliably with Netscape

Quote:
> This raises another question about which I'm curious: I use the above
> little program from the command line and batch files, and no matter
> what SW_* flag I use in the above (SW_MINNOACTIVE, SW_SHOWNA,
> SW_SHOWNOACTIVATE included) the app (doc, URL, dir, drive, whatever)
> always starts in the foreground and with input focus. How do you
> actually control how it starts. In many cases, I'd like it to start
> without input focus and leaving my console in the foreground.

In this case, you may want to search the registry for the correct
application for the registered document type, and ShellExecute() (or
CreateProcess()) that application.  When you run the application instead of
"running" the document, you can control how the window is displayed.

--

Objectivist, Software Engineer (Win32, STL, MFC, and sockets spoken here)

  "In every possible way, with no valid objection, the solution for the
                    economic problem is capitalism."
        - George Reisman, _Capitalism: A Treatise on Economics_



Thu, 23 Dec 1999 03:00:00 GMT  
 ShellExecute with html document doesn't work reliably with Netscape


Fri, 19 Jun 1992 00:00:00 GMT  
 ShellExecute with html document doesn't work reliably with Netscape

Quote:



> >And yet, if the user
> >double-clicks on an .htm file in Explorer, Netscape does start and
> does
> >display the local htm file.

> That's strange, because all Explorer does when you double-click on a
> filename is do a "ShellExecute" on the file!

It does a ShellExecuteEx really: there are some subtle differences with
the functionality of the Ex version which handles RunDll32 spanwed COM
objecta better [like the ExecuteEx can open dial up networking from a
.lnk file], and it has better error reporting.

So, the original poster may want to use the Ex version, at least on
versions of windows (9x and 4.0+) which handle it.

        -Steve

--
Steve Loughran, Hewlett-Packard Laboratories, Bristol, England
http://www-uk.hpl.hp.com/people/slo/    

All opinions expressed are my own and do not represent official
statements of the Hewlett-Packard Company.

All email not addressed directly "to:" me will be deleted long before
arriving in my inbox. And fix the sabotaged email address above first!



Fri, 24 Dec 1999 03:00:00 GMT  
 
 [ 13 post ] 

 Relevant Pages 

1. Hyperlinks/ExtraInfo html doesn't work in 2002

2. Find.Execute doesn't work for a new document

3. Button doesn't work in new document

4. MSChart doesn't work as documented!

5. document.all method doesn't work

6. Q:My ActiveX Document doesn't work on internet

7. Tabbing doesn't work on VB Documents in IE3.02

8. Tabbing doesn't work on VB Documents in IE3.02

9. fRefreshLinks Doesn't work if path doesn't exist

10. ShellExecute Print DOESN'T ALWAYS PRINT!

11. How to Reliably Get the Number of Documents

12. Windows Service Calling VB6 dll doesn't work but works with VB6

 

 
Powered by phpBB® Forum Software