One of the most commonly asked questions in the System iNetwork forums always seems to be How do I open Windows application X from IBM i? How do I launch a browser? How do I display an image? How do I display a PDF? How do I open Microsoft Word for a document? How do I open Excel?
Too often, answers that involve the Windows Start command are given. I don't like the Start command because it opens a command-prompt window, and you have to deal with that ugly window appearing, plus you have to deal with escaping all the characters that DOS interprets in a special way.
Another frequent answer that I wouldn't recommend: hard-coding the path name to a Windows program. What happens when the user chooses to use a different program? What happens when he decides to upgrade to a different version of the program and it has a different name? C'mon, folks! You're programmers--you know the evils of hard-coding!
My favorite technique is to use the Windows rundll32 tool. This article explains what the tool is and how you can use it to launch Windows documents.
Windows File Associations
To prevent hard-coding, Windows has a database (part of the registry, in fact) of file types and the programs that can be used to act upon those file types. These are called File Associations. For example, the .DOC file type is typically associated with Microsoft Word. Inside the registry, there's a key that says, "When the user wants to open a .DOC file, run Microsoft Word," and it gives the pathname and syntax to run the program with the right parameters to open the .DOC file.
The open action is usually the default action, but there are others, including edit, print, explore and find. In Windows, if you right-click a file, you can choose which action to carry out. Windows then looks in the registry to find the right program, pass the right parameters, and act upon your document in the prescribed way.
This is an elegant system because you don't have to hard-code the program. If I decided to use Open Office instead of Microsoft Office, I could set up the association for .DOC to talk to Open Office. Then, all my documents would open with my preferred program. The same is true for URLs and HTML documents, you might configure Chrome to open web documents, while I might choose Firefox, and someone else might choose Internet Explorer. It's not hard-coded, so we can make our decision, and our chosen program will open.
The Windows ShellExecute() API
ShellExecute() is an API that lives in a DLL called Shell32.DLL, which comes with Windows. Its job is to provide the API equivalent of double-clicking or right-clicking your file. You pass ShellExecute() a few parameters, including the path name to the file to launch, and the action you want to take (e.g., open, print, edit, etc). ShellExecute() takes care of finding the right application to handle the document, and then calls it with the correct parameters.
A DLL is the Windows equivalent of a service program. It's like a program, but instead of having one start point that you call by the program name, it has many subprocedures ("functions," in PC terminology) that you can call independently—just like an ILE service program.
Therefore, you can't use it to launch programs over a network from IBM i software . . . or can you?
The RunDLL32 Utility
RunDLL32 stands for "Run DLL (32-bit)," and it's a Windows program that lets you call subprocedures (or "functions," in Windows parlance) from the command line. RunDLL32 takes two parameters.
rundll32 DllName,FunctionName parameter
The first parameter passed to RunDLL32 contains two fields. The first is the name of the DLL (but without the extension). This is followed by a comma, followed by the name of the function ("subprocedure") that you want to call.
RunDLL32 allows you to pass one parameter (and only one—which is its most frustrating limitation) to the function you call. This is a bit of a dilemma because the ideal way to launch a Windows program would be ShellExecute(), and ShellExecute() won't work with only one parameter. It requires six parameters! That means it can't be called from RunDLL32, right?
Well, there's a trick to it. Somewhere along the line, Microsoft realized the fact that ShellExecute() isn't compatible with RunDLL32, so it added a "RunDLL compatible version" of ShellExecute(). Microsoft named it ShellExec_RunDLL to signify that it was RunDLL compatible. ShellExec_RunDLL takes only one parameter, the pathname to the icon. It always takes the "default" action on that icon (which is almost always "open") and opens the window with default settings.
The result is that from a Windows command prompt or Start|run box, you can do this:
rundll32 shell32,ShellExec_RunDLL "C:\scott-test\test.pdf"
When you do that, Windows opens the PDF document using the default viewer (usually Acrobat Reader, but it could be xpdf or a similar tool. You never know!).
RunDLL32 from IBM i
You can run the RunDLL32 on your user's PC during an interactive session via the Start PC Command (STRPCCMD) command. STRPCCMD works by sending a specially formatted screen image to the emulation software. The emulator recognizes it as a remote command (rather than a normal screen) and intercepts it and executes the command that you sent. Most emulation software will examine the program you ask it to run. If it's a DOS program, it'll open a DOS window to run it. If it's a Windows program, it'll launch it as a Windows application without the little black box. That's why I don't like to use the start utility! The start utility is a DOS utility, so if you run it, you'll get the ugly little black DOS box. Even though you may be using start to launch a Windows program, the fact that start itself is a DOS program will cause the black box to appear.
Here's an example of using STRPCCMD to start a program on the user's PC:
DCL VAR(&CMD) TYPE(*CHAR) LEN(123)
DCL VAR(&PATH) TYPE(*CHAR) LEN(89)
CHGVAR VAR(&PATH) +
VALUE('"C:\Windows\Media\Windows XP Shutdown.wav"')
CHGVAR VAR(&CMD) +
VALUE('rundll32 shell32,ShellExec_RunDLL ' *BCAT &PATH)
STRPCCMD PCCMD(&CMD) PAUSE(*NO)
The preceding program will launch the default application to play the WAV (sound) file that you usually hear when shutting down a Windows XP PC. Don't worry—it won't actually shut the PC down; it just plays the sound. I think it's fun because I sneak it into colleagues' programs when they're not looking. Then they hear the "Windows is shutting down" sound and get confused. It's funny—you should try it.
More stuff to try:
- Open Word:
CHGVAR &PATH VALUE('C:\path\to\mydocument.doc')
- Open Excel:
CHGVAR &PATH VALUE('C:\path\to\mydocument.xls')
- Open PDF:
CHGVAR &PATH VALUE('C:\path\to\mydocument.pdf')
- Open browser:
CHGVAR &PATH VALUE('http://www.google.com/search?q=Scott+Klement')
- Run a program:
CHGVAR &PATH VALUE('calc')
- Control panel plug-in:
CHGVAR &PATH VALUE('services.msc')
- Shutdown in 30 secs:
CHGVAR &PATH VALUE('shutdown.exe -s')
- Abort shutdown:
CHGVAR &PATH VALUE('shutdown.exe -a')
Of course, the disadvantage of anything you do with STRPCCMD is that it's difficult to get anything back to the invoking program. There's no way to tell whether your command succeeded, for example. Still, it's a pretty neat tool.