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.Freddy Vulto
Mar 21, 2004: | Compiled ClassExec with Visual C++ .NET. Started development branch 1.5.x. A stable release would become 1.6.x. |
Jun 7, 2002: | Added paragraph 'Processing files within subdirectories' |
Aug 29, 2001: | Added paragraph 'How does classExec work?'. Used HTML::EmbPerl & HTML::Toc to generate this page. Added NedStat counter. |
By reverse engineering I found the DDE parameters are stored in the registry like this:
shell |- <action> |- command |- ddeexec |- Application |- Topicor at least this is the case for Microsoft applications. ClassExec looks for these registry settings, using the
--class
or filename extension. For example with .dot
files it goes like this with .dot
being the extenstion 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
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.
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
The syntax to call 'classExec' recursive on multiple .doc
files within subdirectories would be:
find . -name *.doc -exec classExec {} --command [NewMacros.Test()] ;
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()]"
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.
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()]
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 .doc files to RTF, keeping the date of the original file:
classExec *.doc --command [NewMacros.Convert()]
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
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\")]"
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.
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:
1. From Microsoft Word, call the Visual Basic Editor via {Tools; Macro; Visual Basic Editor}.
2. From the Project Explorer ({View; Project Explorer}) choose the 'Normal' project from the tree root and open the 'Modules' branch.
3. Select the module called 'WordTmpDDEMod' and delete it using {File; Remove WordTmpDDEMod...} (you don't need to export it before removing).
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 GPF.
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.
file: classExec-1.03b.zip (binary), classExec-1.03s.zip (sources)
file: classExec-1.5.0b.zip (binary), classExec-1.5.0s.zip (sources)
If you - from within a Windows application - just want to start the application associated with a given file extension without knowing the name of the associated application, 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
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.
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.