Visual Basic Internet Routines
GetPrivateProfileString: Parse IE Favourites Information
Posted:   Wednesday June 17, 1998
Updated:   Monday December 26, 2011
Applies to:   VB4-32, VB5, VB6
Developed with:   VB6, Windows 98
OS restrictions:   None
Author:   VBnet - Randy Birch
Internet shortcuts for IE (not Netscape).

Using the FindFirstFile/FindNextFile APIs, in conjunction with the shell's SHGetFolderPath API and the workhorse GetPrivateProfileString it is easy to construct a recursive directory search that will return all internet favourites in the user's Favourites folder, along with the URL that each points to.

An IE favourite is stored in a format identical to standard INI files:


The two bolded lines are the target of this routine. The other entries point to the constituent members of a frameset, and supplementary data such as the last modified date and the icon to display in the Favourites menu. (Add VBnet as a favourite and open a new browser window - the MVP logo will appear beside VBnet's shortcut.)

The first step is to retrieve the path to the user's shortcut folder. As a special folder under Windows, the CSIDL_COMMON_FAVORITES constant will return this path when passed to SHGetFolderPath. With this information, we set up a standard recursive folder search calling GetPrivateProfileString for each file ending in .url, extracting the URL= entry under [InternetShortcut], populating the ListView with the information.

 BAS Module Code
Place the following code into the general declarations area of a bas module:

 Form Code
Drop a command button and a ListView control onto a form and add the following code:

Option Explicit
' Copyright 1996-2011 VBnet/Randy Birch, All Rights Reserved.
' Some pages may also contain other copyrights by the author.
' Distribution: You can freely use this code in your own
'               applications, but you may not reproduce 
'               or publish this code on any web site,
'               online service, or distribute as source 
'               on any media without express permission.
Private Const MAX_PATH As Long = 260
Private Const INVALID_HANDLE_VALUE As Long = -1
Private Const SHGFP_TYPE_CURRENT As Long = &H0
Private Const SHGFP_TYPE_DEFAULT As Long = &H1
Private Const CSIDL_FAVORITES As Long = &H6
Private Const MAX_LENGTH As Long = 260
Private Const S_OK As Long = 0
Private Const S_FALSE As Long = 1

Private Type FILETIME
   dwLowDateTime As Long
   dwHighDateTime As Long
End Type

Private Type WIN32_FIND_DATA
   dwFileAttributes As Long
   ftCreationTime As FILETIME
   ftLastAccessTime As FILETIME
   ftLastWriteTime As FILETIME
   nFileSizeHigh As Long
   nFileSizeLow As Long
   dwReserved0 As Long
   dwReserved1 As Long
   cFileName As String * MAX_PATH
   cAlternate As String * 14
End Type

'this is my type for passing and
'retrieving file search information
Private Type FILE_PARAMS
   bRecurse As Boolean
   bList As Boolean
   bFound As Boolean
   sFileRoot As String
   sFileNameExt As String
   sResult As String
   nFileCount As Long
   nFileSize As Double
End Type

Private Declare Function GetPrivateProfileString _
   Lib "kernel32" Alias "GetPrivateProfileStringA" _
  (ByVal lpSectionName As String, _
   ByVal lpKeyName As Any, _
   ByVal lpDefault As String, _
   ByVal lpReturnedString As String, _
   ByVal nSize As Long, _
   ByVal lpFileName As String) As Long
Private Declare Function SHGetFolderPath Lib "shfolder.dll" _
    Alias "SHGetFolderPathA" _
   (ByVal hwndOwner As Long, _
     ByVal nFolder As Long, _
     ByVal hToken As Long, _
     ByVal dwReserved As Long, _
     ByVal lpszPath As String) As Long
Private Declare Function FindFirstFile Lib "kernel32" _
   Alias "FindFirstFileA" _
  (ByVal lpFileName As String, _
   lpFindFileData As WIN32_FIND_DATA) As Long
Private Declare Function FindNextFile Lib "kernel32" _
   Alias "FindNextFileA" _
  (ByVal hFindFile As Long, _
   lpFindFileData As WIN32_FIND_DATA) As Long

Private Declare Function FindClose Lib "kernel32" _
  (ByVal hFindFile As Long) As Long
Private Sub Form_Load()

   With ListView1
      .ColumnHeaders.Add 1, , "Link Name"
      .ColumnHeaders(1).Width = (ListView1.Width \ 2) - 200
      .ColumnHeaders.Add 2, , "URL"
      .ColumnHeaders(2).Width = (ListView1.Width \ 2) - 200
      .View = lvwReport
   End With
End Sub

Private Sub ListView1_ColumnClick(ByVal ColumnHeader As MSComctlLib.ColumnHeader)

  'toggle the sort order based on the column clicked
   ListView1.SortKey = ColumnHeader.Index - 1
   ListView1.SortOrder = Abs(ListView1.SortOrder = 0)
   ListView1.Sorted = True
End Sub

Private Function SearchForFiles(FP As FILE_PARAMS) As Double

  'local working variables
   Dim hFile As Long
   Dim nSize As Long
   Dim sPath As String
   Dim sRoot As String
   Dim sTmp As String
   sRoot = QualifyPath(FP.sFileRoot)
   sPath = sRoot & "*.*"
  'obtain handle to the first match
   hFile = FindFirstFile(sPath, WFD)
  'if valid ...
     'This is where the method obtains the file
     'list and data for the folder passed.
      Call GetFileInformation(FP)

        'if the returned item is a folder...
         If (WFD.dwFileAttributes And FILE_ATTRIBUTE_DIRECTORY) Then
           '..and the Recurse flag was specified
            If FP.bRecurse Then
              'remove trailing nulls
               sTmp = TrimNull(WFD.cFileName)
              'and if the folder is not the default
              'self and parent folders...
               If sTmp <> "." And sTmp <> ".." Then
                 '..then the item is a real folder, which
                 'may contain other sub folders, so assign
                 'the new folder name to FP.sFileRoot and
                 'recursively call this function again with
                 'the amended information.
                  FP.sFileRoot = sRoot & sTmp
                  Call SearchForFiles(FP)
               End If
            End If
         End If
     'continue looping until FindNextFile returns
     '0 (no more matches)
      Loop While FindNextFile(hFile, WFD)
     'close the find handle
      hFile = FindClose(hFile)
   End If
End Function

Private Function TrimNull(startstr As String) As String

  'returns the string up to the first
  'null, if present, or the passed string
   Dim pos As Integer
   pos = InStr(startstr, Chr$(0))
   If pos Then
      TrimNull = Left$(startstr, pos - 1)
      Exit Function
   End If
   TrimNull = startstr
End Function

Private Function GetFileInformation(FP As FILE_PARAMS) As Long

  'local working variables
   Dim hFile As Long
   Dim pos As Long
   Dim sPath As String
   Dim sRoot As String
   Dim sTmp As String
   Dim sURL As String
   Dim sShortcut As String
   Dim itmX As ListItem
  'FP.sFileRoot (assigned to sRoot) contains
  'the path to search.
  'FP.sFileNameExt (assigned to sPath) contains
  'the full path and filespec.
   sRoot = QualifyPath(FP.sFileRoot)
   sPath = sRoot & FP.sFileNameExt
  'obtain handle to the first filespec match
   hFile = FindFirstFile(sPath, WFD)
  'if valid ...

        'remove trailing nulls
         sTmp = TrimNull(WFD.cFileName)
        'Even though this routine uses filespecs,
        '*.* is still valid and will cause the search
        'to return folders as well as files, so a
        'check against folders is still required.
         If Not (WFD.dwFileAttributes And FILE_ATTRIBUTE_DIRECTORY) _
           'determine the link name by removing
           'the .url extension
            pos = InStr(sTmp, ".url")
            If pos > 0 Then
               sShortcut = Left$(sTmp, pos - 1)
              'extract the URL
               sURL = ProfileGetItem("InternetShortcut", "URL", "", sRoot & sTmp)
              'add to the listview
               Set itmX = ListView1.ListItems.Add(, , sShortcut)
               itmX.SubItems(1) = sURL
            End If
         End If
      Loop While FindNextFile(hFile, WFD)
     'close the handle
      hFile = FindClose(hFile)
   End If
End Function

Private Function QualifyPath(sPath As String) As String

  'assures that a passed path ends in a slash
   If Right$(sPath, 1) <> "\" Then
      QualifyPath = sPath & "\"
      QualifyPath = sPath
   End If
End Function

Private Sub Command1_Click()

   Dim favPath As String
  'retrieve the special folder path
  'to the internet Favourites
   favPath = GetFolderPath(CSIDL_FAVORITES)
   If Len(favPath) > 0 Then
     'set up the search UDT
      With FP
         .sFileRoot = favPath
         .sFileNameExt = "*.url"
         .bRecurse = True
      End With
     'get the files
      Call SearchForFiles(FP)

   End If
End Sub

Private Function GetFolderPath(CSIDL As Long) As String

   Dim sPath As String
   Dim sTmp As String
  'fill pidl with the specified folder item
   sPath = Space$(MAX_LENGTH)
   If SHGetFolderPath(Me.hWnd, CSIDL, 0&, SHGFP_TYPE_CURRENT, sPath) = S_OK Then
       sTmp = Left$(sPath, InStr(sPath, Chr$(0)) - 1)
   End If
   GetFolderPath = sTmp
End Function

Private Function ProfileGetItem(lpSectionName As String, _
                                lpKeyName As String, _
                                defaultValue As String, _
                                inifile As String) As String

  'Retrieves a value from an ini file corresponding
  'to the section and key name passed.
   Dim success As Long
   Dim nSize As Long
   Dim ret As String
  'call the API with the parameters passed.
  'The return value is the length of the string
  'in ret, including the terminating null. If a
  'default value was passed, and the section or
  'key name are not in the file, that value is
  'returned. If no default value was passed (""),
  'then success will = 0 if not found.

  'Pad a string large enough to hold the data.
   ret = Space$(2048)
   nSize = Len(ret)
   success = GetPrivateProfileString(lpSectionName, lpKeyName, _
                                     defaultValue, ret, nSize, inifile)
   If success Then
      ProfileGetItem = Left$(ret, success)
   End If
End Function


PayPal Link
Make payments with PayPal - it's fast, free and secure!


Copyright 1996-2011 VBnet and Randy Birch. All Rights Reserved.
Terms of Use  |  Your Privacy



Hit Counter