Compiling/Deploying An Application
Created with dBASE

Last Modified: October, 2002
Ken Mayer, Senior SQA Engineer
dBASE, Inc.

NOTE: The original document for this is still in the Knowledgebase, and is titled "Compiling/Deploying An Application Created with Visual dBASE 7/dB2K". Since dBASE, Inc. does not distribute InstallShield Express, and Inno Setup is discussed in detail in other documents, this one will focus specifically on preparing an application for deployment, compiling and building the application and considerations for getting everything in the right place.

TO a certain extent, the information here should be fairly generic and apply to Visual dBASE 7.0, 7.01 and 7.5, dB2K versions 0.1 through 0.4, and dBASE Plus.

Once your application is complete and ready to deploy, please read the appropriate document dealing with deploying the application (the one mentioned above, which still discusses using InstallShield, or the document on using Inno Setup for later versions of the software).

One final note, a future release of dBASE Plus will have a new Project Manager (or Project Explorer) -- it is not covered here as the author has not seen it, and cannot talk about it, at this time. This article will updated appropriately as time allows.


Any developer who needs to finish their application is going to run into the fact that the process of Compiling and/or Deploying their application is not well documented in the manuals or online help (although this process is better documented in dB2K and dBASE Plus than in previous versions).

This process is actually pretty simple, but it does not appear that way the first time you try it.

You are best off using the Project Manager to set everything up -- it may take a bit of work, but in the long run, you are ensured that everything is set the way it should be.

The instructions in this document are based on a simple application, with local tables. There are more detailed things that can be done (and should be if you are working with non-local tables), and the places to handle these are pointed out, but not detailed here.

Following along, you should be able, when done, to create a project file, and build/compile your application, and be ready to deploy it.

Special Sections:

Some Definitions
The following phrases can be a bit confusing to some folk, so I thought I would attempt to explain them:

Add to Project File -- this phrase refers to adding any file you wish to, to your project file. In the case of any files that can be "compiled" by dBASE (creating a file with a .CO, .PRO, .WFO ... anything ending with "O" except for an Icon (.ICO) in the file extension), these files will automatically be included in the target executable (see below). Anything else, if you really must include it in the executable (some developers store empty tables or image files in the .exe and copy them out later), you must do so explicitly (see below).

Include in Target Executable -- this phrase refers to including a file explicitly in the executable. As noted above, it is possible to have the compiler in dBASE store an image file, or a table (or anything else) in the .EXE. The only real advantage to this is that if the user deletes a file needed by your application, you can have them execute some command that extracts the file, or have the application do it automatically (there is a variation on the COPY FILE command that can be used, we're not going to get into it here).


BDE Settings

In earlier versions of dBASE (Visual dBASE 7.x), deploying the BDE was a bit difficult. With dB2K and later versions, a runtime installer was included to help you out, which installs the runtime, and also the BDE ...

There are still a few issues you may want to consider, however. If using InstallShield Express, please see the appropriate document.

In dB2K and later versions, some of the issues mentioned are dealt with specifically for you, and the Inno Setup document includes a discussion of a program created by Vic McClung that will merge a custom configuration file into the BDE after it's been installed, allowing you to create specific settings.


.INI Files

There are often a few settings saved into the .INI file for dB2K that most people don't even think about. This may include things like the SET CENTURY setting, which will affect the display of date fields (if set to ON you will see all four digits of the year, if set to OFF, you will see only two digits ...).

Note that INI files are covered in more detail in another Knowledgebase article ...

If you expect your deployed application to perform in the same manner as when you were developing it, you MUST deploy a .INI file. It needs to be the same name as the .EXE -- otherwise your application will not automatically read these settings (i.e., MYEXEC.EXE would require a .INI named MYEXEC.INI).

Some settings you should consider (see online help in dB2K/dBASE Plus for details for SET EPOCH, SET CENTURY, SET LDCHECK, etc.) adding as an example below:

   [CommandSettings]
   EPOCH=1950
   LDRIVER=WINDOWS

   [OnOffCommandSettings]
   CENTURY=ON
   LDCHECK=OFF
   BELL=OFF
   TALK=OFF

   [CommandWindow]
   Open=1
   Maximized=0
   Minimized=1

   [ComponentTypes]
   ComponentTypeNumeric=1
   ComponentTypeDate=1
   ComponentTypeLogical=0
   ComponentTypeMemo=0
   ComponentTypeBinary=0
   ComponentTypeOLE=0
   ComponentTypeNumericForTables=1
   ComponentTypeDateForTables=1
   ComponentTypeLogicalForTables=0
   ComponentTypeMemoForTables=0
   ComponentTypeBinaryForTables=0
   ComponentTypeOLEForTables=0

   [IDAPI]
   CONFIGFILE01=mycustom.cfg

The "LDRIVER=WINDOWS" setting ensures that no matter what your application's BDE Driver your source code will be saved as ANSI. (There is a problem with this setting and the SoundEx() function -- otherwise this setting will enhance the speed of text processing immensely).

The "TALK" setting is very important (this is from Gary White who discovered it during one deploy he did) -- if Talk is not set OFF (either here or in your code), there will be a serious performance degradation, as Visual dBASE will go through the motions of echoing comands to the command window. In dBASE Plus this isn't as important, as the Runtime Engine automatically assumes talk is off.

The "CommandWindow" settings are there just to be sure there are no other problems -- having the runtime try to open the Command Window is probably not a good idea.

The "ComponentTypes" section may cause some datatype mismatch errors if not included, particularly if you are using the grid component on your forms. You should copy the section shown above from your own DB2K or PLUS.INI, as you may have different settings than those shown above.

Encrypted Tables
If you are working with encrypted tables (using the dBASE PROTECT command to do so), you will need to deploy the DBSYSTEM.DB file, but you also need to have an entry in your .INI that looks like:

   [CommandSettings]
   DBSYSTEM=D:\PATH

Where "D:\PATH" is the path to the directory where you are deploying this file to. If you already have a "[CommandSettings]" section (see above), just add the "DBSYSTEM" entry. If you are deploying the DBSYSTEM file to the same as your application you can set this to "." (i.e., DBSYSTEM=. ) -- the "." stands for "current directory" ...


Creating a Project

If you have not already created a project for your application, you should do the following (and you may want to read the following to be sure you have done all that is needed ...):

NOTE: you will see, when you right click on files in the pane, a couple of options:

"Exclude from Build" -- only use this if you don't need a specific program, form, or whatever to be a part of the .exe. (Example: I have a program I use called SETUP.PRG - this is used to ensure that when I am coding that various .CCs and procedure files are available -- but I don't need it to be compiled into the .EXE, as the statements involved are called in my startup program ...)

"Include in Target Executable" -- this is deceptive -- it looks like you need to actually select each item to be included -- however, if a program, form, report, or other compileable file (datamodules, sql files, custom controls/ forms, etc.) is in the list, the .??O or .?O file will be automatically included in the .EXE file, and you do not have to do anything. The only reason for using this is if you wish to include tables, .DLLs, images ... in your .EXE (a trick some developers use to hide tables from the user ... we won't get into that here).



Preparing the Application

You are now nearly ready to compile your application, but there are some options you should be aware of.

Right click in the project manager's left pane, and select:
Project Properties

You will see a dialog with three tabs:

Project

Compile Build


Compile The Application

Once you have done any settings in the project manager that are needed, you can build your application from the main menu of dBASE -- but the project manager needs to be up -- you cannot do the following without it ... (well, you can type "BUILD something" [see online help] in the command window, but it won't make sure all files necessary for the application are included in the .EXE):

Select the "Build" menu, select the menu item: "Build myapp.exe" (where "myapp.exe" is the name of your application)

Note that from the same menu you can execute the .EXE file, which can be useful for testing, and you can debug it from the menu as well ...

There are actually two steps here -- the first compiles the individual files to their "pcode" (the .WFO, .PRO, etc.). A dialog will show that this process is complete, and you must click "OK" to continue to the actual creation of the .EXE. The amount of time it takes to generate the .EXE will vary based on how complex it is -- have some patience here ... That's all there is to compiling your application (deceptively simple, eh?) ...

If you set up a log file (see above, under "Preparing the Application"), any errors (or warnings) should appear in the log file.

NOTE: If you have paths to custom controls, header files, and so on (such as: C:\PROGRAM FILES\dBASE\DB2K 01\CLASSES\SEEKER.CC ), the path is removed from the compiled version. PROBLEM: if you do not include the custom controls in your list of files in the Project, they will not be in the executable, and when you run the executable, errors will occur.


Re-Building

Unless your code is perfect the first time out, you'll probably need to rebuild the .EXE multiple times -- suggest that you run the "Rebuild All" menu option rather than running the "Build myapp.exe" option -- this will ensure that all programs, forms, reports, etc., get recompiled before building your executable, and then the .EXE will be rebuilt.


OCX and DLL Controls

OCX and some DLL Controls require some registry settings. The problem is that it's not 100% automatic in most cases. Below are two ways of dealing with these -- you can let your install software handle this, or you can code it in your own application.

If you wish to use the installer to handle this, since each install software package is different, either read the appropriate document (this is dicussed in the Knowledgebase article that walks through creating an installation with InstallShield), or the help that comes with that software.

Manually Handling These In Your Own Code

An example of this is in VESPER7 (found at the author's web site and mirrored to some other web sites out there). This is free-ware sample code.

The basics of this are covered here.

dBASE ships with some registry API calls found in these files -- WINREG.H and REGISTRY.PRG. (WINREG.H is in the INCLUDE directory that ships with Visual dBASE, and REGISTRY.PRG is in the SAMPLES directory ... don't ask me why they were placed in these different directories, but ...)

The file "winreg.h" contains definitions, and "registry.prg" contains actual extern calls to code.

The fun part is that you need to check to see if the registry key is set. In the startup program for VESPER7, the following is contained in the Open method (for a calendar control created in Delphi 3 and converted to an OCX file):

      // necessary for Registry stuff:
      #include <winreg.h>
      set procedure to registry additive

      // Check to see if the Calendar has been registered
      // and if not, register it
      oReg = new Registry( HKEY_CLASSES_ROOT, ;
                           "CalendarXControl.CalendarX" )
      // if key referred to by "oReg" does was just
      // created, then we need to register the control:
      if ( oReg.newlyCreated )
         run( "regsvr32 /s calendar.ocx", false )
      endif

      // check to see if the registry key is empty -- if
      // so, something didn't work ...:
      if empty( oReg.queryValue( "" ) )
         msgbox( "Registry setting for Calendar control not set --"+;
                 "Do not try running calendar -- an error will "+;
                 "occur and may cause the program to crash. Contact "+;
                 "Ken to get a fix ...", ;
                 "Didn't work!" )
      endif

If the registry key is empty, it was probably created when we checked to see (oReg.newlyCreated) if it existed. The registry API calls being used will create the key when checking for it. If it didn't exist (i.e., oReg.newlyCreated actually returns a logical value -- true means we just created it), then we run a DOS program (odd, but true) -- the /s parameter simply runs the program in "silent" mode -- no dialog box will appear -- that will register the ocx ( "regsvr32.exe" -- note -- this program normally resides in your \WINDOWS\SYSTEM directory -- if it doesn't, or if your DOS path does not include that directory, this will not execute). (Note: there is now a DeleteKey() method in the REGISTRY object -- this didn't used to be there -- at the time Vesper was actively being worked on Visual dBASE 7.0 was the latest version -- this was added for 7.01 ... you could delete a registry key if it was empty ...)

The last thing we do is check to see if the key is still empty, and if it is, we display an error. This error is usually because the program doesn't exist (not likely, but it is possible -- "regsvr32.exe" is installed with Windows 95, 98 and NT); or more likely is the fact that your DOS path does not include the \WINDOWS\SYSTEM directory, which is where this program is installed to. You can get the user to step out to DOS and type:

     regsvr32 myocx.ocx

and it should display a (windows) alert dialog stating that it worked. (The /s flag in the RUN() call above simply runs this in "silent" mode -- so that when the start program executes, the user never has to even be concerned with the details ...)

NOTE: Using REGSVR32.EXE you can actually remove an OCX's (or probably even a .DLL's) entries in the registry by using the /U flag (uninstall).

If your .OCX has dependencies on other .DLLs, you need to install them first -- otherwise the .OCX won't install properly.


Network Deployment

This information comes from Gary White, who has performed a network installation. The author of this HOW TO does not currently have a way to test this. If you have suggestions for network deployment that are different from Gary's, please feel free to say something in the Visual dBASE newsgroups ...

"Network deployment is a two step process. You must install the program and you must install the data files. I have not found a way to do this with a single deployment. I build one deployment that does not include any shared tables. The tables that will reside on a shared network drive are a separate deployment project. The data files project may, or may not include setting up the BDE alias. The start-up program checks for the existence of the BDE alias, if it is not found, allows the user to locate the files. Once the files are found, the program creates the alias on the users' machine. A simplified version of the code for that would look something like the following, although a more complete version would check for the existence of all the files necessary."

   //Code as provided by Gary White, some of it is
   // based on code by Romain Strieff and Jim Sare
   if not databaseFound( "yourDatabaseName" )
      cPath = getDirectory()
      CreateAlias( "yourDatabaseName", cPath )
   endif

   function dataBaseFound( cDatabase )
      local d, dbArray 
      d = new database()
      dbArray = d.getSchema( "Databases" )
      release object d
   return dbArray.scan( cDatabase ) > 0

  function CreateAlias(cAliasName,cPath)
     //Creates a DBF Alias

     if type("DbiAddAlias") # "FP"
        extern cint DbiAddAlias(;
               cHandle,;
               CPTR,;
               CPTR,;
               CPTR,;
               clogical) idapi32
     endif
  return DbiAddAlias(null,;
                     DBCSToSBCSZ(cAliasName),;
                     DBCSToSBCSZ("DBASE"),;
                     DBCSToSBCSZ("PATH:" + cPath),;
                     TRUE)=0

   // necessary for above
   Function DBCSToSBCSZ(c)
      LOCAL cTemp, x

      cTemp = Replicate(Chr(0), ((Len(c) + 1) / 2) + ;
                                ((Len(c) + 1) % 2))
      For x = 1 To Len(c)
         cTemp.SetByte(x - 1, Asc(SubStr(c, x)))
      EndFor

   RETURN cTemp


DEO - Dynamic External Objects

DEO is actually pretty easy to set up. The actual concept is discussed in the online help, the User's Guide, and the Language Reference for dBASE, so we won't go into all of the "why you should" (or should not) use it aspects.

To set this up for your application, make sure that only the objects you want to include in the application are selected in the Project Manager. It might be best to simply not include any forms, custom controls, reports, etc., that you are using via DEO in the project manager at all. As you do not necessarily want them compiled into the executable, it is easier to not include them at all. However, you will need to be able to compile all of your forms, program files, reports, and other files into deployable OBJECT files (.wfo, .pro, etc.).

One suggestion is to create a simple program that simply compiles everything, along the lines of:

   // Compile necessary files:
   // custom controls:
   compile :MySource:MyCustomClass.cc
   compile :dUFLP:preview.wfm
   compile :dUFLP:ini.cc
   compile :dUFLP:stringex.cc
   compile :dUFLP:bdealias.cc
   
   // datamodule
   compile :MySource:MyData.dmd
   
   // programs:
   compile :MySource:Start.prgeditscreen
   // etc.

When this is done executing, if you included everything needed, then follow the steps to BUILD your executable as shown above.

Details for deploying a DEO-based application are included in the Knowledgebase article on using Inno Setup. Make sure you include in the application's .INI file the appropriate entries for DEO file locations.


That's it

Well, parts of this could be covered in more depth, but the idea was to give you a basic grounding in using the Compiler options with dBASE. If you need more, check online help for both dBASE (project manager, BUILD ...); and your deployer software. In addition, you are encouraged to visit the dBASE newsgroups (see www.dbase.com for details) to obtain assistance.

Don't forget that the Knowledgebase is full of other useful documents as well as this one ...


DISCLAIMER: the author is an employee of dBASE, Inc., but has written this on his own time. If you have questions regarding this .HOW document, or about dB2K you can communicate directly with the author and dBVIPS in the appropriate newsgroups on the internet.

.HOW files are created as a free service by members of dBVIPS and dBASE, Inc. employees to help users learn to use dBASE more effectively. They are edited by both dBVIPS members and dBASE, Inc. Technical Support (to ensure quality). This .HOW file MAY NOT BE POSTED ELSEWHERE without the explicit permission of the author, who retains all rights to the document.

Copyright 2002, Kenneth J. Mayer. All rights reserved.

Information about dBASE, Inc. can be found at:

       http://www.dbase.com
    

EoHT: PrepareToDeploy.htm -- October, 2002 -- KJM