ClassExec
As far as I'm concerned, the diatribes about DDE being too old a technology to be of any use, are a great misunderstanding. Microsoft makes excessive use of DDE to let the shell communicate with various applications (e.g. MS Office). Just search the registry for 'ddeexec' and you'll see what I mean. Most Windows applications lack the wealth of startup arguments which normally would allow you to pass information to the program during startup. ClassExec brings back this functionality to the command prompt.
ClassExec is a command line utility to:
- start a file within its default application, e.g.
classExec foo.doc
- start a file within another default application, e.g.
classExec --class .xls foo.doc
- create a new Word document based on a specified template, passing arguments to a startup macro along the way:
classExec my.dot --action new --command "[NewMacros.LoadFile \"C:\test.txt\"]"
- print files
- etcetera...
Contents
How does classExec work?
By reverse engineering I found the DDE parameters are stored in the registry like this:
shell |- <action> |- command |- ddeexec |- Application |- Topic
or at least this is the case for Microsoft applications. ClassExec looks for these registry settings, using the filename extension or the `--class' option. For example with .dot files it goes like this with .dot being the extension and `Word.Template.8' being the classname:
HKEY_CLASSES_ROOT |- .dot (Default) = Word.Template.8 : |- Word.Template.8 |- shell |- <action> |- command |- ddexec :
If no such branch for your filename extension exists, make sure to check the 'Use DDE' checkbox within Explorer via {View|Folder Options...|File Types|Edit|Edit}. I think Windows is using the `ddeexec/Application' key to look up the actual `Application' in:
HKEY_LOCAL_MACHINE |- Software |- Microsoft |- Windows |- CurrentVersion |- App Paths |- <Application>.exe
Examples
Introduction
The commands:
classExec classExec --help
will display a help message and exit. The commands:
classExec <filename> classExec <filename> --action open
both will open <filename>, since `open' is the default action of classExec if no action is specified. Note this is the same as the built-in Windows command:
start <filename>
The command:
classExec *
will issue the `open' action on all files in the current directory. The command:
classExec * --class .doc
will open all files in Word. You want to open all files in Excel instead? Here's the command to do so:
classExec * --class .xls
The command:
classExec C:\* D:\* --class .doc
will open all files from the C:\ directory as well as all files from the D:\ directory, in Word.
Advertisement
Selecting browser
If you want to view a HTML file in your default browser from the command line, you could issue one of these commands:
classExec example.htm start example.htm
But what to do if you want to view the HTML file in either Netscape Navigator or Microsoft Internet Explorer, without wanting to bother if it's the default browser or not? Here's what to do if you want to view the HTML file using Netscape Navigator:
classExec example.htm --class NetscapeMarkup
If you want to view the HTML file using Microsoft Internet Explorer, use:
classExec example.htm --class htmlFile
Word
Processing files within subdirectories
ClassExec only works on files within the specified folder. To process files within subfolders as well, the GNU utility `find.exe' can be used. Find.exe can be obtained by downloading find41b.zip from www.delorie.com/djgpp/ or by downloading utilities from unxutils.sourceforge.net.
The syntax to call classExec recursive on multiple .doc files within subdirectories would be:
find . -name *.doc -exec classExec {} --command [NewMacros.Test()] ;
Calling macro on startup
Suppose you're having a template my.dot with a macro NewMacros.LoadFile:
Sub LoadFile(as_File As String) MsgBox as_File + Chr$(13) Selection.InsertFile as_dpf End Sub
Here's how you can start C:\test.txt in Word, base it on my.dot, and calling LoadFile on startup:
classExec my.dot --action new --command "[NewMacros.LoadFile \"C:\test.txt\"]"
Or if you're having a macro which asks for two arguments:
Sub ShowMessages(as_Msg1 As String, as_Msg2 As String) MsgBox as_Msg1 MsgBox as_Msg2 End Sub
Here's how you would call it:
classExec my.dot --action new --command "[NewMacros.ShowMessages \"Msg1\", \"Msg2\"]"
A macro with no arguments gets called like this:
classExec my.dot --action new --command "[NewMacros.ShowMessages()]"
Printing
The command:
classExec <filename>.doc --action print
will open Word and print <filename>.doc. If Word wasn't open, Word will be closed automatically after the print job is done. The command:
classExec <filename>.txt --class .doc --action print
will open Word and print <filename>.txt. If Word wasn't open, Word will be closed automatically after the print job is done. The command:
classExec <filename>.doc --action print --noifexec
will open Word and print <filename>.doc. If Word wasn't open, Word will not be closed after the print job is done. The command:
classExec <filename>.doc --action print --ifexec
will open Word and print <filename>.doc. After the print job, Word will be closed.
Batch conversion
After you created this macro in module NewMacros of normal.dot:
Sub Convert() ActiveDocument.SaveAs ActiveDocument.FullName + ".rtf", _ FileFormat:=wdFormatRTF ActiveDocument.Close End Sub
here's how you could invoke classExec to convert all files in a folder to RTF:
classExec * --class .doc --command [NewMacros.Convert()]
Batch conversion, keeping date of original file
Suppose you want to convert all .doc files to .rtf. Extra condition is you want to give the .rtf file the date of the original .doc file. If you put the GNU utility touch.exe in the C:\Windows directory and you put the next macro Convert in the NewMacros section of normal.dot:
Sub Convert() Dim sFileIn, sFileOut As String sFileIn = ActiveDocument.FullName sFileOut = ActiveDocument.Path & Application.PathSeparator & _ ActiveDocument.Name & ".rtf" ActiveDocument.SaveAs sFileOut, _ FileFormat:=wdFormatRTF ActiveDocument.Close Shell "C:\Windows\touch.exe " & sFileOut & " -r " & sFileIn End Sub
here's how you could invoke classExec to convert Word files to RTF, keeping the date of the original file:
classExec *.doc --command [NewMacros.Convert()]
Excel
Create new sheet based on another
If you want to create a new sheet, based on another sheet (book1.xls), here's how you would do so:
classExec book1.xls --action new
Calling macro on startup
Suppose you're having a file book1.xls with a macro Sheet1.HelloWorld:
Sub HelloWorld() MsgBox "Hello world!" End Sub
Here's how you would start book1.xls in Excel, calling macro Sheet1.HelloWorld on startup:
classExec book1.xls --command "[Run(\"Sheet1.HelloWorld\")]"
Fill cells on startup
It looks like it isn't possible to pass arguments to an Excel macro during startup. Anyone? Any string you pass to the opened sheet will be inserted into the sheet. For instance, if you say:
classExec book1.xls --command "Hello world"
the string "Hello world" will be inserted in cell A1 of book1.xls. You can pass <tab> in the string to advance to a cell on the right. For instance if you say:
classExec book1.xls --command "Hello<tab>world"
the string "Hello" will be inserted in cell A1, whereas "world" will be inserted in cell A2. You can pass <newline> in the string to advance to a cell underneath the current cell. For instance, if you say:
classExec book1.xls --command "Hello<newline>world"
the string "Hello" will be inserted in cell A1, whereas "world" will be inserted in cell B1.
Access
Snapshot Viewer
Snapshot Viewer is a program that you can use to view, print, and electronically mail an Access report snapshot www.microsoft.com/accessdev/prodinfo/snapshot.htm).
To open a snapshot file:
classExec report.snp
To print a snapshot file:
classExec report.snp --action print
Be aware however, the Snapshot Viewer installation program doesn't install complete registry keys; to be specific it omits the
- ddeexec\application
- ddeexec\topic
keys. To make full use of ClassExec with Snapshot Viewer, make sure the following registry keys are specified:
HKEY_CLASSES_ROOT |- SnapshotFile |- shell |- open | |- command (Default) = <Path to snapView.exe> | |- ddeexec (Default) = [open("%1")] | |- application (Default) = SnapView | |- topic (Default) = system | |- print | |- command (Default) = <Path to snapView.exe> | |- ddexec (Default) = [print("%1")] | |- application (Default) = SnapView | |- topic (Default) = system | |- printto |- command (Default) = <Path to snapView.exe> |- ddeexec (Default) = [printto("%1","%2","%3","%4")] |- application (Default) = SnapView |- topic (Default) = system
Known Problems
Setting default printer
Windows 2000/XP
You can set the default printer from the command line using rundll32 and printui.dll. For example, to select "HP DeskJet 710C" as the default printer:
rundll32 printui.dll,PrintUIEntry /y /n "HP DeskJet 710C"
For more information, see: http://www.robvanderwoude.com/2kprintcontrol.html
Word97 error: "Ambiguous name detected: TmpDDE"
When you execute a DDE command via Microsoft Word 97, Word will dynamically create a temporary module called `WordTmpDDEMod' in normal.dot with a temporary subroutine called `TmpDDE' in it. This temporary subroutine contains the DDE commands. After the subroutine exits, the temporary module will automatically be deleted.
However, you may found yourself in a situation where Word hasn't cleaned up the temporary DDE module. Here's how you can remove the temporary DDE module manually:
- From Microsoft Word, call the Visual Basic Editor via {Tools; Macro; Visual Basic Editor}.
- From the Project Explorer ({View; Project Explorer}) choose the `Normal' project from the tree root and open the `Modules' branch.
- Select the module called `WordTmpDDEMod' and delete it using {File; Remove WordTmpDDEMod...} (you don't need to export it before removing).
Word Viewer doesn't support DDE print
Microsoft Word Viewer 2007 or 2003 doesn't support printing via DDE. WordView 95 used to support this and even had a /p switch, but print automation has been removed from WordView 97 and up.
Up to Windows XP, Wordpad has .doc support so you might try Wordpad:
classexec word.doc --class Wordpad.Document.1 --action print
Windows Vista however, removed .doc support from Wordpad. A workaround might be to use the free and open OpenOffice:
soffice -p word.doc classexec word.doc --class .odt --action print
Regressive Word 97 DDE functionality
According to Ted Giria, Word 97 allows not more then 256 bytes in a package whereas Word 95 allowes 127 commands at one. Also Word 95 is more stable with DDE than 97. In some situations in Word 95 where you have an error message or error return code, Word 97 yields a general protection fault (GPF).
Download
This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
See also: Gpg: Verifying FVue releases
Release
classExec-1.03b.zip (binary), classExec-1.03b.zip.asc (signature)
classExec-1.03s.zip (sources), classExec-1.03s.zip.asc (signature)
Development
classExec-1.5.0b.zip (binary), classExec-1.5.0b.zip.asc (signature)
classExec-1.5.0s.zip (sources), classExec-1.5.0b.zip.asc (signature)
Advertisement
Release Notes
v1.03
- Fixed Windows NT error message "The instruction at '0x77f64b53' referenced memory at '0x0000031d'. The memory could not be 'read'", caused by 'LocalFree()' which tried to free an already freed piece of memory.
v1.02
- Fixed error message "invalid page fault in module CLASSEXEC.EXE at 0137:00401595" when using a full classname (e.g. 'txtfile') instead of an extension (e.g. '.txt').
v1.01
- Fixed error message "access violation on address 0xC0000005" on Windows NT, caused by dynamic determination of application name. Application name now is set fixed to "classExec".
- Added environment string expansion to commands. E.g. the command "%SystemRoot%\system32\notepad.exe" now will get expanded to "C:\WinNt\system32\notepad.exe".
- Enhanced error message of non-startable application with the application command line string.
v1.00
- Initial version.
Alternatives
Windows Scripting Host
The Windows Scripting Host has some advantages though. For instance, the ability to send key strokes to an application. Here's an example VBScript to start up any argument file, print it using {File|Print}, send {ENTER} to the print dialog, and close it using {File|Close}.
Set WshShell = WScript.CreateObject("WScript.Shell") WshShell.run WScript.Arguments(0) On Error Resume Next Err.Clear Wscript.Sleep(100) REM Send keys: ALT-File|Print, ENTER, ALT-File|Close WshShell.SendKeys "%FP{ENTER}%FC"
For more information, see:
'ShellExecute()' API function
If you just want to start the application associated with a given file extension, you're probably better of using the Windows API 'ShellExecute()' function. This is the summary of the Microsoft document Q170918:
"You can use the Windows API ShellExecute() function to start the application associated with a given document extension without knowing the name of the associated application. For example, you could start the Paintbrush program by passing the filename ARCADE.BMP to the ShellExecute() function."
And this is what the Visual Basic declaration looks like:
Declare Function ShellExecute Lib "shell32.dll" Alias "ShellExecuteA" ( _ ByVal hwnd As Long, ByVal lpszOp As String, _ ByVal lpszFile As String, ByVal lpszParams As String, _ ByVal LpszDir As String, ByVal FsShowCmd As Long _ ) As Long
'Start' command line function
If you - from the command prompt - just want to start the application associated with a single file without knowing the name of the associated application, you can use the start
function from the command prompt, e.g.:
start arcade.bmp
This is what the help message (start /?
) has to say:
Runs a Windows program or an MS-DOS program. START [options] program [arg...] START [options] document.ext /m[inimized] Run the new program minimized (in the background). /max[imized] Run the new program maximized (in the foreground). /r[estored] Run the new program restored (in the foreground). [default] /w[ait] Does not return until the other program exits.
Word Batch Conversion Wizard
Microsoft includes the Batch Conversion Wizard with Word. It allows you
to do a conversion to/from Word format on a folder full of files. If Word
is fully installed, there will be a file called convert8.wiz
, in
.\Program Files\Microsoft Office\Office\Macros. Double-click it and follow
the instructions.
Links
- Dynamic Data Exchange (DDE) and NetDDE FAQ
- Extensive information about DDE