Launching HTML From a CDROM
This article from Win32 Q&A, MSJ APRIL 1999 may contain
URLs that were valid when originally published, but now link to sites or pages
that no longer exist. To maintain the flow of the article, we've left these URLs
in the text, but disabled the links.
by Jeffrey Richter
April 1999
Jeffrey Richter wrote Advanced Windows, Third Edition
(Microsoft
Press, 1998) and Windows 95: A Developer's Guide
(M&T Books, 1995).
Jeff is a consultant and teaches Win32 programming courses
(http://www.solsem.com/).
He can be reached at
http://www.jeffreyrichter.com/.
Q
How can I make a CD-ROM load an HTML file automatically when the disk is
inserted into the drive?
So many people,
I lost count
A
This is by far the most popular question I've ever been asked. This month
I'll offer three slightly different solutions, each with some pros and
cons. But before I dive in, here's some quick background
information.
The mechanism that Windows® uses to
automatically execute a process when a CD-ROM disk is inserted in the
drive is called AutoPlay. Simply stated, when a CD-ROM disk is inserted in
a drive, the system broadcasts a WM_DEVICECHANGE notification. If
Explorer.exe is running, it examines the newly inserted disk, looking for
a file called AUTORUN.INF. This file is a simple ASCII text file (often
created with Notepad) that contains statements telling Explorer what icon
to show for the drive when it appears in the My Computer folder. The
statements also tell Explorer what menu items should appear in the drive's
context menu. Lastly, if the AUTORUN.INF file contains an "OPEN="
statement (and most do), then Explorer peels off the string to the right
of the equal sign and passes this string to the Windows CreateProcess
function.
I'm not going to explain everything that you
can do in this file because I've already discussed it in previous
MSJ articles. So here's a simple AUTORUN.INF file:
[AutoRun]
ICON=SomeProcess.exe
OPEN=SomeProcess.exe
This file tells the Explorer to show
SomeProcess's icon for the CD-ROM disk in the My Computer folder. When the disk
is inserted (or when the user attempts to open the disk), the Explorer grabs the
OPEN statement's command line and passes it to CreateProcess.
To make the Explorer display an HTML file, I first
tried to create an AUTORUN.INF file as follows:
[AutoRun]
ICON=SomeProcess.exe
OPEN=Welcome.html
I had hoped that Explorer would see that
HTML files were associated with the user's default browser and that Explorer
would run AUTORUN.INF, passing it the path of my HTML file. The beauty of this
is that the system would automatically determine which browser the user has set
up as their default. Unfortunately, this AUTORUN.INF file does not work.
Explorer calls CreateProcess internally, which instructs the system to run an
executable file named Welcome.html. Since this file is not an executable,
CreateProcess fails and nothing runs.
Had the Explorer team at Microsoft decided to call
ShellExecute instead of CreateProcess, my AUTORUN.INF file would have worked
just fine. ShellExecute looks up file associations that are in the registry,
constructs a proper command line automatically, and passes the resulting command
line to CreateProcess. So ShellExecute would have seen that files ending with an
HTML extension are associated with IExplore.exe (or whatever) and called
CreateProcess, passing it something like "IExplore.exe Welcome.html". This would
have been an elegant solution.
OK, so my first attempt didn't work. What next? Well,
the next step seems obvious: write a super simple application that calls
ShellExecute. This application will be placed on the CD-ROM disk with the
Welcome.html file.
Figure 1
shows the code for this simple application. This application takes its
command-line parameter and passes it off to ShellExecute to do the work. To
prepare the CD-ROM disk for shipping, I create a Welcome.html file that has what
I want the user to see when they insert the disk. Then I create the following
AUTORUN.INF file:
[AutoRun]
ICON=ShellExecute.exe
OPEN=ShellExecute Welcome.html
This is the first solution to the problem. But I
wondered if there was a way to accomplish the same thing without having to write
my own code. Basically, the problem now is how to run some application that
calls ShellExecute, passing it a command-line parameter that I specify.
It dawned on me that the command shell has a START
command that does just this. So I created the following AUTORUN.INF file:
[AutoRun]
ICON=SomeIcon.ico
OPEN=CMD.EXE /c "start Welcome.html"
This worked great, but it has two
problems. First, when the command shell executes, the system creates a console
window that gets destroyed almost immediately. This causes some unpleasant
flashing, and I'd prefer my CD-ROMs to have a more polished look. Second,
CMD.EXE exists on Windows NT®, but does not exist on Windows
9
x.
Windows 9
x, of course, uses COMMAND.COM as its
command shell processor. I fixed this problem by changing my AUTORUN.INF file to
read as follows:
[AutoRun]
ICON=SomeIcon.ico
OPEN=ShellExecute.bat Welcome.html
When "ShellExecute.bat" is passed to
CreateProcess, it knows to spawn the correct command shell for the system you're
on (CMD.EXE or COMMAND.COM). By the way, here is my ShellExecute.bat file:
Start %1
Pretty simple, huh? The Start command
causes the command processor to call ShellExecute internally. Even though I got
this technique working on both OS platforms, I wasn't happy because of the
flashing console window. What I really need is a GUI application that calls
ShellExecute. Incidentally, this is why my code in
Figure
1 uses a WinMain function instead of a main function; this application
should be a GUI app.
After racking my brain for a while, I remembered that
Windows now ships with a scripting host. In fact, there are two scripting host
processes: a GUI (WSCRIPT.EXE) and a CUI (CSCRIPT.EXE). I, of course, wanted to
use the GUI host to avoid the unpleasant flashing.
The following JScript®
// Create an instance of the scripting Shell Object
WshShell = WScript.CreateObject("WScript.Shell");
// Have the Shell Object call ShellExecute on our HTML // file
WshShell.Run("Welcome.html", 1, 0);
// Destroy the Shell Object
WScript.DisconnectObject(WshShell);
simply takes its command-line arguments
and passes them to the Shell object's Run method. This method, in turn, calls
the Windows ShellExecute function. Voilà! So now my CD-ROM has a Welcome.html
file, a ShellExecute.js file, and the following AUTORUN.INF file:
[AutoRun]
ICON=SomeIcon.ico
OPEN=Wscript ShellExecute.js //B //nologo Welcome.html
This is my favorite solution because it doesn't
involve writing, compiling, and linking any code. Therefore, it was the easiest
to test and modify. So what is the downside of using the scripting host? Some
Windows platforms don't have the scripting host installed. For example, Windows
95 and Windows NT 4.0 didn't ship with the Wscript.exe application, so if your
users are running on these platforms, your HTML file won't be displayed. For
these platforms, you'll need to use one of the other two methods. Of course,
Windows 98 ships with the scripting host (and Windows 2000 is expected to), so
if your application requires these platforms (or later), feel free to use the
scripting host method.
While I'm on the subject, let me tell you how I
tested all these mechanisms. First, I did not burn a new CD-ROM disk to try out
each idea I had. Instead, there is a way to test AUTORUN.INF files using a
floppy disk or a hard drive directory. To do this you must edit the
NoDriveTypeAutoRun value in the following registry subkey:
HKEY_CURRENT_USER\Software\Microsoft\Windows\
CurrentVersion\Policies\Explorer\
This value indicates which drives should
have AutoPlay enabled. When Explorer receives the WM_DEVICECHANGE message, it
first checks this registry value to see if it should parse the disk's
AUTORUN.INF file at all. Knowledge Base article
Q136214 explains how to set this value correctly for
testing.
After you change this registry value, don't forget to
shut down the Explorer and restart it so that the change takes effect. The easy
way to do this is to choose Shutdown from the Start menu. But when the Shutdown
confirmation dialog box appears, don't just click a button. Instead, hold down
the Control+Alt+Shift keys and click No. This tells the Explorer to terminate
itself without shutting down the whole machine.
Now you can start another instance of Explorer to do
your testing. On Windows 2000, press Control+Alt+Del and select the Task
Manager. When the Task Manager appears, choose the New Task (Run…) option from
the File menu and enter "Explorer." On Windows 9x, start a command shell
before you terminate the Explorer. After the Explorer terminates, go to the
command shell and run Explorer. You can do this on Windows NT too.
Now that a new instance of Explorer is running and
has read the new value from the registry, you can test your AUTORUN.INF file by
finding the drive in the My Computer folder and trying to open it. Instead of
Explorer opening the folder, it will parse the AUTORUN.INF file and try to
execute its "OPEN=" statement.
Have a question about programming in Win32? Contact Jeffrey Richter at http://www.jeffreyrichter.com/
From the April 1999 issue of Microsoft Systems Journal