Visual Basic Bug list


These are bugs I have found in Visual Basic that are not fixed in Visual Basic 6 through service pack 2 and/or 3. This page is to help developers with these issues since Microsoft has chosen not to put these bugs in their knowledge base. In most cases I hope to list the workarounds. See Bob Consorti's incorporation of some of the P&DW fixes as well as others at http://ourworld.compuserve.com/homepages/onthree/vb6.html

The official release notes in service pack 3 do not mention fixes to all of the bugs listed here. Briefly scanning the code seems to confirm this. However, there are many changes to the P&DW code and I have not confirmed which of the bugs are fixed, which not by service pack 3.

You can try service pack 3 ( http://msdn.microsoft.com/vstudio/sp/default.asp) first, to see if this resolves your problems. I've noticed sp3 cleans up the P&DW code by reducing goto statements and handling types more precisely. However, it introduces some serious bugs. As time permits, I'll update this page with sp3 changes. Check what's new for updates.

If you already made changes to your setup1.vbp before upgrading to service pack 3, you may need to be careful restoring the setup1 project to its original state. The sp3 install warns if non-version files are newer, they may not get overwritten with the new ones.

Items listed as (SP3) are bugs introduce in SP3, (SP2) are bugs that are fixed in SP3, (SP2 & SP3) are bugs both in SP2 and SP3, and those without any indicator means I have not verified it is fixed in SP3.


Package and Deployment Wizard

(Also see: http://support.microsoft.com/support/vbasic/pdw.asp)

Install is very very slow

This is because every file is uncompressed from the cab files one at a time even if they don't need to be installed. And if the install file is the same version as the existing file, it copies it anyway. As a workaround, specify multiple cab files.

Also see Every file installed is logged as new below.

Install fails if temp folder is missing or on different drive

In setup1.bas move:
AddDirSep mstrConcatDrive
after:
If mstrConcatDrive <> vbNullString Then
If bootstrap files are loaded after a reboot, they will fail if the temp folder is on a different disk drive than the system folder. Either move temp file to same drive or move files in winint.ini file before rebooting.

Not mentioned in Microsoft's knowledge base, there are two additional problems that can cause install to continually attempt to update bootstrap files after reboot.

If someone has a command in their autoexec.bat file that deletes files from the temp directory, the bootstrap files never get copied after reboot.

Another case I have seen can be fixed by deleting left over files as described in Disk n not found below. I don't know why and may never since we don't get to see the source code.

Setup is not restarted after bootstrap files loaded

When reboot is needed after bootstrap files are loaded, the installation routine does not continue. Some users may think the program was installed. Instead it should place an entry in the registry to run after reboot.

Unfortunately, since the bootstrap code is in the setup.exe which Microsoft does not give us the source, there is no clean workaround.

Every file installed is logged as new

If you look at the install log (St6unst.log), every file (other than bootstrap) has an action line of:

(File was not found or was an older version -- new file copied)

when this is not always true.

For one, the AddActionNote after the:

Case intFILEUPTODATE
should read:
AddActionNote ResolveResString(resLOG_FILEUPTODATE)
instead of:
AddActionNote ResolveResString(resLOG_FILECOPIED)
Additionally, change the IsNewerVer function in setup1.bas from:
            (.FileVerPart4 = sDestVer.FileVerPart4) Then GoTo INVNewer
to:
(.FileVerPart4 = sDestVer.FileVerPart4) Then IsNewerVer = 2
Then in the CopySection function, instead of checking
if IsNewerVer(sSrcVerInfo, sDestVerInfo) = False then
check for False or 2 and only execute the code up to:
                            If Not fOverWrite Then
only if False.

Non-Versioned new files get version conflict dialog (SP3)

This is a very serious SP3 introduced bug which can result in the wrong file being copied. If the existing file is older, then a version conflict dialog (see below) says the existing file is newer and recommends keeping the existing.

To fix, reverse fcNewer and fcOlder in the SourceFileIsNewer function in setup1.bas as follows:

        If sFile.varDate < datDest Then
            SourceFileIsNewer = fcNewer
        ElseIf sFile.varDate = datDest Then
            SourceFileIsNewer = fcEquivalent
        Else
            SourceFileIsNewer = fcOlder
        End If
with
        If sFile.varDate < datDest Then
            SourceFileIsNewer = fcOlder
        ElseIf sFile.varDate = datDest Then
            SourceFileIsNewer = fcEquivalent
        Else
            SourceFileIsNewer = fcNewer
        End If
Thanks John Reynaert

Non-versioned up-to-date files get version conflict dialog (SP2)

To fix, in setup1 basSetup1 module change the "<=" to "<" in the following line:
If sFile.varDate <= FileDateTime(strDestDir & strDestName) Then

Non-Versioned version conflict message displays useless information (SP2 & SP3)

Non-version version conflict warning message Before a file that has no version overwrites an existing file with the same name, the setup displays a useless message that lists the description and version number that by definition are blank. It should, instead list file date and size of new and old file so the user can make an educated decision.

To add to the confusion is the use of a negative "not newer" instead of "older".

Copy progress screen disappears after overwrite dialog (SP2)

To fix, after each
frm.show vbModal, frmSetup1
insert:
frmCopy.ZOrder

Overwrite warning does not allow cancel (SP2 & SP3)

When following the above disappearing screen issue, you can never halt installation. Otherwise, this could be considered a human interface flaw.

Version overwrite warning not clear (SP2 & SP3)

Version overwrite warning message When installing over a newer version, the warning states "Your version: x.x.xxx.xx" which is unclear to the user. It turns out "your" means the new file which is contrary to what most people think when installing. It is more confusing when it asks "Do you want to keep this file?" It should phrase it as "New version:" and "Do you want to keep the existing file?". In addition, it does not list the version number of the existing file for a better educated decision. Also, it should have a cancel button to allow you to exit the install.

Change lines 1001, 1004, and 1005 in Setup1.res resource file.

Access violation copying msvcrt.dll (and other dlls) (SP2 & SP3*)

If an old file is in use when installation is attempting to install a new version, the setup routine can get an access violation or other sharing error. SP3 reduces the likelyhood of this access violation by not reinstalling the dll if it is the same version.

Microsoft's position is that operating system files should not be updated by your installation routine. However, the tools Microsoft supplies to developers do not identify what files are operating system files. And the P&DW is placing these files in the installation in the first place. In addition, how is a developer to know if the newer file is needed to fix a bug? And finally, Microsoft does the same thing with their applications, so how can they expect us not follow suit? An install routine that access violates is unacceptable!

The real fix is to make an entry in the wininit.ini file (win9x) or use MOVEFILE_DELAY_UNTIL_REBOOT (NT) as follows (SP2 only!):

In Setup1.bas add the following to the declarations section:

Global gReBoot As Boolean
Declare Function GetPrivateProfileSection Lib "kernel32" Alias "GetPrivateProfileSectionA" (ByVal lpAppName As String, ByVal lpReturnedString As String, ByVal nSize As Long, ByVal lpFilename As String) As Long
Declare Function WritePrivateProfileSection Lib "kernel32" Alias "WritePrivateProfileSectionA" (ByVal lpAppName As String, ByVal lpString As String, ByVal lpFilename As String) As Long
Declare Function MoveFileEx Lib "Kernel32" Alias "MoveFileExA" (ByVal OldFilename As String, ByVal NewFileName As String, ByVal nWord As Long) As Long
In ExitSetup procedure add the reboot flag:
        If GetKeyValue(HK_LOCAL_MACHINE, sKEY, sValue, sRet) Or gReBoot Then
Replace the CopyFile function with the following:
Function CopyFile(ByVal strSrcDir As String, ByVal strDestDir As String, ByVal strSrcName As String, ByVal strDestName As String, ByVal fShared As Boolean, ByVal fSystem As Boolean, Optional ByVal fOverWrite As Boolean = False) As Boolean
    Const intUNKNOWN% = 0
    Const intCOPIED% = 1
    Const intNOCOPY% = 2
    Const intFILEUPTODATE% = 3
    Const intDELAYED = 4
    Const MOVEFILE_DELAY_UNTIL_REBOOT = &H4
    Const MOVEFILE_REPLACE_EXISTING = &H1
    Const MOVEFILE_DELAY_AND_REPLACE = MOVEFILE_DELAY_UNTIL_REBOOT + MOVEFILE_REPLACE_EXISTING

    '
    'VerInstallFile() Flags
    '
    Const VIFF_FORCEINSTALL% = &H1
    Const VIF_TEMPFILE& = &H1
    Const VIF_SRCOLD& = &H4
    Const VIF_DIFFLANG& = &H8
    Const VIF_DIFFCODEPG& = &H10
    Const VIF_DIFFTYPE& = &H20
    Const VIF_WRITEPROT& = &H40
    Const VIF_FILEINUSE& = &H80
    Const VIF_OUTOFSPACE& = &H100
    Const VIF_ACCESSVIOLATION& = &H200
    Const VIF_SHARINGVIOLATION = &H400
    Const VIF_CANNOTCREATE = &H800
    Const VIF_CANNOTDELETE = &H1000
    Const VIF_CANNOTRENAME = &H2000
    Const VIF_OUTOFMEMORY = &H8000&
    Const VIF_CANNOTREADSRC = &H10000
    Const VIF_CANNOTREADDST = &H20000
    Const VIF_BUFFTOOSMALL = &H40000

    Static fIgnoreWarn As Integer             'user warned about ignoring error?

    Dim strMsg As String
    Dim lRC As Long
    Dim lpTmpNameLen As Long
    Dim intFlags As Integer
    Dim intRESULT As Integer
    Dim fFileAlreadyExisted

    On Error Resume Next

    CopyFile = False

    '
    'Ensure that the source file is available for copying
    '
    If DetectFile(strSrcDir & strSrcName) = vbIgnore Then
        AbortAction
        Exit Function
    End If
    
    '
    ' Make sure that the Destination path (including path, filename, commandline args, etc.
    ' is not longer than the max allowed.
    '
    If Not fCheckFNLength(strDestDir & strDestName) Then
        AbortAction
        strMsg = ResolveResString(resCANTCOPYPATHTOOLONG) & vbLf & vbLf & ResolveResString(resCHOOSENEWDEST) & vbLf & vbLf & strDestDir & strDestName
        Call MsgError(strMsg, vbOKOnly, gstrSETMSG)
        ExitSetup frmCopy, gintRET_FATAL
        Exit Function
    End If
    '
    'Make the destination directory, prompt the user to retry if there is an error
    '
    If Not MakePath(strDestDir) Then
        AbortAction ' Abort file copy
        Exit Function
    End If

    '
    'Make sure we have the LFN (long filename) of the destination directory
    '
    strDestDir = GetLongPathName(strDestDir)
    
    '
    'Setup for VerInstallFile call
    '
    lpTmpNameLen = gintMAX_SIZE
    mstrVerTmpName = String$(lpTmpNameLen, 0)
    intFlags = 0
    If fOverWrite Then intFlags = VIFF_FORCEINSTALL
    fFileAlreadyExisted = FileExists(strDestDir & strDestName)

    intRESULT = intUNKNOWN

    Do While intRESULT = intUNKNOWN
        'VerInstallFile under Windows 95 does not handle
        '  long filenames, so we must give it the short versions
        '  (32-bit only).
        Dim strShortSrcName As String
        Dim strShortDestName As String
        Dim strShortSrcDir As String
        Dim strShortDestDir As String
        
        strShortSrcName = strSrcName
        strShortSrcDir = strSrcDir
        strShortDestName = strDestName
        strShortDestDir = strDestDir
        If Not FileExists(strDestDir & strDestName) Then
            'If the destination file does not already
            '  exist, we create a dummy with the correct
            '  (long) filename so that we can get its
            '  short filename for VerInstallFile.
            Open strDestDir & strDestName For Output Access Write As #1
            Close #1
        End If
    
        On Error GoTo UnexpectedErr
        If Not IsWindowsNT() Then
            Dim strTemp As String
            'This conversion is not necessary under Windows NT
            strShortSrcDir = GetShortPathName(strSrcDir)
            If GetFileName(strSrcName) = strSrcName Then
                strShortSrcName = GetFileName(GetShortPathName(strSrcDir & strSrcName))
            Else
                strTemp = GetShortPathName(strSrcDir & strSrcName)
                strShortSrcName = Mid$(strTemp, Len(strShortSrcDir) + 1)
            End If
            strShortDestDir = GetShortPathName(strDestDir)
            strShortDestName = GetFileName(GetShortPathName(strDestDir & strDestName))
        End If
        On Error Resume Next
            
        lRC = VerInstallFile(intFlags, strShortSrcName, strShortDestName, strShortSrcDir, strShortDestDir, 0&, mstrVerTmpName, lpTmpNameLen)
        If Err <> 0 Then
            '
            'If the version or file expansion DLLs couldn't be found, then abort setup
            '
            ExitSetup frmCopy, gintRET_FATAL
        End If

        If lRC = 0 Then
            '
            'File was successfully installed, increment reference count if needed
            '
            
            'One more kludge for long filenames: VerInstallFile may have renamed
            'the file to its short version if it went through with the copy.
            'Therefore we simply rename it back to what it should be.
            Name strDestDir & strShortDestName As strDestDir & strDestName
            intRESULT = intCOPIED
        ElseIf lRC And VIF_SRCOLD Then
            '
            'Source file was older, so not copied, the existing version of the file
            'will be used.  Increment reference count if needed
            '
            intRESULT = intFILEUPTODATE
        ElseIf lRC And (VIF_DIFFLANG Or VIF_DIFFCODEPG Or VIF_DIFFTYPE) Then
            '
            'We retry and force installation for these cases.  You can modify the code
            'here to prompt the user about what to do.
            '
            intFlags = VIFF_FORCEINSTALL
        ElseIf lRC And VIF_WRITEPROT Then
            strMsg = ResolveResString(resWRITEPROT)
            GoSub CFMsg
        ElseIf lRC And VIF_FILEINUSE Then
            strMsg = ResolveResString(resINUSE)
            GoSub MvFileDelay
        ElseIf lRC And VIF_OUTOFSPACE Then
            strMsg = ResolveResString(resOUTOFSPACE) & Left$(strDestDir, 2)
            GoSub CFMsg
        ElseIf lRC And VIF_ACCESSVIOLATION Then
            strMsg = ResolveResString(resACCESSVIOLATION)
            GoSub MvFileDelay
        ElseIf lRC And VIF_SHARINGVIOLATION Then
            strMsg = ResolveResString(resSHARINGVIOLATION)
            GoSub MvFileDelay
        ElseIf lRC And VIF_OUTOFMEMORY Then
            strMsg = ResolveResString(resOUTOFMEMORY)
            GoSub CFMsg
        Else
            '
            ' For these cases, we generically report the error and do not install the file
            ' unless this is an SMS install; in which case we abort.
            '
            If lRC And VIF_CANNOTCREATE Then
                strMsg = ResolveResString(resCANNOTCREATE)
            ElseIf lRC And VIF_CANNOTDELETE Then
                strMsg = ResolveResString(resCANNOTDELETE)
            ElseIf lRC And VIF_CANNOTRENAME Then
                strMsg = ResolveResString(resCANNOTRENAME)
            ElseIf lRC And VIF_CANNOTREADSRC Then
                strMsg = ResolveResString(resCANNOTREADSRC)
            ElseIf lRC And VIF_CANNOTREADDST Then
                strMsg = ResolveResString(resCANNOTREADDST)
            ElseIf lRC And VIF_BUFFTOOSMALL Then
                strMsg = ResolveResString(resBUFFTOOSMALL)
            End If

            strMsg = strMsg & ResolveResString(resNOINSTALL)
            MsgError strMsg, vbOKOnly Or vbExclamation, gstrTitle
            If gfSMS Then
                ExitSetup frmSetup1, gintRET_FATAL
            End If
            intRESULT = intNOCOPY
        End If
    Loop

    '
    'If there was a temp file left over from VerInstallFile, remove it
    '
    If lRC And VIF_TEMPFILE Then
        Kill mstrVerTmpName
    End If

    'Abort or commit the current Action, and do reference counting
    Select Case intRESULT
        Case intNOCOPY
            AbortAction
        Case intCOPIED
            DecideIncrementRefCount strDestDir & strDestName, fShared, fSystem, fFileAlreadyExisted
            If (Extension(strDestName) = gsEXT_FONTFON) Or (Extension(strDestName) = gsEXT_FONTTTF) Then
                'do nothing
            Else
                AddActionNote ResolveResString(resLOG_FILECOPIED)
                CommitAction
            End If
            CopyFile = True
        Case intDELAYED
            DecideIncrementRefCount strDestDir & strDestName, fShared, fSystem, fFileAlreadyExisted
            If (Extension(strDestName) = gsEXT_FONTFON) Or (Extension(strDestName) = gsEXT_FONTTTF) Then
                'do nothing
            Else
                AddActionNote "File installation delayed after reboot."
                CommitAction
            End If
            CopyFile = True
        Case intFILEUPTODATE
            DecideIncrementRefCount strDestDir & strDestName, fShared, fSystem, fFileAlreadyExisted
            If (Extension(strDestName) = gsEXT_FONTFON) Or (Extension(strDestName) = gsEXT_FONTTTF) Then
                'do nothing
            Else
                'AddActionNote ResolveResString(resLOG_FILECOPIED)
                AddActionNote ResolveResString(resLOG_FILEUPTODATE)
                CommitAction
            End If
            CopyFile = True
        Case Else
            AbortAction ' Defensive - this shouldn't be reached
        'End Case
    End Select

    Exit Function

UnexpectedErr:
    MsgError error$ & vbLf & vbLf & ResolveResString(resUNEXPECTED), vbOKOnly Or vbExclamation, gstrTitle
    ExitSetup frmCopy, gintRET_FATAL
    
MvFileDelay:
    Dim strProfileSection As String
    Dim lngLength As Long
    Dim lngSize As Long
    Dim strFile As String
    Static lngUnique As Long
    
    If lngUnique = 0 Then
        lngUnique = Format$(Now(), "ddhhnnss")
    Else
        lngUnique = lngUnique + 1
    End If
    strFile = Format$(lngUnique, "00000000") & ".tmp"
    intFlags = 0
    On Error GoTo 0
    On Error Resume Next
    lRC = VerInstallFile(intFlags, strShortSrcName, strFile, strShortSrcDir, strShortDestDir, 0&, mstrVerTmpName, lpTmpNameLen)
    If Err = 0 And lRC = 0 Then
        If IsWindowsNT() Then
            If MoveFileEx(strDestDir & strFile, strDestDir & strDestName, MOVEFILE_DELAY_AND_REPLACE) <> 0 Then
                intRESULT = intDELAYED
                gReBoot = True
            Else
                GoSub CFMsg
            End If
        Else
            strProfileSection = String$(32767, 0)
            lngLength = GetPrivateProfileSection("Rename" & vbNullChar, strProfileSection, 32767, "WinInit.ini" & vbNullChar)
            If lngLength <> 32765 Then
                If WritePrivateProfileSection("Rename" & vbNullChar, _
                    Left(strProfileSection, lngLength) & strShortDestDir & strDestName & "=" & strShortDestDir & strFile & vbNullChar, _
                    "WinInit.ini" & vbNullChar) = 0 Then
                    GoSub CFMsg
                Else
                    intRESULT = intDELAYED
                    gReBoot = True
                End If
            Else
                GoSub CFMsg
            End If
        End If
    Else
        GoSub CFMsg
    End If
    Return

CFMsg: '(Subroutine)
    Dim intMsgRet As Integer
    strMsg = strDestDir & strDestName & vbLf & vbLf & strMsg
    intMsgRet = MsgError(strMsg, vbAbortRetryIgnore Or vbExclamation Or vbDefaultButton2, gstrTitle)
    If gfNoUserInput Then intMsgRet = vbAbort
    Select Case intMsgRet
        Case vbAbort
            ExitSetup frmCopy, gintRET_ABORT
        Case vbIgnore
            If fIgnoreWarn = True Then
                intRESULT = intNOCOPY
            Else
                fIgnoreWarn = True
                strMsg = strMsg & vbLf & vbLf & ResolveResString(resWARNIGNORE)
                If MsgError(strMsg, vbYesNo Or vbQuestion Or vbDefaultButton2, gstrTitle) = vbYes Then
                    intRESULT = intNOCOPY
                Else
                    'Will retry
                End If
            End If
        'End Case
    End Select

    Return
End Function
Caveats
NT code thanks to Brian J. McMahon & Tim Watson.

Files copied from version conflict warning most likely get today's date (SP2 & SP3)

After not answering the version conflict dialog quickly, the file copied is stamped with today's date instead of the original file date (see next issue).

Some files copied get today's date (SP2 & SP3)

In addition to the version conflict file date issue above, some files get stamped with today's date without getting this dialog. It never seems to be the same file in error. This can happen because the check to see if the file was copied is flawed. If the file copy crosses a minute boundary, it does not properly fix the date. In the CopySection procedure add the following to the top:
    Dim StartDate As Date
       
    StartDate = Now
Before service pack 3:
After the CSContinue label replace the lines starting with the Dim through the line with the If statement with the following:
        Dim sFileDate As Date
        
        sFileDate = FileDateTime(sFile.strDestDir & sFile.strDestName)
        
        If DateDiff("s", StartDate, sFileDate) > 0 Then
Service pack 3:
Change the following lines after the CSContinue label:
        sFileDate = Format$(FileDateTime(sFile.strDestDir & sFile.strDestName), "m/d/yyyy h:m")
        sCurDate = Format$(Now, "m/d/yyyy h:m")

        If sFileDate = sCurDate Then
with these:
        Dim sFileDate2 As Date

        sFileDate2 = FileDateTime(sFile.strDestDir & sFile.strDestName)
        
        If DateDiff("s", StartDate, sFileDate2) > 0 Then

Disk n not found

If setup is interrupted, subsequent attempts result in a "disk n not found". For a workaround remove the following files and reattempt the setup:
\WINDOWS\SYSTEM\VB6STKIT.DLL
\WINDOWS\SYSTEM\MSVBVM60.DLL
\WINDOWS\ST6UNST.EXE
\WINDOWS\SETUP.EXE
\WINDOWS\SETUP.LST
\WINDOWS\SETUP1.EXE
\WINDOWS\*.CAB
Remove the following files *ONLY* if they are zero bytes in length:
\WINDOWS\SYSTEM\SCRRUN.DLL (might not be found on all machines)
\WINDOWS\SYSTEM\OLEAUT32.DLL
The major cause for this error is that the cab files are not always removed after an aborted installation. This is because the code assumes the cabs are extracted in numerical order which in most cases is not true.

To prevent the major cause add:

    Form_Unload 0
    KillTempFolder
before the following line in frmSetup1:
    CopySection gstrINI_FILES
Then change the frmSetup1 unload event as follows (and same code in basSetup1.MoveAppRemovalFiles):
Public Sub Form_Unload(Cancel As Integer)
    'Get rid of the cab file in the windows dir (if it exists).
    Dim lCount As Long
    Dim sCab As String
    Dim sTemp As String
    
    'Get rid of the cab file in the windows dir (if it exists).
    If gintCabs = 1 Then
        sCab = gstrWinDir
        AddDirSep sCab
        sCab = sCab & BaseName(GetShortPathName(gsCABNAME))
        If FileExists(sCab) Then
             SetAttr sCab, vbNormal
	     Kill sCab
        endif
    Else
        For lCount = 1 To gintCabs
            sCab = gstrWinDir
            AddDirSep sCab
            sTemp = Left(gsCABNAME, Len(gsCABNAME) - 5) & CStr(lCount) & gstrSEP_EXT & gsINI_CABNAME
            sCab = sCab & BaseName(sTemp)
            If FileExists(sCab) Then
               SetAttr sCab, vbNormal
               Kill sCab
            End If
        Next lCount
    End If
End Sub
Then in basSetup1, change KillTempFolder from Private to Public.

Files copied to Windows folder always share (SP2 & SP3)

When a file (i.e. test.bat) is installed in the Windows folder, it is installed share.

As a workaround, remove the shared designation in the setup.lst file.

Unable to select multiple files to add (SP2 & SP3*)

This feature which was part of the previous versions of VB is no longer available. If you want to add several Crystal Reports to your installation, for example, you have to select one at a time through the open file dialog. It is slowed further by defaulting to exe suffix. (the former is fixed in sp3, the latter is not)

Setup.lst does not always create correct version #

I added a dll that updated 1.0.2.0 version to a 1.0.3.0 version but the entry in setup.lst listed 1.0.0.0 even though the size and date were correct. Interestingly, the correct file was added to the cab file. As a workaround, modify the setup.lst by hand.

Install uses setup.lst data instead of file attributes

Setup.lst is used when comparing dates, sizes and versions of install files, instead of the actual files that are shipped in the cab files. This leads to misleading warning messages when the previous error happens. Also, if changing a file in the support folder without updating the setup.lst file (not documented), also causes this invalid warning.

Packaging report errantly indicates mdac inclusion (10 March 1999)

If you uncheck including mdac_typ.exe you get a "You have included mdac_typ.exe in your installation package." message in the final packaging report.

Rule of thumb is not to believe anything the P&D Wizard tells you; double check it!

Creating dependencies/setup is confusing and error prone

The method of creating a setup routine versus a dependency file has been "improved". However, since the documentation is not clear, it is very easy to blow away one or the other.

PDCMDLN invalid page fault (SP2 & SP3)

The "Package project Files Found" section of the .PDM file can get corrupt and cause the P&D Wizard to crash. As a workaround, delete the entries under this section and re-run the wizard.

Useless warning (SP2 & SP3*)

When you recompile your project with automatic version number checked, you need to save the project. Thus the vbp file will get updated. The P&D wizard displays a useless warning message asking if you want to recompile because your exe is older than your vbp.

SP3 partially resolves this by also indicating the other files that have changed.

In place upgrades not handled (SP2 & SP3)

Actually, this has never worked in any version of VB. If you install over an existing application, the uninstall does not clean up properly. It should append to the existing log file to handle in place upgrades. SP2 and SP3 handle it differently.

SP2 had a bug where it included only one entry in Add/Remove wizard if the application name had a lower case letter in it. As a result, uninstall would not decrement multiple shares, not all files would be removed and/or missing file errors were displayed.

SP3 creates multilple uninstall entries which when removed at least decrement share counts. However, users may be confused and accidently remove the application. Also, missing file errors were displayed, though at least all files are removed if the user removes each. Adding to the confusion is the names listed in the Add/Remove wizard. The second entry appends the folder, the third through n appends the folder followed by #3 to #n respectfully.

Uninstall does not decrement share count for bootstrap files (SP3)

For example, if yours is the last VB6 application to be removed, the MSVBVM60.DLL will not be removed. As a workaround, you could change setup1 to copy the bootstrap log entries with SystemFile action and change them to SharedFile action. For example copy:
ACTION: SystemFile: "C:\WINDOWS\SYSTEM\VB6STKIT.DLL"
(File currently on disk was already up to date)
after
NOTE: Now spawning the main Setup program...
and replace SystemFile with SharedFile
ACTION: SharedFile: "C:\WINDOWS\SYSTEM\VB6STKIT.DLL"
(File currently on disk was already up to date)
This could be dangerous, however, if and when Microsoft decides to fix the uninstaller. Hopefully it would be fixed with a point release (i.e. st7unst.exe) or they would change the setup1 as suggested above.

Path/file access error at end of installation (23 March 1999)

Some systems complain when attempting to delete files that are read only. Since the cab files are readonly, when attempting to remove these files at the end of setup, this error happens. See Disk n not found where:
             SetAttr sCab, vbNormal
is added.

Non-US product shipped with wrong VB6 setup project

Many Non-US customers report that the setup1.vbp version is much older than setup1.exe (6.00.8083 v.s. 6.00.8171). Attempting to compile this older version results in failures. Contact Microsoft in order to get correct version.

Unable to register EXPSRV.DLL (SP2*)

The PDW thinks version 6.0.8268 of expsrv.dll needs to be registered. This version comes from IE5 or possibly other products.

I suspect it is needed for the new vbajet32.dll. How to address this issue depends on what you ship. From what I can tell, if you also ship 6.0.8268 version of vbajet32.dll, make sure expsrv.dll is listed after vbajet32.dll in the setup.lst. People tell me moving it to the end works.

If you ship the previous version of vbajet32.dll you can either remove $(DLLSelfRegister) from the setup.lst file or place the previous version of expsrv.dll in your "Program Files\Microsoft Visual Studio\VB98\Wizards\PDWizard\Redist" folder and rerun P&D Wizard.

SP3 ships 6.0.8269 which the P&DW does not attempt to register. Be careful, however, Windows 98 Second Edition reinstalls 6.0.8268.

Bootstrap install fails if reboot needed (SP3)

On some machines the setup.exe attempts to copy all the files instead of just the bootstrap files. Then after it asks you if you want to reboot, it gets an error saying it cannot read source file RBTnnnn.tmp file. This error only seems to happen if installing bootstrap files requires a reboot.

As a workaround, do not use the setup.exe that comes with SP3.

No uninstall for mdac_typ (SP2 & SP3)

If mdac_typ is included in the setup, there is no method of un-installing it. This, of course, violates Windows Logo requirements.

DAO

DAO 3.6 find does not support 'field = Null'

The previous versions of DAO would support the following just fine:
MyRecordset.findfirst "myfield = Null"
DAO 3.6 will never find nulls this way. As a workaround change the above to:
MyRecordset.findfirst "myfield is Null"

Optimistic locking fails using MS Access 2.0 and DAO 3.x

When optimistic locking is set, pessimistic locking is used instead, resulting in lockouts in multi-user situations. There is no workaround unless you have the luxury of upgrading to newer versions of MS Access. (sample of bug to be posted)

Time precision error using MS Access 2.0 and DAO 3.x

Date fields containing time values do not always equate between DAO 3.x and 2.x generated values. For example, a select statement on a date field containing "10:00 AM" in DAO 2.x may result in record not found in DAO 3.x:
(SELECT * FROM table WHERE DateField = #10:00 AM#)
As a workaround for homogeneous environments, execute the following SQL statement:
UPDATE table Set DateField = CVDate(Format(DateField, 'hh:nn:ss ampm'))
Heterogeneous environments are out of luck. In other words, the above workaround only works if you are upgrading or downgrading to one or the other version. For example, dates with times created in Access 2.0 may not be found in Access 97 and visa versa.

Locks not freed after error using MS Access 2.0 and DAO 3.x

If an error occurs, locks do not get removed. Ramification can be great since the Jet engine may escalate to a higher level lock and thus lockout something as simple as a read.

As a workaround use the freelocks statement after errors.

Clone does not inherit lockedits property

No matter what it is set at, it is changed to pessimistic locking. As a workaround set lockedits to parent recordset value.

CreateQueryDef fails with some parameterized queries using MS Access 2.0 and DAO 3.x

CreateQueryDef of a parameterized query with a field that contains a space fails. For example:
MyDB.CreateQueryDef "MyQuery", "PARAMETERS [T No] Long; SELECT * FROM MyTable where MyField = [T No]"
fails because it can't handle the [T No] field. As a workaround, remove the space from your database field or upgrade to Access 97.

Clone does not inherit indexes using MS Access 2.0 and DAO 3.x

The Microsoft bug list implies this only affects tabledefs which as a workaround you reassign the index after creating the clone. However, this also affects recordsets which do not have the index property and thus the workaround is not possible. Performance, thus can be dramatically degraded and thus defeating the purpose of the clone.
David L. Beckwith
vbbugs@TeeItUp.com