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).
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.
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" ...
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).
Right click in the project
manager's left pane, and select:
Project Properties
You will see a dialog with three tabs:
Project
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.
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 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.
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