Visual Basic Q&A

As a software engineer, I focus on .NET, especially asp.net, C#, WCF and so on, and I am also very interested in Search Engine Optimization.

Entries for February, 2010

INFO: Identifying the Jet Database Engine Components

Symptoms
DAO is a COM wrapper around the Jet Engine, which is used by MicrosoftAccess, Excel, Project, Visual Basic, and the Microsoft Foundation Classes(among others). It can be confusing which version of Jet you are usingbecause so many applications may distribute Jet onto your machine. Thetables and explanations in this article are intended to help you identifythe version and components of Jet that you are using for the givenapplication.
Resolution
This table displays which version of Jet is shipped with each of thefollowing products.

ApplicationMicrosoft JET version———————————————————————–Microsoft Access 1.01.0Microsoft Access 1.11.1Microsoft Access 2.02.0Microsoft Access 2.02.5 with Microsoft Access Service PackMicrosoft Access 7.03.0Microsoft Access 973.5 with Office 97Microsoft Access 97 SR13.5 with Office 97SR1Visual Basic 3.01.1Visual Basic 3.02.0 with Visual Basic CompatibilityLayerVisual Basic 3.02.5 with Microsoft Access Service PackVisual Basic 4.0 16-bit2.5Visual Basic 4.0 32-bit3.0Visual Basic 5.0 32-bit3.0Visual Basic 5.0 32-bit3.5Visual C++ 4.X3.0Visual C++ 5.03.5Jet 3.51 (web download)3.51 (Latest, 3.5 Binary compatible)
Compatibility Among VersionsWith each new version of Microsoft Jet, enhancements in functionality andchanges to the structure of the database file cause problems with backwardcompatibility. Wherever possible, efforts have been made to ensure an easymigration path among versions. However, incompatibilities do exist. Thefollowing table illustrates how you can use database files and objectsamong different versions of Microsoft Jet.

Jet Version——————————–1.01.12.02.53.03.5———————————————-MDB Version———–1.0YYYYYY1.1NYYYYY2.0NNYYYY3.0NNNNYY
A “Y” indicates that you can use the database without conversion; “N”indicates that you cannot use or convert the database. With DAO code, youcan open any version of any database up to the same version of MicrosoftJet. Microsoft Access is an exception to this rule because it can open onlythose databases with the same version as itself. However, it can link totables with the same or earlier version. In other words, if you upgrade toMicrosoft Jet 3.0, you will still be able to read version 2.x databases.
There is no version 2.5 or 3.5 of an .mdb file (just 2.0 and 3.0), whichare common to the x.0 and x.5 versions of Jet.
Jet 2.0 and Jet 2.5 use identical database formats in every aspect. Jet 2.0can read databases created with Jet 2.5.
Microsoft Jet 3.5 databases have the same structure as Jet 3.0. MicrosoftJet 3.0 can read data from Microsoft Jet 3.5 tables. The main limitationhere is that Microsoft Jet 3.5 may support additional properties on thedatabase object that aren’t recognized or taken advantage of by MicrosoftJet 3.0, but there aren’t any data incompatibilities.
Notice that Visual Basic 3.0 is capable of using three different versionsof Jet each requiring a separate set of dynamic link libraries (DLLs). Thiscan cause problems when your Visual Basic application expects to use Jet2.0 for example, and then you install another Visual Basic applicationusing an earlier version of Jet on the same system that replaces some ofthe version 2.0 DLLs with version 1.1. Typically the problem DLL in thissituation is Vbdb300.dll because it determines which version of the Jetengine will be used.
The following table should help you solve any version conflicts, and helpyou identify the version of Jet you are using. You may use the Wps.exeutility shipped with Visual Basic to find out which version of Jet youcurrently have loaded in memory. Wps.exe is located in the \VB\CDKdirectory of Visual Basic 3.0 Professional, and in \TOOLS\PSS directory ofthe Visual Basic 4.0 CD. Pay special attention to the version informationobtained from File Manager (File, Properties) in Visual Basic 3.0, andMicrosoft System Info. in Visual Basic 4.0 32-bit.
The following files are required by Visual Basic to use the Jet DatabaseEngine:

Jet VersionFileVersionDescription———————————————————————1.1VBDB300.DLL3.00.0528VB/JET supportMSAES110.DLL1.10.0000Expression servicesMSAJT110.DLL1.10.0001Jet 1.1 engineXBS110.DLL1.10.0002External xBASE ISAMBTRV110.DLL1.10.0000External Btrieve ISAMPDX110.DLL1.10.0000External Paradox ISAM2.0 (comlyr)VBDB300.DLL3.00.0529VB/JET supportMSAJT112.DLL1.99.1605Jet 2.x comp. loaderMSAJT200.DLL2.00.0000Jet 2.0 engineXBS200.DLL2.00.0000External xBASE ISAMBTRV200.DLL2.00.0000External Btrieve ISAMPDX200.DLL2.00.0000External Paradox ISAM2.5 (accsvc)VBDB300.DLL3.00.0529VB/JET supportMSAJT112.DLL1.99.1605Jet 2.x comp loaderMSAJT200.DLL2.50.1606Jet 2.5 engineMSJETERR.DLL2.50.1108Error servicesMSJETINT.DLL2.50.1108InternationalXBS200.DLL2.50.1108External xBASE ISAMBTRV200.DLL2.50.1108External Btrieve ISAMPDX200.DLL2.50.1108External Paradox ISAM2.5 (VB4 16)VBDB16.DLL4.00.2422VB/JET supportMSAJT200.DLL2.50.1606Jet 2.5 engineMSJETERR.DLL2.50.1111Error servicesMSJETINT.DLL2.50.1111InternationalXBS200.DLL2.50.1117External xBASE ISAMBTRV200.DLL2.50.1117External Btrieve ISAMPDX200.DLL2.50.1117External Paradox ISAMMSXL2016.DLL2.50.1117External Excel ISAMMSTX2016.DLL2.50.1117External Text ISAM3.0MSJT3032.DLL3.0.0.2118Jet 3.0 engineMSJINT32.DLL3.0.0.2118InternationalMSJTER32.DLL3.0.0.2118Error servicesMSXL3032.DLL3.0.0.2001External Excel ISAMMSRD2X32.DLL3.0.0.2118External Jet 2.0 ISAMMSLT3032.DLL3.0.0.2008External Lotus ISAMMSPX3032.DLL3.0.0.2001External Paradox ISAMMSXB3032.DLL3.0.0.2008External xBASE ISAMMSTX3032.DLL3.0.0.2008External Text ISAM
With Jet 3.5x, there have been multiple releases. The following tableindicates which version of Jet applies to a given product:

Access 97Access 97aFileNameOffice 97VB5Office 97aJet 3.51——————————————————–MSEXCL35.DLL3.50.3428.03.50.3602.53.50.3907.0n/aMSJET35.DLL3.50.3428.03.50.3602.43.50.3907.53.51.0623.4MSJINT35.DLL3.50.3428.03.50.3602.53.50.3907.0n/aMSJTER35.DLL3.50.3428.03.50.3602.03.50.3907.0n/aMSLTUS35.DLLn/a3.50.3602.5n/an/aMSPDOX35.DLLn/a3.50.3602.0n/an/aMSRD2X35.DLL3.50.3428.03.50.3602.03.50.3907.0n/aMSREPL35.DLL3.50.3428.03.50.3602.03.50.3907.13.51.0623.0MSTEXT35.DLL3.50.3428.03.50.3602.03.50.3907.0n/aMSXBSE35.DLL3.50.3428.03.50.3602.03.50.3907.0n/aVBAJET32.DLL3.0.0.69085.0.0.71223.0.0.6908n/aVBAR332.DLL3.0.0.69083.0.0.69083.0.0.6908n/a

INFO: How to Use DDE in Visual Basic to Communicate with Other Windows Programs

Symptoms
This article describes how to use Dynamic Data Exchange (DDE) from a Visual Basic program. Although Visual Basic offers more powerful, robust and reliable intercommunication between programs by using OLE, it still supports the older DDE technology. You can use DDE to link to and share data between programs.
Using OLE to communicate with other programs is better than using DDE with Visual Basic. OLE offers you better performance than DDE does. If a program supports OLE automation, it exposes an “Object Model” you can use to manipulate the program (through code) to complete actions for you. DDE is more useful in communicating with older programs that might not support OLE but do support DDE, and many 16-bit programs fall into this category.
Microsoft recommends that you use OLE rather than DDEto communicate with another program when you are developing your Visual Basic program. However, because there are times when you may need or want to use DDE, this article describes how to use DDE from a Visual Basic program.
Resolution
Visual Basic can exchange data, such as information, commands or keystrokes, with any program that supports DDE. A DDE link requires the following three things:Program nameTopicItemThe program name is the executable (.exe) file name of the source program minus the .exe file extension. The topic describes the type of data that is being exchanged. The topic is specific to the DDE source program. However, “System” is the one universal topic that you can use to query what topics are available in a particular program. The item parameter is the actual data that is being transferred. In Visual Basic, a topic could be a form with a textbox as an item. In Microsoft Excel, a topic could be a spreadsheet with a cell as an item. The program name and topic cannot be modified once the DDE link has been established because any modifications break the connection. The item parameter can be modified to any valid item during the DDE conversation without breaking the DDE link.
Specific to Visual Basic, the LinkTopic property supplies a combination of the program name and topic parameters. The LinkTopic property is available for Label, PictureBox, or TextBox controls which can share data through a DDE connection. The program name and topic parameters are combined by using the pipe character (|) as the separator. For example, to create a DDE link with Microsoft Word as the source program and by using the System topic. the LinkTopic property of a textbox would be:
Text1.LinkTopic=”WinWord|System”When Visual Basic is the source program for the DDE link, the LinkTopic of the form which contains the control to be shared is set to a known name. This known name is used in the LinkTopic of the Visual Basic destination program as the topic information. For example, to access data from a form with a LinkTopic that is set to “DDELink”, a Visual Basic destination program would have a matching control with a LinkTopic set to “program name|DDELink”.
The LinkItem property corresponds to the item parameter in a DDE connection, and this property is set to a corresponding item in the source program, for example, the “Total” cell in an Excel spreadsheet. The LinkItem property is set for the control that is used as in a destination program. When a Visual Basic form is the source in a DDE connection, the name of the control on the form can be the item argument in the program|topic|item string that is used by the destination program. When Visual Basic is used as both the source and destination program, the LinkItem property of the destination program would be set to the name of the control in the Visual Basic source program. For example, with Visual Basic used as both the source and destination program and a text box that is named txtSource as the item in the source program, a corresponding txtData text box in the destination program would have its LinkItem property set to txtSource:
txtData.LinkItem = “txtSource”Before a connection can be established, the mechanism to update the information needs to be set. In a DDE connection, there are three types of links:AutomaticManualNotifyAn automatic link updates the destination information whenever the source is modified. A manual link requires that the data be requested by the destination program, and notify informs the destination program that the source data has been changed but doesn’t actually update the information in the destination program. The one exception to an automatic update is the Picturebox control. Visual Basic does not automatically notify a DDE destination program when the Picture property setting of a PictureBox on a source Form changes. Because the amount of data in a graphic can be very large and because it seldom makes sense to update a destination program as each pixel in the picture changes, Visual Basic requires that you use the LinkSend method to explicitly notify DDE destination programs when the contents of a PictureBox change.
Once a DDE link has been established, there are several methods and events in Visual Basic that can be used to control how data is sent between the source and the destination program.
MethodsLinkRequest: Asks the source program to update the contents of a destination item.
LinkExecute: Sends a command string to the source program.
LinkPoke: Transfers the contents of the item control to the source program. Typically, information in a DDE conversation flows from the source to the destination. However, LinkPoke provides a destination object with the ability to supply data to the source.
LinkSend: Transfers the contents of a PictureBox control to the destination program in a DDE conversation.
EventsLinkOpen: Occurs when a DDE link is being initiated.
LinkClose: Occurs when a DDE link terminates. Either program in a DDE conversation may terminate a link at any time.
LinkError: Occurs when there is an error during a DDE conversation. This event is recognized only as the result of a DDE-related error that occurs when no Visual Basic code is being executed. The error number is passed as an argument.
LinkExecute: Occurs when a command string is sent by a destination program in a DDE conversation. The destination program expects the source program to perform the operation described by the string.
LinkNotify: Occurs when the source has changed the data that is defined by the DDE link if the LinkMode property of the destination control is set to Notify.

INFO: How Setup Wizard and PDW Use Dependency Files

Symptoms
A dependency (.DEP) file contains information about the run-timerequirements of an application or component; it contains informationregarding which files are needed, how the files are to be registered, andwhere they should be installed on the target computer. You can createdependency files for standard Visual Basic projects, ActiveX controls,ActiveX documents, and other ActiveX components.
When a component is used in another project, the dependency information forthe component is incorporated into the project’s dependency information.This dependency information is used by the Setup Wizard (known as thePackage and Deployment Wizard or PDW in Visual Basic 6.0). When you use theSetup Wizard or PDW to generate a setup for your project, the wizard refersto the project’s dependency information to determine which files should bedistributed with your project and how those files should be installed.
All of the ActiveX controls that ship with Visual Basic have a companiondependency file. It is strongly recommended that you generate a dependencyfile for your component, especially if you intend that the component beused in other Visual Basic projects. The Setup Wizard and PDW give you theoption to generate a dependency file for your project or component. Thedependency file may also be generated using a text editor if you cannot usethe Setup Wizard or PDW to create one. The remainder of this articledescribes the syntax for a dependency file.
Resolution
A dependency file is a standard Windows .INI file and can be read andwritten to using the standard Windows APIs (GetPrivateProfileString andWritePrivateProfileString).
There are a few items to note for dependency files:
Dependency files may have multiple sections. The section orderis not significant.Entries are not case-sensitive.Comments are allowed when preceded by a semi-colon (;).The dependency file name is important. The file name prefixmust match the file name of the component it describes. Forexample, a dependency file MyOCX.DEP would correspond to acomponent, such as MyOCX.OCX or MyOCX.DLL.Each section in a .DEP file uses the following syntax:

[Component File Name]Dest=<Destination>UsesN=<Dependent File>Register=<Method of Registration>Version=<Component version>Date=<Component Date>Time=<Component Time>ProgramIconTitle=<Title for Shortcut>ProgramIconCmdLine=<Command Line for Shortcut>
Dest=The Dest= key indicates the destination folder for the component. Thisvalue may be a relative path, a full path, or a path based on any of thefollowing macros (for example, it may be simply a macro, or it may be amacro followed by a backslash and a relative path):

$(AppPath)Indicates the path the user selectsduring setup. $(WinSysPath)Indicates the \Windows\System or\Winnt\System32 folder. $(WinPath)Indicates the \Windows or \Winnt folder. $(ProgramFiles)Indicates the folder specified atHKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\ProgramFilesDir. $(CommonFiles)Indicates the folder specified atHKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\CommonFilesDir. $(CommonFilesSys)Indicates $(CommonFiles)\System inWindows 95, Windows 98, NT 4.0, and Windows 2000,or the same as $(WinSysPath) in NT 3.51. $(MSDAOPath)The location stored in the registryfor DAO components. The Dest= key applies only to the component to which the section applies.By default, all files dependent on the component will also be placed in thesame location. To override the location for a “child,” you can create asection for the “child” and specify a different destination in thatsection.
UsesN=The UsesN= key (where N is an integer) indicates a dependent file for thecomponent. A file specified by a UsesN= key is required for the componentdefined by that section. In a section, N must be sequential and must startwith 1. For an illustration, refer to the following sample section:

[MyOCX.OCX]Dest=$(WinSysPath)Uses1=MyDLL.DLLUses2=MyOCX.TXT In this example, MyOCX.OCX depends upon (or requires) MyDLL.DLL andMyOCX.TXT.
NOTE: If the UsesN keys are not ordered sequentially, or if a number isskipped, dependent files may not be recognized in the section and may notbe acknowledged by the Setup Wizard or PDW.
Register=The Register= key indicates whether the file should be registered and, ifso, how it should be registered. The valid values for this key are:

NoneIf a value is omitted for this key,the file is not registered.$(DllSelfRegister)The file supports self-registrationand self-unregistration via a DLLentry point.$(ExeSelfRegister)The file is a local server thatsupports self-registration throughthe command-line parameter”/RegServer” and self-unregistrationthrough the command-line parameter”/UnRegServer.”$(TLBRegister)The file is a .TLB file and should beregistered.FilenameThe file is registered by callingRegedit.exe with this filename as aCommand-line parameter.$(Remote)Used only by Visual Basic to indicatethat the file is a .VBR file. If the Register= key is omitted altogether, the file is not registered.
Version=(Optional)
The Version= key indicates the version of the component that is needed. TheSetup Wizard and PDW can detect that a .dep file is out-of-date using theVersion= key. The version is specified in the format a.b.c.d, as in thefollowing example:

Version=4.50.10.11
Date=(Optional)
The Date= key is the date stamp of the component that is needed. The SetupWizard and PDW can detect that a .DEP file is out-of-date using this key.This value must always be in the format d/m/yyyy or dd/mm/yyyy, even whenusing a localized Setup Wizard or PDW. For example:

Date=10/5/1996 -or-

Date=04/03/1997 NOTE: This key is ignored if a value is specified for the Version= key.
Time=(Optional)
The Time= key is the time stamp of the component that is needed. The SetupWizard and PDW can detect that a .DEP file is out-of-date using this key.This value must always be in the 24-hour format hh:mm:ss, even when using alocalized Setup Wizard or PDW. For example:

Time=14:05:32 NOTE: This key is ignored if a value is specified for the Version= key.
ProgramIconTitle= and ProgramIconCmdLine=(Optional)
The ProgramIconTitle= key indicates that a shortcut (or Program Managericon for Windows NT 3.51) should be created if the file is installed. Thevalue for the ProgramIconTitle= key is the title given to the shortcut (oricon). The value may be quoted or unquoted. For example:

ProgramIconTitle=My Program Title If you indicate that a shortcut should be created, you can give the commandline for the shortcut by specifying a value for the ProgramIconCmdLine=key. The path that you use for the command-line value may contain themacros listed for the Dest= key. For example:

ProgramIconCmdLine=$(AppPath)\Readme.txt
Localized ComponentsSome components may have different dependencies based on the language. Toinstall a component based on the language setting for the client’scomputer, you may specify a section with the component name followed by thelanguage ID.
For example, VBRUN500.DLL has a satellite DLL for all languages (with theexception of English):

[VBRUN500.DLL]Dest=$(WinSysPath)[VBRUN500.DLL <000C>];000C = primary language ID for FrenchUses1=VB5FR.DLL[VBRUN500.DLL <0007>];0007 = primary language ID for GermanUses1=VB5DE.DLL In this example, if VBRUN500.DLL is installed and the client’s languagesettings are French, VB5FR.DLL will also be installed. Likewise, ifVBRUN500.DLL is installed and the client’s language settings are German,VB5DE.DLL will be installed.
Sample Dependency FileThe following is a sample .DEP file for a component named MyOCX.OCX. Thisdependency file would be named MyOCX.DEP:

[MyOCX.OCX]Register=$(DLLSelfRegister)Dest=$(WinSysPath)Date=1/23/1996Time=10:15:33Version=1.1.13.6Uses1=MyDLL.DLLUses2=MyServer.EXEUses3=VBRUN500.DLL[MyServer.EXE]Dest=$(WinPath)Date=1/23/1996Time=18:52:48Version=1.0.1.0Uses1=VBRUN500.DLLRegister=$(ExeSelfRegister)ProgramIconTitle=My ProgramProgramIconCmdLine=$(WinSysPath)\MyOCX.OCX[MyDLL.DLL]Register=$(DLLSelfRegister)Version=1.0.1.0[VBRUN500.DLL]Dest=$(WinSysPath);Additional Files for International Support[VBRUN500.DLL <0007>]Uses1=VB5DE.DLL[VBRUN500.DLL <000C>]Uses1=VB5FR.DLL MyOCX.OCX is a self-registering file that is installed in theWindows\System folder (or Winnt\System32 folder on NT or Windows 2000). MyOCX.OCX depends upon (requires) three files: MyDLL.DLL, MyServer.EXE, and VBRUN500.DLL.
MyServer.EXE is a self-registering file that is installed in the Windowsfolder (or Winnt folder on NT or Windows 2000). MyServer.EXE has only one dependent file, VBRUN500.DLL. If MyServer.EXE is installed during setup, a shortcut is created with the title “My Program” and the command lineWindows\System\MyOCX.OCX (or Winnt\System32\MyOCX.OCX on NT or Windows 2000).
MyDLL.DLL is also a self-registering file. A destination for MyDLL.DLL isnot specified; thus, it will be placed in the destination path for itsparent, MyOCX.OCX.
VBRUN500.DLL will not be registered because a Register= key is notspecified in its section. VBRUN500.DLL will be placed in the Windows\System(or Winnt\System32) folder. If VBRUN500.DLL is installed during setup,VB5DE.DLL will be installed if the language setting is German and VB5FR.DLLwill be installed if the language setting is French. If the languagesetting is set to something other than French or German, no additionalfiles will be installed.
How Setup Wizard and PDW Search for Dependency InformationWhen the Setup Wizard and PDW need to find dependency information for afile (for example, MyOCX.OCX), they follow a specific path. The wizards usethe following methods to locate a section entitled [MyOCX.OCX]; when thesection is found, the search ends.
If the file has been located in a .DEP file, it will use theinformation in the .DEP file in which it was first found.The Setup Wizard will look in the default master dependencyfile for Visual Basic 5.0 (VB5DEP.INI). The PDW will look in thedefault master dependency file for Visual Basic 6.0 (VB6DEP.INI).Information that is placed in the default master dependency fileoverrides that which might be found elsewhere.The Setup Wizard and PDW will look for a dependency file namedMyOCX.DEP. If the dependency file is found, the wizard will searchfor the section entitled [MyOCX.OCX].It will search for a .DEP file associated with the parent ofMyOCX.OCX and possibly continue up the parent chain until asection entitled [MyOCX.OCX] is located.

INFO: Deploy database applications with the Package and Deployment Wizard (PDW)

Symptoms
The Microsoft Data Object Libraries may be referenced in your Visual Basic project. When the Package and Deployment Wizard (PDW) is used to build the installation, the PDW scans the project files and determines which dependency files need to be distributed.
This article provides the general information you need to distribute any of the following Data Object Libraries with your Visual Basic project: Microsoft Data Access Objects (DAO) 3.51 Object LibraryMicrosoft Data Access Objects (DAO) 3.6 Object LibraryMicrosoft Remote Data Object (RDO) 2.0Microsoft ActiveX Data Objects (ADO) 2.0, 2.1, 2.5, or 2.6 Library
Resolution
The files are listed in the Setup’s file that is created by the PDW for distribution.
For additional information on how each section in the Setup.lst file is used, click the following article number to view the article in the Microsoft Knowledge Base:
189743?(http://support.microsoft.com/kb/189743/) Description of Setup.lst sections The following sections describe points to be aware of when you distribute any of the Data Object Libraries.
Microsoft Data Access Objects (DAO) 3.51 Object LibraryIntrinsic data control incompatibility with Microsoft Access 2000 (Jet 4.0) If you use the intrinsic data control in your project and you attempt to connect to a Microsoft Access 2000 database, you may receive the following error message:

Unrecognized Database Format This error message occurs because the DAO generic data control is based on Jet 3.51 and does not recognize Jet 4.0 database formats. Access 2000 is a Jet 4.0 format database. Prior to Microsoft Visual Studio 6.0 Service Pack 4 (SP4), the workaround for this problem was to open a recordset with DAO code, and then assign it to the recordset property of a data control. For additional information, click the following article number to view the article in the Microsoft Knowledge Base:
238401?(http://support.microsoft.com/kb/238401/) PRB: Unrecognized database format error message when upgrading to Access 2000 This problem does not exist with the data control that ships with Microsoft Visual Studio 6.0 Service Pack 6.
Visual Studio 6.0 Service Pack 6 can be obtained at the Visual Studio 6.0 Service Pack Web site:
http://msdn2.microsoft.com/en-us/vstudio/aa718364.aspx(http://msdn2.microsoft.com/en-us/vstudio/aa718364.aspx)Jet 3.51 OLE DB Provider is not included in MDAC 2.1 or later The Jet OLE DB Provider requires the version number of the provider in order to connect to an Access database. If your application specifies Version 3.51 of the Jet OLE DB provider in a connection string or a UDL, and you install ADO by redistributing MDAC 2.1, you are likely to receive the following error message:

3706: ADO could not find the specified provider This error message occurs because MDAC 2.0 installs version 3.51 of the Jet OLE DB provider while MDAC 2.1 installs version 4.0 of the Jet OLE DB Provider, but does not install version 3.51. For additional information, click the following article number to view the article in the Microsoft Knowledge Base:
197902?(http://support.microsoft.com/kb/197902/) PRB: Jet 3.51 OLE DB Provider is not installed with MDAC 2.1 or later
Microsoft Data Access Objects (DAO) 3.6 Object Library DAO version 3.6 is required for applications that use DAO to read and write to Access 2000 databases. If Access 2000 (or DAO 3.6) is already installed on the destination computer, then no additional steps are required. If it is not, it is necessary to distribute DAO 3.6. However, there is currently no redistributable for DAO 3.6. In order to redistribute DAO 3.6, it is necessary to install DCOM, redistribute MDAC 2.1(GA) or later, and ensure that the DAO DLL is also distributed and registered on the destination computer.
For additional information, click the following article number to view the article in the Microsoft Knowledge Base:
233002?(http://support.microsoft.com/kb/233002/) How to redistribute DAO 3.6
Microsoft Remote Data Object (RDO) 2.0 In order for RDO to be properly distributed and installed, ODBC must already be installed on the destination computer. ODBC can be installed through the odbcst32.exe file, which is located in the ODBC Folder under the SQL/i386 directory on Visual Basic 6.0 Disk 2. ODBC can also be installed by including the MDAC redistributable in the distribution that is outlined in the “References” section covering distributing ADO/MDAC. To determine all of the files needed to distribute for RDO to work successfully on a computer that does not have Visual Basic installed, you can generate a dependency (.dep) file with the Package and Deployment Wizard. To generate a dependency file that shows the files needed for RDO when running the PDW, complete the following steps: Create a Standard EXE project in Visual Basic. Form1 is created by default.Add a reference to Microsoft Remote Data Object 2.0.Save this project and run the Package and Deployment Wizard on it.Select the Package option.On the Package Type, choose Dependency File, and then proceed through the wizard to completion. When you are finished, you have a file with a .dep extension that can be opened with Microsoft Notepad. MSRDO20.dll and its dependencies are shown in this file.
You want to ensure that these files are included with the distribution. If these files are not listed on the Included Files dialog box when you run the Package and Deployment Wizard, include them by clicking Add in the dialog box.
Microsoft ActiveX Data Objects (ADO) 2.0, 2.1 or 2.5 Library The PDW does not distribute mdac_typ unless there is a specific reference to an ADO Library (any version) in the project.
You can also add mdac_typ.exe manually by clicking Add in the Included Files dialog box when you run the Package and Deployment Wizard. The wizard uses the MDAC_Typ.exe file in the …\Wizards\PDWizard\Redist folder. Obtain the MDAC Components at the following Microsoft Web site:
http://msdn2.microsoft.com/en-us/data/aa937695.aspx(http://msdn2.microsoft.com/en-us/data/aa937695.aspx) For additional information how the PDW distributes MDAC, click the following article number to view the article in the Microsoft Knowledge Base:
217754?(http://support.microsoft.com/kb/217754/) How to control which MDAC version the Package and Deployment Wizard (PDW) distributes The installation of Microsoft Data Access Components (MDAC) requires that DCOM be already installed on the destination computer: For Windows 95 computers, install DCOM95.For Windows 98 computers, install DCOM98.Download the latest version of DCOM from the following Microsoft Web page:
http://www.microsoft.com/downloads/details.aspx?familyid=08B1AC1B-7A11-43E8-B59D-0867F9BDDA66&displaylang=en(http://www.microsoft.com/downloads/details.aspx?familyid=08B1AC1B-7A11-43E8-B59D-0867F9BDDA66&displaylang=en) If DCOM is not already installed on the destination computer, you may receive one of the following error messages:

Unable to load file ‘msdadc.dll’ to register it
-or-

DLL registration failed For additional information, click the following article number to view the article in the Microsoft Knowledge Base:
191704?(http://support.microsoft.com/kb/191704/) PRB: Unable to load file to register it during setup

INFO: Avoid Global Variables in Visual Basic COM+ Components

Symptoms
When you use global variables in Visual Basic 6.0 COM+ Apartment components, data may become corrupted. Visual Basic COM+ components use single-threaded apartment (STA) threads. This may cause data to become corrupted under load because of the mechanism that COM+ uses to bind activities to its pooled STA threads. Microsoft does not recommend the use of global variables in Visual Basic COM+ components.
Resolution
Global variables in Visual Basic are slightly different in scope from global variables in a C++ program. Instead of having one copy of a global variable that all instances of a class share, Visual Basic stores a unique copy of each global variable per thread in thread local storage (TLS). If two instances of the same Apartment class are bound to different STA threads, each STA (and, therefore, each of the two instances of that class) has its own copy of the global variable. Changes that one instance (one STA) makes to the value are notseen by the other instance (a different STA) because each TLS is unique to an STA.
When you configure a Visual Basic Apartment component in COM+, the COM+ activity model may cause a global variable to become corrupted. COM+ binds up to five activities to one of its pooled STA threads, depending on the load. Therefore, five different logical chains of execution, or five callers, can all be bound to one STA thread.
More than onethread cannot run in the same STA at the same time. When a COM method makes a call to an object that is bound to an STA, this call is packaged as a WM_USER message that is posted to the hidden window of that STA. When an outgoing apartment method call, or a cross-process remote procedure call (RPC) is made, the COM channel creates a separate thread to make the actual method call, and then enters the message loop and services the next message in the queue.
Because the STA guards data against concurrency but not against reentrancy, a second caller (activity) on that thread uses the CPU and can gain access to the global TLS data while the first caller is still in progress. This second caller has access to the same data in TLS that the preempted first call may have changed. If the data is changed while the second message is being processed, the data reflects this change immediately. When the first call returns, it finds that the data is different from what appeared previously and determines that the data has been corrupted.
For example, configure a Visual Basic Apartment component that has a class named MyVBClass in COM+. MyVBClass contains code to change the global integer variable g_MyVal. The first caller, client X, creates an instance of MyVBClass, and then calls a method to set g_MyVal to 5. In the same method, MyVBClass performs either a cross-apartment or cross-process RPC call to another COM+ component. The COM channel creates an additional thread to make the actual RPC call, and then enters the COM message pump and handles a pending call from client Y.
Client Y sets g_MyVal to 10, completes its work, and then returns. When the call of client Y is completed, the outgoing method call of client X uses the processor again. Client X’s call reads g_MyVal and expects the value that it set previously (5). However, the value 10 is received. To client X, this is a corrupted value.
In any multithreaded execution environment, Visual Basic globals are unique in the TLS of each thread. However, you have little control over which STA your instances are bound to, unless you explicitly configure your component to use COM+ concurrency. However, COM+ concurrency only guarantees that all instances in the same logical thread of execution are bound to the same STA. When you start a different thread of execution, or when you do not use COM+ synchronization, your instances may not be bound to an STA where the correct global representation is stored. This is another way that you can experience problems when you use globals in Visual Basic.
Microsoft recommends that you do not use global variables in Visual Basic components that run in any multithreaded environment such as IIS and COM+. Instead, you can declare private variables in the class, and then expose them by using public properties as shown in the following sample code.Avoid Global Variable Workaround

‘ Private variable for storing the valuePrivate intMyVal As Integer’ Public property to retrieve the valuePublic Property Get MyValue() As IntegerMyValue = intMyValEnd Property’ Public property to assign the valuePublic Property Set MyValue(myVal As Integer)intMyVal = myValEnd PropertyEmulateMTSBehavior WorkaroundAnother way towork around this problem is to set the EmulateMTSBehavior registry key. This setting causes an instance of an object to be created on its own thread. Therefore, you no longer experience the problem of having two instances that share the same TLS data.

Note After you reach the 100 threads with the EmulateMTSBehavior registry key, the behavior returns to the default setting and you can reuse the threads.
Important Depending on your architecture, setting this registry key may adversely affect the performance of your COM+ application. If you decide to set this registry key, thoroughly stress test your application to verify that the performance is acceptable. For additional information, click the following article number to view the article in the Microsoft Knowledge Base:
303071?(http://support.microsoft.com/kb/303071/EN-US/) INFO: Registry Key for Tuning COM+ Thread and ActivityFor more information about how to set the EmulateMTSBehavior registry key, visit the following Microsoft Web site:
http://msdn2.microsoft.com/en-us/library/ms809941.aspx(http://msdn2.microsoft.com/en-us/library/ms809941.aspx)Intrinsic Visual Basic ObjectsIn Visual Basic code, theApp, the Err, and the Printer intrinsic Visual Basic objects are stored on a per-thread basis in TLS. These objects can also experience the problems that concurrent access to TLS can cause. Use these objects very carefully in a multithreaded distributed environment such as COM+ or Microsoft Internet Information Services (IIS).App Object The App object contains read-only information about the Visual Basic application, and also about methods to log events. By using the App.StartLogging method, a developer can change the properties of the App object to control how events are logged using the App.LogEvent method. When you call App.StartLogging to change the way that events are logged, you affect the global App object that is shared for each of your components on that thread. If your application uses the App.StartLogging method, make sure that you call this to set the correct logMode before each call to App.LogEvent.Printer ObjectWhen you set the properties of the global Printer object, all instances of your Visual Basic component on that thread use the new, updated data. If your Visual Basic components change the Printer properties, you must verify that the properties are set correctly immediately before you print. You must verify the Printer properties because another instance of your component on the same thread may have changed the properties between the time that they were set and the time that the document was spooled off to the printer.Err ObjectVisual Basic uses the Err object to store error information when a runtime error is raised in your Visual Basic component. Because the Err object is stored in TLS, each of your components that are on the same thread share the same copy of that Err object.
Verify that you have completed using the Err object before you make any blocking calls that may permit another Visual Basic component on the same thread to run. Do not make any other out-of-process calls, do not raise events, and do not call DoEvents from within your error handling routine until you have completed using the existing data in the Err object or you may obtain incorrect results.
Never pass the Err object outside your Visual Basic component. The Err object is also a private Visual Basic object. Do not pass it outside the component. Whena second object gains access to the Err object, the Err object calls back to the original Visual Basic component on a different STA to use the data. That data may be incorrect for the current object. If you must pass error information outside your component, pass specific data such as the Err.Number and the Err.Description. For more information, visit the following Microsoft Web site:
http://msdn2.microsoft.com/en-us/library/aa716186(VS.60).aspx(http://msdn2.microsoft.com/en-us/library/aa716186(VS.60).aspx)

ImportText.exe Importing Text into Access with ADO/RDO/DAO/Filesys/Automation

Symptoms
The ImportText.exe sample demonstrates various ways to import text files into a Microsoft Access database. There are many ways to import text data to an Access database, and typically the best option is determined by the task requirements.
ADORDODAOFilesysAutomation The sample application attached details the above coding options.
Resolution
The following files are available for download from the Microsoft Download Center:
TextImport.exe(http://download.microsoft.com/download/vb60pro/sample/1/w9xnt4/en-us/textimport.exe)
For additional information about how to download Microsoft Support files, click the following article number to view the article in the Microsoft Knowledge Base:
119591?(http://support.microsoft.com/kb/119591/EN-US/) How to Obtain Microsoft Support Files from Online Services Microsoft scanned this file for viruses. Microsoft used the most current virus-detection software that was available on the date that the file was posted. The file is stored on security-enhanced servers that help to prevent any unauthorized changes to the file.

Collapse this tableExpand this table
FileNameSizeImportText.vbp1,464ImportText.vbw56Sample.out3,346Sample.txt3,346Sample_Header.txt3,708Schema.ini422Schema_Header.ini420TextImport.frm28,678TextImport.frx84TextImport.mdb108,544
All files should reside in the same folder. Run the sample application ImportText.vbp and examine the different import/export options. The sample TextImport.mdb is used and should reside in the application path. The default sample text file is Sample.txt. A Sample_Header.txt file is included and contains the column header for the text file. An alternate schema file, Schema_Header.ini, may be used to demonstrate using the ColNameHeader=True option in the schema file corresponding to the Sample_Header.txt file.
Among the data import options demonstrated, DAO is probably the most efficient (fewest layers) or with the smallest memory footprint; especially if importing to an Access database.
Refer to the following list for an overview of the libraries loaded for each data access method. The FileSys objects sample: Scripting Runtime + DAO libraries + Jet librariesThe RDO sample: RDO libraries + ODBC libraries + ODBC Jet library + Jet libraries + Text ISAM driverThe ADO (the default example): ADO libraries (OLEDB + MSDASQL) + ODBC libraries + ODBC Jet library + Jet libraries + Text ISAM driverThe Automation sample: MSOffice Runtime library. For the DAO sample: DAO libraries + Jet libraries + Text ISAM driver The following function is the DAO object sample in the TextImport.vbp application. This code is used in the application when you click the DAO radio button before importing. You can modify the DAO sample by adding a recordset and a loop for data manipulation just as in the FileSys objects example.

Sub DAOOpenTextFileImport()On Error GoTo ErrHandlerlblAction.Caption = “DAO Import…”Dim daoDB As DAO.DatabaseDim strSQL As StringIf chkCreateTbl.Value = 1 ThenDBEngine.IniPath = App.Path & “\Schema_Header.ini”ElseDBEngine.IniPath = App.Path & “\Schema.ini”End IfSet daoDB = OpenDatabase(App.Path, False, False, _”Text;Database=” & App.Path & “;table=” & txtFile.Text)If chkCreateTbl.Value = 1 Then’Use this if you do not already have a table created in Access.’Creates and appends the data in one step.strSQL = “SELECT * INTO [" & txtTable.Text & "] IN ‘” & _App.Path & “\” & txtDatabase.Text & ” ‘”strSQL = strSQL & “FROM ” & txtFile.TextdaoDB.Execute strSQLElse’Delete data before importing – use if necessary.strSQL = “DELETE FROM [" & txtTable.Text & "] IN ‘” & _App.Path & “\” & txtDatabase.Text & “‘”daoDB.Execute strSQL’Append data to Access table.strSQL = “INSERT INTO [" & txtTable.Text & "] IN ‘” & _App.Path & “\” & txtDatabase.Text & “‘”strSQL = strSQL & “SELECT * FROM ” & txtFile.TextdaoDB.Execute strSQLEnd IfGoTo ExitSubErrHandler:lblAction.Caption = “DAO Import – Error.”MsgBox “Error: ” & Err.Number & vbCrLf & Err.DescriptionExitSub:lblAction.Caption = “Complete…”daoDB.CloseSet daoDB = NothingEnd Sub The following function is the FileSys object sample in the TextImport.vbp application. This code is used in the application when you select the FileSys radio button before importing. Notice in the sample code that to create the table layout in Access, based on the Schema_Header.ini file, there is no need to loop through the header file and create the table manually if you use the Text ISAM driver. Although, if you are using the Text ISAM driver then there is no need to use the FileSystemObject (and that is part of the point) unless you must use the FileSystemObject to import, then use DAO and do it in one as shown in the DAO sample code. Since you must use DAO anyway (to create the recordset object) even if you are doing data manipulation on import, then use DAO for the entire process since you already have it loaded in memory to create the recordset.

Private Sub FileSysImport()On Error GoTo ErrHandlerlblAction.Caption = “FileSys Import…”Dim daoDB As DAO.DatabaseDim daoRs As DAO.RecordsetDim fs As FileSystemObjectDim ts As TextStreamDim inLine As VariantDim strSQL As StringDim i As IntegerIf chkCreateTbl.Value = 1 Then’This is an eazy way to create the Table layout in Access based on the Schema_Header.ini file.DBEngine.IniPath = App.Path & “\Schema_Header.ini”Set daoDB = OpenDatabase(App.Path, False, False, “Text;Database=” & App.Path & “;table=” & txtFile.Text)strSQL = “SELECT * INTO [" & txtTable.Text & "] IN ‘” & App.Path & “\” & txtDatabase.Text & ” ‘”strSQL = strSQL & “FROM ” & txtFile.Text & ” WHERE 1=0″daoDB.Execute strSQLSet daoDB = NothingSet daoDB = OpenDatabase(App.Path & “\” & txtDatabase.Text, False, False)ElseDBEngine.IniPath = App.Path & “\Schema.ini”Set daoDB = OpenDatabase(App.Path & “\” & txtDatabase.Text, False, False)strSQL = “DELETE * FROM [" & txtTable.Text & "] IN ‘” & App.Path & “\” & txtDatabase.Text & “‘”daoDB.Execute strSQL, dbFailOnErrorEnd IfstrSQL = “SELECT * FROM [" & txtTable.Text & "] WHERE 1=0″Set daoRs = daoDB.OpenRecordset(strSQL, dbOpenDynaset, dbAppendOnly)Set fs = New FileSystemObjectSet ts = fs.OpenTextFile(App.Path & “\” & txtFile.Text, ForReading, False, TristateUseDefault)’This skips the column header.If chkColHeader.Value = 1 TheninLine = Split(ts.ReadLine, “,”)End IfWhile Not ts.AtEndOfStreaminLine = Split(ts.ReadLine, “,”)daoRs.AddNewFor i = 0 To UBound(inLine) – 1daoRs.Fields(i).Value = Left(inLine(i), daoRs.Fields(i).Size)Next idaoRs.UpdateWendGoTo ExitSubErrHandler:lblAction.Caption = “FileSys Import – Error.”MsgBox “Error: ” & Err.Number & vbCrLf & Err.DescriptionExitSub:lblAction.Caption = “Complete…”If Not ts Is Nothing Then ts.CloseIf Not daoRs Is Nothing Then daoRs.ClosedaoDB.CloseSet daoRs = NothingSet daoDB = NothingSet ts = NothingSet fs = NothingEnd Sub The simplest example is the Automation sample. A sample TextImport.mdb is used and the example import/export specifications have been created in the sample .mdb file: Sample and sample w/columns. You can find the specification property setting on the Properties tab of the Tab control. To import with or without the column names in the first row create another import/export specification and put the name of that specification in the text box txtSpecName on the tab control. An example specification is included in the sample .mdb file: Sample w/columns. To import the text file with Access Automation you can simply execute the DoCmd.TransferText method of the Access object.

Private Sub AccessAutomateImport()’Assumes table already exists.On Error GoTo ErrHandlerlblAction.Caption = “Access Automation…”Dim AccessApp As access.ApplicationDim strDB As StringstrDB = App.Path & “\” & txtDatabase.TextSet AccessApp = New access.ApplicationAccessApp.OpenCurrentDatabase strDB’To Import with/without Column names in first row create another Import/Export Specification’and put the name of that specification in the Text box ‘txtSpecName’ on the Tab Control.’An example Specification is included in the sample MDB – ‘Sample w/columns’.AccessApp.DoCmd.TransferText acImportDelim, txtSpecName.Text, txtTable.Text, App.Path & “\” & txtFile.TextAccessApp.CloseCurrentDatabaseGoTo ExitSubErrHandler:lblAction.Caption = “Access Automation – Error.”MsgBox “Error: ” & Err.Number & vbCrLf & Err.DescriptionExitSub:lblAction.Caption = “Complete…”appAccess.QuitSet appAccess = NothingEnd Sub For additional details and code refer to the sample application TextImport.exe.