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

Table of Contents

Page Updates

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.

1  How does classExec work?

By reverse engineering I found the DDE parameters are stored in the registry like this:

or 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: 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:

2  Release Notes

2.1  v1.03

2.2  v1.02

2.3  v1.01

2.4  v1.00

3  Examples

3.1  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.

3.2  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

3.3  Word

3.3.1  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:

3.3.2  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()]"

3.3.3  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.

3.3.4  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()]

3.3.5  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 .doc files to RTF, keeping the date of the original file:

    classExec *.doc --command [NewMacros.Convert()]

3.4  Excel

3.4.1  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

3.4.2  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\")]"

3.4.3  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.

4  Known Problems

4.1  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:

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).

4.2  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 GPF.

5  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.

5.1  Release

file: classExec-1.03b.zip (binary), classExec-1.03s.zip (sources)

5.2  Development

file: classExec-1.5.0b.zip (binary), classExec-1.5.0s.zip (sources)

6  Alternatives

6.1  'ShellExecute()' API function

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

6.2  '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.

6.3  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.

7  Links




Home