Jeff Webb, Mike McKelvy, Ronald Martinsen, Taylor Maxwell, Michael Regelski September 1995 Special Edition Using Visual Basic 4 - Chapter 29 1-56529-998-1 Computer Programming computer programming Visual Basic OLE database applications ODBC VB VBA API This book is an all-in-one reference that provides extensive coverage of every topic and technique for creating optimized and customized applications with Visual Basic.

Chapter 29

Distributing Integrated Applications


After you finish building and testing your integrated application, you're ready to distribute it—right? Wrong. Before distributing any integrated application, there are several things that you must know. This chapter guides you through the distribution process.

In this chapter, you learn more about the following:

Preventing Distribution Embarrassments

You've just completed your program and tested it for several hours (or days) on your system. You're convinced that you have a "bug-free" application, so you copy your executable to a floppy and take it to your friend's computer. You spend 20 minutes telling him how awesome your program is, just to arouse his curiosity. After he is so excited that he has declared you a "Computer Genius," you copy your program to his hard disk. You double-click on your program in File Manager, and a big error message comes up on the screen.

Your face turns red, and you begin to sweat. You try to handle the situation by reading the message to yourself and trying to run your program again. Nothing happens. After trying everything you know, with no success, you look to your friend and say, "What the heck is wrong with your stinking computer?"

Has this happened to you? If not, then you better read this chapter to prevent it from happening. If it has, you already know the importance of this chapter.

This chapter discusses some of the important distribution-related issues that will help you to maintain your status as a computer genius, and keep you from jumping off a bridge in embarrassment. Read this chapter carefully and refer to it often, or else you'll be the next victim of a poor distribution attempt.

Distributing Your Applications

The first and most important part of a successful distribution is to ensure that you have the correct files in the correct place. If you forget one file, or if you put it in the wrong directory, your application will not run. Forgetting distribution files also shows sloppiness on the part your company, so it's something that you should avoid at all costs. See Chapter 30, "Distributing Your Applications," in the Visual Basic Programmers Guide for a complete listing of the supporting files that Visual Basic and its custom controls require.

Even if you write your own setup program, you should use the Setup Wizard. The Setup Wizard searches your application for all the required distribution files and copies them to a floppy disk. After Setup Wizard finishes, you can look on the disk to see which files your application requires (ignore the SETUP*.* files) and copy them to your setup disk.

Licensing Considerations

When making your distribution disk, you should copy only those files that you have a license to distribute. Distributing unlicensed files can lead to severe legal action against you and your company, as well as extreme embarrassment. Even if you don't realize that you are illegally distributing a file, you can still get into big trouble.

Play it safe and distribute only those files that you have a legal right to distribute. When in doubt, contact the company that wrote the software or contact Microsoft.

Even if a file comes with a program that you own (for example, clip art from Corel Draw or certain Visual Basic files), you don't necessarily have the legal right to distribute the file.

Handling Missing Files That Can't Be Licensed

If you can't purchase a license to distribute a file, you have to require that your users own the program or file on which your application depends. Because you are likely to write an application that depends on one or more Microsoft Office applications (which you can't distribute), you will have to notify the user of which Office applications (and versions) that he or she must have installed before running your program.

Ensuring Proper Installations—Setup Programs

Copying all the proper files to your disk doesn't mean that they will get copied to the correct directory on the user's system. If your application doesn't have a setup program that does everything necessary to run your application, the odds of it working on another computer are very poor. You should always write a good setup and uninstall program.

The advantages of a good setup and uninstall program are many, because it does the following:

Because you purchased Visual Basic 4.0, you have no excuse not to have a setup program, because VB4 includes the Setup Wizard. The Setup Wizard is a great utility that creates a setup/uninstall disk for your Visual Basic application and makes sure that all the files that your application requires are on it.

If your application requires a more robust setup program, you can always modify the source code that Setup Wizard creates and add your application-specific features. If you need even more advanced features and you don't know how to code them, you can always purchase one of the many prewritten setup programs on the market.

A good setup program pays for itself after you sell your first five to ten applications (depending on the product cost), so you have no excuse not to write one (no matter how small your application is).

All Windows 95 certified applications will be required to have a setup program that installs and uninstalls all of its files, so now is the time to learn how to write a good setup program. If you have the Windows 95 SDK, you also can consider using the InstallShield 95 setup and uninstall program that comes with the SDK.

If possible, set up a single system with only your target operating system installed. If your application can run on a system that has only the operating system installed, the odds are that your setup disk is good.

Handling Missing Components—Gracefully

When creating integrated applications that depend on multiple programs being present, you must ensure that your program is prepared to handle a missing component. For example, suppose that you want to create an About box that has a System Info button like the ones in the Office applications, as shown in figure 29.1.

Fig. 29.1

You can add Microsoft's System Info button to your applications.

You can't legally distribute the System Information program, so your program can show or hide that button depending on whether that component is present. Listing 29.1 demonstrates how to accomplish this task.

Listing 29.1 This Example Shows How Your Application Can Handle Missing Components Gracefully

'****************************************************************
' FRMABOUT.FRM - Demonstrates how to handle a missing component.
'****************************************************************
Option Explicit
Private WinDir As String
#If Win32 Then
Const SYSINFO = "msapps\msinfo\msinfo32.exe"
Private Declare Function GetWindowsDirectory& Lib "Kernel32" _
Alias "GetWindowsDirectoryA" (ByVal buffer$, ByVal bufLen&)
#Else
Const SYSINFO = "msapps\msinfo\msinfo.exe"
Private Declare Function GetWindowsDirectory% Lib "Kernel" _
(ByVal buffer$, ByVal bufLen%)
#End If
'****************************************************************
' Unload the form.
'****************************************************************
Private Sub cmdOk_Click()
Unload Me
End Sub
'****************************************************************
' Start the Microsoft System Information program.
'****************************************************************
Private Sub cmdSysInfo_Click()
Shell WinDir & SYSINFO, vbNormalFocus
End Sub
'****************************************************************
' Load the form and determine if the System Info button should
' be visible.
'****************************************************************
Private Sub Form_Load()
'************************************************************
' Always use system colors.
'************************************************************
Lines(0).BorderColor = vb3DHighlight
Lines(1).BorderColor = vb3DShadow
Lines(2).BorderColor = vb3DHighlight
Lines(3).BorderColor = vb3DShadow
BackColor = vb3DFace
'************************************************************
' Change the picture displayed in the image control.
'************************************************************
img.picture = Me.Icon
'************************************************************
' Center the form.
'************************************************************
Move (Screen.Width - Width) \ 2, (Screen.Height - Height) \ 2
'************************************************************
' Get the path to the Windows directory.
'************************************************************
WinDir = Space(2048)
WinDir = Left(WinDir, GetWindowsDirectory(WinDir, _
Len(WinDir))) & "\"
'************************************************************
'Set visible status depending on the existence of the file.
'************************************************************
cmdSysInfo.Visible = FileExists(WinDir & SYSINFO)
End Sub
'****************************************************************
' Determine if the file exists, and return the result.
'****************************************************************
Private Function FileExists(sFileName As String) As Boolean
On Error Resume Next
FileExists = IIf(Dir(sFileName) <> "", True, False)
End Function

The key element of this program is determining whether the file exists. If MSINFO.EXE is present, the button's Visible property changes to True. Otherwise, the program sets its Visible property to False and hides the button. Figure 29.2 shows how the sample program looks when MSINFO.EXE exists.

Fig. 29.2

The System Info button displays only if MSINFO.EXE exists.

You might think that it is much more difficult to handle a missing Office application, but it really isn't. Listing 29.2 shows how easy it is to determine whether an Office application is present.

Listing 29.2 Checking for An Application's Existence Is Easy

'*****************************************************************
' FRMEXISTS.FRM - Lists the existence of several Office apps.
'*****************************************************************
Option Explicit
#If Win16 Then
Private Declare Function GetProfileString% Lib "Kernel" (ByVal _
sSection$, ByVal sKey$, ByVal sDef$, ByVal sRetStr$, _
ByVal iSize%)
#End If
'*****************************************************************
' Checks to see if a file exists.
'*****************************************************************
Function FileExists(sFileName$) As Boolean
On Error Resume Next
FileExists = IIf(Dir(Trim(sFileName)) <> "", True, False)
End Function
#If Win32 Then
'*****************************************************************
' This function determines if an application is present by seeing
' if there is any text in the Registry for the provided SubKey.
'*****************************************************************
Public Function IsAppPresent(strSubKey$, strValueName$) As Boolean
IsAppPresent = CBool(Len(GetRegString(HKEY_CLASSES_ROOT, _
strSubKey, strValueName)))
End Function
#Else
'*****************************************************************
' This function determines if an application is present.
' The sExtension arg is the 3-letter extension of its data files.
' The sDefaultPath is where you think the app might be installed.
'*****************************************************************
Public Function IsAppPresent(sExtension$, sDefaultPath$) _
As Boolean
Dim sAppPath As String
'*************************************************************
' Check the [Extensions] section of the WIN.INI to see where
' the app is located. If the extension is not found, then
' the default EXE path (sDefaultPath) is checked.
'*************************************************************
sAppPath = Space(4098)
GetProfileString "Extensions", sExtension, sDefaultPath __
& " ^" & sExtension, sAppPath, Len(sAppPath)
'*************************************************************
' [Extensions] section stores info in the following format:
' <extension>=<application path> ^<extension>
' To get the application path, you'll need to take everything
' to the left of the caret (^).
'*************************************************************
sAppPath = Left(sAppPath, InStr(sAppPath, "^") - 1)
'*************************************************************
' Return whether or not the application is present.
'*************************************************************
IsAppPresent = FileExists(sAppPath)
End Function
#End If
'*****************************************************************
' Unloads the form.
'*****************************************************************
Private Sub cmdExit_Click()
Unload Me
End Sub
'*****************************************************************
' Performs some initialization steps, and list the existence of
' certain Office apps.
'*****************************************************************
Private Sub Form_Load()
Move (Screen.Width - Width) / 2, (Screen.Height - Height) / 2
Print 'Print blank line
'*************************************************************
' Call the appropriate version of IsAppPresent, depending on
' the current platform.
'*************************************************************
#If Win32 Then
Print " Access", IsAppPresent("Access.Database\CurVer", "")
Print " Excel", IsAppPresent("Excel.Sheet\CurVer", "")
Print " PowerPoint", IsAppPresent("PowerPoint.Slide\CurVer", _
"")
Print " Word", IsAppPresent("Word.Document\CurVer", "")
#Else
Print " Access", IsAppPresent("mdb", "c:\access\msaccess.exe")
Print " Excel", IsAppPresent("xls", "c:\excel\excel.exe")
Print " PowerPoint", IsAppPresent("ppt", _
"c:\powerpnt\powerpnt.exe")
Print " Word", IsAppPresent("doc", "c:\winword\winword.exe")
#End If
End Sub

The key feature in this application is the IsAppPresent function. In the 16-bit version of Windows, all you need to do to find out whether an application exists is to check whether its executable is present. Because the WIN.INI file contains the location of most executables in the [Extensions] section, locating the application is easy. Figure 29.3 shows the program in listing 29.2 running.

Fig. 29.3

The APPEXIST.VBP project determines which Office applications exist.

In the 32-bit version of Windows, you will want to search the Registry to make sure that an application is present. The following module, REGISTRY.BAS, retrieves a string from anywhere in the Registry (unlike VB4's GetSetting function):

'*****************************************************************
' REGSITRY.BAS - Contains the code necessary to access the Windows
' registration datbase.
'*****************************************************************
#If Win32 Then
Option Explicit
'*****************************************************************
' The minimal API calls required to read from the Registry.
'*****************************************************************
Private Declare Function RegOpenKey Lib "advapi32" Alias _
"RegOpenKeyA" (ByVal hKey As Long, ByVal lpSubKey As String, _
phkResult As Long) As Long
Private Declare Function RegQueryValueEx Lib "advapi32" Alias _
"RegQueryValueExA" (ByVal hKey As Long, ByVal lpValueName As _
String, lpReserved As Long, lptype As Long, lpData As Any, _
lpcbData As Long) As Long
Private Declare Function RegCloseKey& Lib "advapi32" (ByVal hKey&)
'*****************************************************************
' The constants used in this module for the regsitry API calls.
'*****************************************************************
Private Const REG_SZ = 1 ' Unicode null terminated string
Private Const REG_EXPAND_SZ = 2 ' Unicode null terminated string
' with environment variable
' references.
Private Const ERROR_SUCCESS = 0
'*****************************************************************
' The numeric constants for the major keys in the regsitry.
'*****************************************************************
Public Const HKEY_CLASSES_ROOT = &H80000000
Public Const HKEY_CURRENT_USER = &H80000001
Public Const HKEY_LOCAL_MACHINE = &H80000002
Public Const HKEY_USERS = &H80000003
Public Const HKEY_PERFORMANCE_DATA = &H80000004
'*****************************************************************
' GetRegString takes three arguments. A HKEY constant
' (listed above), a subkey, and a value in that subkey.
' This function returns the string stored in the strValueName
' value in the Registry.
'*****************************************************************
Public Function GetRegString(hKey As Long, strSubKey As String, _
strValueName As String) As String
Dim strSetting As String
Dim lngDataLen As Long
Dim lngRes As Long
'*************************************************************
' Open the key. If success, then get the data from the key.
'*************************************************************
If RegOpenKey(hKey, strSubKey, lngRes) = ERROR_SUCCESS Then
strSetting = Space(255)
lngDataLen = Len(strSetting)
'*********************************************************
' Query the key for the current setting. If this call
' succeeds, then return the string.
'*********************************************************
If RegQueryValueEx(lngRes, strValueName, ByVal 0, _
REG_EXPAND_SZ, ByVal strSetting, lngDataLen) = _
ERROR_SUCCESS Then
If lngDataLen > 1 Then
GetRegString = Left(strSetting, lngDataLen - 1)
End If
End If
'*********************************************************
' ALWAYS close any keys that you open.
'*********************************************************
If RegCloseKey(lngRes) <> ERROR_SUCCESS Then
MsgBox "RegCloseKey Failed: " & strSubKey, vbCritical
End If
End If
End Function
#End If

Application Performance Considerations

Another major pitfall that you face when distributing an integrated application is performance considerations. If the target system doesn't have enough random access memory (RAM) or is low on system resources, your application can fail. In this section, you learn how to ensure that your application thrives on its targeted system.

System Requirements

After you create your integrated application, you need to gather the system requirements of all products that your applications use. Using these system requirements, you can take the highest requirements from each to determine what your application requires.

Next, you should take the following steps to determine what minimum free system resources your application requires:

  1. Exit and restart Windows.
  2. From Notepad's About box, check the available amount of system resources. Write this number down.
  3. Close Notepad's About box and run your application.
  4. Test every feature of your application (except any that terminate it).
  5. While your application is still running, return to Notepad's About box to see what the System Resources line reads now.
  6. Subtract amount in step 5 from the amount in step 2. This is the amount of system resources your application consumes.

Now you're ready to build your system requirements list. Your system requirements should include the following information:

Most integrated applications have the following system requirements:

After establishing your user requirements, you should put them in the front of your product manual, in your README.TXT file, and on your product packaging (if any). This is important because the customer must know what your product requires before purchasing it.

Hardware Performance Considerations

Because you're reading this book, you're probably a real "power user." You probably have at least a 486–50 or greater system with 16M or more RAM. This means that your application really flies when you use it, but what happens when you install it on a wimpy machine (for example, a 486-25 with 8M of RAM)? If your answer is that "it croaks," you must reconsider how you have written your application.

Handling Wimpy Machines

Writing a program for a system that is less powerful than your own is difficult, but important if you want your program to succeed. Because most institutions (businesses, government, schools, and so on) are usually two or more years behind in technology, you neglect a big market by writing applications that run only on systems that are as fast (or faster) than your own.

Of course, you can't target systems that don't meet your system requirements, but your program should run (at least partially) on any 486 (or higher) system with at least 8M of RAM.

The most important thing about handling a wimpy machine is to ensure that your program doesn't perform unexpectedly during any of the following stressful situations:

Each of these situations can cause your program to fail miserably, so you must prepare to handle them.

If possible, you should always try to test your application on a 386-33 with 4M of RAM that is running its video at 640X480X16 and prints to a dot matrix printer. This test will indicate how your program responds to wimpy machines.

Handling Low Memory Situations

No matter how much RAM a system has, your application will eventually face a low memory or low system resource situation. By handling the situation gracefully, you show your customer that you thought of everything when you developed your application, and keep the technical support calls to a minimum.

When a Visual Basic application gets low on memory, the value of Err is either 7 (a standard out-of-memory error) or 31001 (an OLE out-of-memory error). Therefore, your application should always watch for these error messages. It's also useful if your application can do something internally to try to free up some more memory. Listing 29.3 demonstrates some of the steps that your application can take to handle low memory situations.

Listing 29.3 Every Application Should Be Prepared to Handle Low Memory Situations

'************************************************************
' FRMLOMEM.FRM - Demonstrates good error-handling techniques.
'************************************************************
Option Explicit
'************************************************************
' Centers the form
'************************************************************
Private Sub Form_Load()
'********************************************************
' Tell your app where to go when an error occurs.
'********************************************************
On Error GoTo Form_Load_Err
'********************************************************
' Center the form and the label.
'********************************************************
Move (Screen.Width - Width) / 2, (Screen.Height - Height) / 2
lblMsg.Move (ScaleWidth - lblMsg.Width) / 2, _
(ScaleHeight - lblMsg.Height) / 2
'********************************************************
' Raise an error to simulate a low memory situation.
'********************************************************
Err.Raise InputBox("Enter a error number:", Default:=7)
Exit Sub
Form_Load_Err:
'********************************************************
' When an error is triggered, jump to the error handler.
'********************************************************
ErrHandler Err.Number, "Form_Load"
End
End Sub

This program prompts the user for an error number and passes that number to Err.Raise to simulate an error. After the error is triggered, the program transfers control to the following error-handling routine:

'************************************************************
' A generic error handler.
'************************************************************
Sub ErrHandler(iErr%, sCallingProc$)
Dim msg$, res%
'********************************************************
' Prevent crashes in your error handler with Resume Next
'********************************************************
On Error Resume Next
'********************************************************
' If out of memory error, then tell use to free memory
'********************************************************
If iErr = 7 Or iErr = 31001 Then
'****************************************************
' Here is a good place to unload any picture boxes,
' hide unnecessary controls, close DDE links or OLE
' objects, erase arrays, and set object variables
' = Nothing.
'****************************************************
msg = "Your system is extremely low on memory, so "
msg = msg & "please close any applications "
msg = msg & "that you (or this application) are "
msg = msg & "not using."
'********************************************************
' Otherwise tell the user what error occurred, and where
' it was triggered. (This is useful during tech support
' calls).
'********************************************************
Else
msg = "A """ & Error(iErr) & """ error has occurred "
msg = msg & "in this applications " & sCallingProc
msg = msg & " procedure. " & vbLf & vbLf & "Please "
msg = msg & "consult ""Appendix E: Error Messages"" "
msg = msg & "for instructions on how to correct "
msg = msg & "this error."
End If
'********************************************************
' Display the appropriate error message.
'********************************************************
MsgBox msg, vbExclamation
End Sub

After the error has been triggered, the error handler displays an appropriate error message for the user. If the error was an out-of-memory error, the message says to close any unnecessary applications to free up some more memory. Figure 29.4 shows the error message.

Fig. 29.4

A good error message tells the user what to do to fix the error.

Low or Insufficient Disk Space

Because they usually have large hard disks, programmers can easily forget that others aren't so fortunate. You must prepare your application (especially your setup program) for the dreaded Err 61 (Disk Full) error.

Whenever you create or copy a file, you should always check whether the available disk space is greater than the size of the file that you want to copy or create. If there isn't enough room, you should notify the user to free up some disk space and provide the option of either aborting or trying again. If there is enough room, you should copy your file, but still include an error handler for Err 61. Listing 29.4 is an example of a function that returns the available disk space.

Listing 29.4 The GetDiskSpaceFree Function Returns the Available Disk Space

Option Explicit
#If Win32 Then
Private Declare Function DiskSpaceFree Lib "STKIT432.DLL" Alias _
"DISKSPACEFREE" () As Long
#Else
Private Declare Function DiskSpaceFree Lib "STKIT416.DLL" () _
As Long
#End If
'*************************************************************
' Get the disk space free for a specific drive
'*************************************************************
Public Function GetDiskSpaceFree(sDrive As String)
Dim res As Long
On Error Resume Next
'*********************************************************
' Change to the drive that you wish to check.
'*********************************************************
ChDrive sDrive
res = DiskSpaceFree()
'*********************************************************
' If STKIT4*.DLL or drive can't be found, then return -1.
'*********************************************************
GetDiskSpaceFree = IIf(Err, -1, Format(res, _
"###,###,###,##0"))
End Function
'*************************************************************
' Get the disk space free for the current drive
'*************************************************************
Private Sub Command1_Click()
Caption = GetDiskSpaceFree(Left(CurDir, 1))
End Sub

If you use the GetDiskSpaceFree function, you must make sure that you install STKIT416.DLL or STKIT432.DLL. You can find this file on any disk created by Setup Wizard.

Handling Different Resolution Printers

Beginning programmers often forget that not every user prints to printers that have the same resolution as theirs. Such a mistake can render your program's printing feature useless to some of your customers, and cause you to lose business.

The only good way to handle printing to different printers is to test your printing features on the following printers:

When your program can successfully print to each of these types of printers, your printing feature is ready to ship. The new printer object in Visual Basic 4.0 provides a wealth of new methods and properties to help take advantage of almost any printer that you can install on Windows. Before calling the Windows API printing functions, make sure that you look closely at the new Printer object in VB4.

Developing the UI in 640X480X16

One of the biggest mistakes that a Windows programmer can make is to neglect developing your user interface in 640X480X16 resolution. You might spend over a week developing the perfect user interface, only to discover that your interface is useless on anything less than 800X600X256. Some of the problems that you face by not developing user interface in 640X480X16 are the following:

To make matters worse, if you then try to fix your forms, you might discover that there isn't enough room on your existing forms to hold all of your controls. You could wind up spending another two weeks fixing your user interface because you have to double the number of forms in your application. You might have to delay your perfectly debugged product just because you forgot to plan for a lower resolution.

Before you decide to require your users to run your application in 800X600X256, remember that an estimated 90 percent of all Windows users have their video resolution set to 640X480X16. Because most users don't know how to change their video resolution, it is vital that your application support this common video resolution. Windows 95 might alleviate this problem, but you should still consider 640X480X16 as a target resolution.

As you can see in listing 29.5, you don't even have to call the API to get the video resolution. However, if you want to find out how many colors the screen supports, you have to make a few API calls.

Listing 29.5 A Demonstration of How to Retrieve the Current Video Resolution

'*****************************************************************
' VIDEORES.BAS - Displays the current video resolution.
'*****************************************************************
Option Explicit
#If Win32 Then
Private Declare Function GetDC& Lib "User32" (ByVal hWnd As Long)
Private Declare Function GetDeviceCaps% Lib "GDI32" (ByVal hDC&, _
ByVal iCapability&)
#Else
Private Declare Function GetDC% Lib "User" (ByVal hWnd As Integer)
Private Declare Function GetDeviceCaps% Lib "GDI" (ByVal hDC%, _
ByVal iCapability%)
#End If
'*****************************************************************
' Displays the video resolution in a message box.
'*****************************************************************
Sub Main()
MsgBox GetResolution(True), vbInformation, "Video Resolution"
End Sub
'*****************************************************************
' Determines the width, and height of the screen in pixels,
' and the number of colors the screen can display at one time.
'*****************************************************************
Function GetResolution(bReturnColors As Boolean) As String
Dim iWidth, iHeight, iColors, ScreenHDC
Const BITSPIXEL = 12
Const PLANES = 14
'*************************************************************
' Get the resolution using standard VB methods.
'*************************************************************
iWidth = Screen.Width \ Screen.TwipsPerPixelX
iHeight = Screen.Height \ Screen.TwipsPerPixelY
'*************************************************************
' Get the device context of the screen, and use GetDeviceCaps
' to find out how many colors the screen supports.
'*************************************************************
ScreenHDC = GetDC(0)
iColors = GetDeviceCaps(ScreenHDC, PLANES) * 2 _
^ GetDeviceCaps(ScreenHDC, BITSPIXEL)
'*************************************************************
' Only display the color resolution if the caller wants it.
'*************************************************************
If bReturnColors Then
GetResolution = iWidth & "x" & iHeight & "x" & iColors
Else
GetResolution = iWidth & "x" & iHeight
End If
End Function

The Importance of Documentation and Help

No matter how user-friendly you think your program is, plenty of users still won't be able to figure it out. That's why you must provide a well-written user's manual and online Help file.

The best online Help is a copy of your manual. You can save yourself a lot of time if you first create your Help file, then save it under a different name, and use it to create your manual.

Before shipping any application, you should make sure that your documentation and online Help discuss every element of your program and its output (printout, files, and so on). After completing both, you can link every control in your project to its corresponding topic in your Help file by using the HelpContextID property. After your product is ready to ship, test what happens when you press the F1 key on every control.

A good manual and Help file separates good applications from bad ones. Even if your product is shareware, you'll benefit greatly from spending time on these valuable accessories to your product. You'll also find that you increase your chances to get free magazine reviews when you take the time to document your product well.

Planning and Error Handling

This chapter has saved the most important two aspects of the development process for last: planning and error handling. If you neglect either one of these elements during the development process, your application is destined to fail (or at least require a quick maintenance release).

The Planning and Development Process

Planning should be the first step in your entire development process. A discussion of all the aspects of the development life cycle is beyond the scope of this book, but you can use the following list a guide for every development project:

If you like to code but hate commenting, you might try the following technique. Code first, then comment every line of code last. You then must reread every line of code, which often can uncover fuzzy logic and dead code that you can change or eliminate.

This book could go on for pages citing things that you should do during the planning and development stage, but the preceding list should give you a starting point. See the "From Here" section at the end of this chapter for more information about where you can go to learn more about this important process.

Error Handling

Unless you're some sort of programming god, your application is destined to have run-time bugs that you never expected. The key to handling such bugs is a good error-handling mechanism in your project. The following list describes some of valuable tips:

From Here...

An entire book could be written on the topics covered in this chapter, but this chapter is a good start on successfully distributing your integrated application. If you are interested in obtaining additional information on the topics mentioned in this section, you should do the following: