FATTR - Sample file manipulation DLL for Microsoft Access ========================================================= 3/20/94 -- KNG Added Get/SetFileAttr() functions. This is a DLL callable from Microsoft Access that contains the following functions: GetFileSize() - gets the size of a specified file GetFileDateTime() - gets the timestamp of a specified file GetDiskFree() - returns the amount of free disk space on a specifie drive DosFindFirst() - returns the first file matching a specification DosFindNext() - returns the next file from the original DosFindFirst() ConvertDosTime() - converts the date/time information from DOS time to Access time format GetFileAttr() - Retrieve a specific file's DOS attribute (one or more of the ATTR_*, constants listed below, added together SetFileAttr() - Set a specific file's DOS attribute, using the sum of one or more of the ATTR_* constants. This is commonly requested information from Microsoft Access, however they are not currently supplied by Access or the Windows API. To use ------ Copy FATTR.DLL to your Access directory or Windows directory. The file FATTR.MDB contains the following declarations: Global Const ATTR_NORMAL = 0 Global Const ATTR_READONLY = 1 Global Const ATTR_HIDDEN = 2 Global Const ATTR_SYSTEM = 4 Global Const ATTR_LABEL = 8 Global Const ATTR_SUBDIR = 16 Global Const ATTR_ARCHIVE = 32 Type FINDFILE reserved As String * 21 attrib As String * 1 wr_time As Integer wr_date As Integer size As Long name As String * 13 End Type ' Both these functions return the file's attribute after the function call. ' On error, they return -2 if the file wasn't found, or -5 if permission was denied. Declare Function GetFileAttr Lib "FATTR.DLL" Alias "GetFAttr" (ByVal strFileName As String) As Integer Declare Function SetFileAttr Lib "FATTR.DLL" Alias "SetFAttr" (ByVal strFileName As String, ByVal intAttr As Integer) As Integer Declare Function GetDiskFree Lib "FATTR.DLL" (ByVal disk As Integer) As Long Declare Function ConvertDosTime Lib "FATTR.DLL" (ff As FINDFILE) As Double Declare Function DosFindFirst Lib "FATTR.DLL" (ByVal FileName$, ByVal attrib%, ff As FINDFILE) As Integer Declare Function DosFindNext Lib "FATTR.DLL" (ff As FINDFILE) As Integer Declare Function GetFileDateTime Lib "FATTR.DLL" (ByVal FileName$) As Double Declare Function GetFileSize Lib "FATTR.DLL" (ByVal FileName$) As Long Reference to Functions ====================== GetFileAttr() ------------- Syntax GetFileAttr(strFileName) strFileName is the name of a file to examine. Returns an integer representing the file's attribute. -2 if the file wasn't found. -5 if permission was denied. Notes Use the ATTR_* attribute constants when checking and setting file attributes. To see if a file is hidden: intAttr = GetFileAttr("someFileName") isHidden = intAttr AND ATTR_HIDDEN SetFileAttr() ------------- Syntax SetFileAttr(strFileName, intAttrib) strFileName is the name of a file for which to set the attribute. intAttrib is the attribute to set for the file Returns The original file attribute. -2 if the file wasn't found. -5 if permission was denied. Notes To set a file to be hidden: intAttr = GetFileAttr("someFileName") intAttr = intAttr OR ATTR_HIDDEN intAttr = SetFileAttr("someFileName", intAttr) or intAttr = SetFileAttr("someFileName", GetFileAttr("someFileName") OR ATTR_HIDDEN) GetFileSize() ------------- Syntax GetFileSize(sFileName) sFileName is the name of a file to examine. Returns a long integer representing the size of the file. Notes A full path may be necessary. The function only looks for files with normal attributes. Hidden or system files will not be searched for with this function. GetDiskFree() ------------- Syntax GetDiskFree(nDrive) nDrive is a number, where 1=A, 2=B, 3=C, etc. Returns a long integer representing the amount of disk space available on the designated drive. Notes nDrive can also be 0, which means default drive. Huge drives may not be representable with a long integer, since longs are signed under Access. GetFileDateTime() ----------------- Syntax GetFileDateTime(sFileName) sFileName is the name of a file to examine. Returns a double value, which is the internal representation of a date/time under Access. Notes A full path may be necessary. The date/time returned is a double, but can be converted to a readable format with the Format function: Format(GetFileDateTime("MSACCESS.EXE"), "Long Date") DosFindFirst() -------------- Syntax DosFindFirst(sFileSpec, nAttrib, ffStruct) sFileSpec is a valid DOS filespec, possibly including wildcards. nAttrib can be one or more of the following OR'd together: ATTR_NORMAL, ATTR_RDONLY, ATTR_HIDDEN, ATTR_SYSTEM, ATTR_ARCH, ATTR_VOLID, ATTR_SUBDIR. ffStruct is a variable of type FINDFILE. Returns Zero is successful. Notes To OR attributes together, either add them together or use the OR operator. Example: (ATTR_NORMAL OR ATTR_RDONLY OR ATTR_SUBDIR) ffStruct is filled in with the first file that meets the search specification. To retrieve the next file, use DosFindNext(). ffStruct contains the following elements: name - an ASCII 0 terminated filename attrib - a character attribute wr_date/wr_time - the file timestamp size - the file size To convert the wr_date/wr_time format to something readable, you should first call ConvertDosTime(). The attrib element will contain any file attributes OR'd together. To extract a particular attribute, AND it with the attribute you are querying. For example, to determine if a file found is a subdirectory, you can say something like If (Asc(ffStruct.attrib) AND ATTR_SUBDIR) Then MsgBox "It is a subdirectory!" End If Note that Asc() is necessary, because the element is a character. The name element is zero terminated, which means you will need to remove the ASCII 0 from the string. The following code shows how to do that: If InStr(ffStruct.name, Chr(0)) > 0) Then MyVar = Left(ffStruct.name, InStr(ffStruct.name, Chr(0)) - 1) End If DosFindNext() ------------- Syntax DosFindNext(ffStruct) ffStruct is a variable of type FINDFILE. It should have been initialized by calling DosFindFirst() first. Returns Zero is successful. Notes DosFindNext() goes hand-in-hand with DosFindFirst(). A common way to traverse a directory is as follows: Dim status, ffStruct As FINDFILE status = DosFindFirst("*.*", ATTR_NORMAL, ffStruct) While status = 0 Then status = DosFindNext(ffStruct) Wend ConvertDosTime() ---------------- Syntax ConvertDosTime(ffStruct) ffStruct is a variable of type FINDFILE. It should be initialized by DosFindFirst() or DosFindNext(). Returns a double value, which is the internal representation of a date/time under Access. Notes The date/time returned is a double, but can be converted to a readable format with the Format function. The following example, goes through the Access directory and dumps the name and date of every file to the Immediate Window: Dim status, ffStruct As FINDFILE status = DosFindFirst("*.*", ATTR_NORMAL, ffStruct) While status = 0 Then Debug.Print ffStruct.name & Format(ConvertDosTime(ffStruct), "Long Date") status = DosFindNext(ffStruct) Wend Examples ======= The following examples come in the FATTR.MDB. It is a "whereis" program written in Access Basic that uses the FATTR.DLL. To use it, go to the Access Immediate Window and type the following: ? whereis("C:\WINDOWS\", "*.DLL") The program will then dump all files matching the file specification to the Immediate Window. whereis() takes two arguments: the first argument is the directory to start from. It must be a valid directory and MUST have a backslash as the last character. The second argument is the filespec to search for. It can contain the DOS wildcard characters "*" and "?". The above example finds all DLLs in the WINDOWS directory all directories underneath. Function WhereIs (strDirSpec As String, strSpec As String) Dim ff As FINDFILE Dim intStat As Integer Dim varRetval As Variant Dim varTemp As Variant 'look for subdirectories first Debug.Print "Searching " & strDirSpec & strSpec intStat = DosFindFirst(strDirSpec & "*.*", ATTR_SUBDIR, ff) While (intStat = 0) If (Asc(ff.attrib) And ATTR_SUBDIR) And (Left(ff.name, 1) <> ".") Then 'clean ff.name If (InStr(ff.name, Chr(0)) > 0) Then varTemp = Left(ff.name, InStr(ff.name, Chr(0)) - 1) Else varTemp = ff.name End If varRetval = WhereIs(strDirSpec & varTemp & "\", strSpec) End If intStat = DosFindNext(ff) Wend 'look specifically for a file type intStat = DosFindFirst(strDirSpec & strSpec, 0, ff) While (intStat = 0) If (InStr(ff.name, Chr(0)) > 0) Then varTemp = Left(ff.name, InStr(ff.name, Chr(0)) - 1) Else varTemp = ff.name End If Debug.Print varTemp, Format(ConvertDosTime(ff), "long date") intStat = DosFindNext(ff) Wend 'allow other things to happen DoEvents End Function This function uses the Dir() function to list all the files in the C:\ directory, along with their file attributes. Function TestAttrib () ' Print out a list of files in your root ' directory, along with the file attribute of each. Dim strName As String ' Note: Dir() won't find hidden or system files. strName = Dir("C:\") Do While strName <> "" Debug.Print strName, GetFileAttr("C:\" & strName) strName = Dir Loop End Function Programming notes ================= Look at FATTR.C and notice how simple it is to create a DLL that you can use with Microsoft Access! The DLL was built with Microsoft Visual C++ using the Large Memory Model and all default settings and optimizations. Visual C++ will create a default WEP and LibMain(), so these aren't included. Also note that the Large Model is required because much of the runtime library is not model independent! To get the internal Access date format, I used the following formula: ((time_t - 25200) / 86400) + 25569 where time_t is the C time format (number of seconds starting 1/1/70 midnight) 25200 is the number of seconds in 7 hours 86400 is the number of seconds in 1 day 25569 is the Access equivalent of 1/1/70 Legal stuff =========== Please note that this sample is totally unsupported, and the software is PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND and in no event shall MS be liable for any damages whatsoever in connection with your use of the sample. However, I'm willing to answer questions about sample and programming DLLs for Access in general. Please feel free to copy this and use it, sell it, whatever. Roger Harui [MSFT], 71742,1177 Ken Getz 76137,3650