|
|
![]() |
|
||
|
|
|||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||
| Visual Basic Registry Routines RegEnumValue: Enumerate Registered Shared DLLs |
||
| Posted: | Sunday February 23, 2003 | |
| Updated: | Monday December 26, 2011 | |
| Applies to: | VB4-32, VB5, VB6 | |
| Developed with: | VB6, Windows XP | |
| OS restrictions: | None | |
| Author: | VBnet - Randy Birch | |
|
Related: |
RegEnumKeyEx: Retrieve the Registered File Associations | |
| Prerequisites |
| None. |
|
|
The
ShareDLL
file
provided on the VBnet Dev Resources Tools page contains a
Microsoft unsupported tool for displaying - albeit one line at a time -
the amount of data in the SharedDLLs registry key.Shrdll.exe is a command-line tool that helps support professionals and their customers understand the state of the SharedDlls registry key and can be a sys admin's best friend when applications won't install with an 'error writing to the registry' error. Because registry keys in Windows 95 cannot be larger than 64K, it is possible that applications will fail to install if they are writing too much to a registry key this is already practically full. HKEY_LOCAL_MACHINE \ SOFTWARE \ Microsoft \ Windows \ CurrentVersion \ SharedDLLs is the registry key where this is most likely to occur. It also determines which entries in the SharedDLLs key point to files that have been moved or no longer exist and provides for removing those entries to free up registry key space. The Microsoft utility is also useful under any 32-bit Windows version to simply clean the SharedDLLs key of entries left after the uninstall of applications. I've used it since Windows 95 on 95, NT4, 2000 and XP with absolutely no negative impact, however for those interested here is Microsoft's published info, dated May 14, 2001: Depending on the platform, checks are performed at the beginning of Setup to ensure that the registry does not overflow. There are two aspects of the registry that can affect Setup in this regard:
Microsoft Windows 2000
Microsoft Windows NT 4.0
Microsoft Windows 98
Microsoft Windows 95 This page is more a demo of how to use the registry than anything particularly useful, other than showing all Shared DLL files in one view, rather than one at a time. It shows how to enumerate the entries under the SharedDLLs key, how to retrieve the value associated with each entry, as well as how to determine if the file specified actually exists, and by extension, whether that entry could be safely deleted. The code does not delete the superfluous entries. The values shown in the second column represents the DLL usage count. Installation program should keep track of shared DLLs; when installing an application that uses shared DLLs, it should increment the use counter for the DLL in the registry. When removing an application, it should decrement the use counter. If the result is zero, the user should be given the option of deleting the DLL. Interestingly, QuickTime mucks around with the registry - the QTPlugin.ocx entry is not deleted when the QuickTime is uninstalled, and pretty well sets itself such it will never be removed from the SharedDLLs key by setting its usage count at 998! |
| BAS Module Code |
| None. |
|
|
| Form Code |
|
|
| Add a single command button (Command1) and a listview (Listview1) to a form. The code uses the VB6 listview, so VB4/5 users will need to change the library reference ListView1_ColumnClick declare: |
|
|
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 LVM_FIRST As Long = &H1000
Private Const LVM_SETCOLUMNWIDTH As Long = (LVM_FIRST + 30)
Private Const LVSCW_AUTOSIZE As Long = -1
Private Const LVSCW_AUTOSIZE_USEHEADER As Long = -2
Private Const INVALID_HANDLE_VALUE = -1
Private Const HKEY_LOCAL_MACHINE = &H80000002
Private Const REG_DWORD As Long = &H4 '32-bit number
Private Const ERROR_MORE_DATA = 234
Private Const ERROR_SUCCESS As Long = 0
Private Const MAX_PATH As Long = 260
Private Const STANDARD_RIGHTS_READ As Long = &H20000
Private Const KEY_QUERY_VALUE As Long = &H1
Private Const KEY_ENUMERATE_SUB_KEYS As Long = &H8
Private Const KEY_NOTIFY As Long = &H10
Private Const SYNCHRONIZE As Long = &H100000
Private Const KEY_READ As Long = ((STANDARD_RIGHTS_READ Or _
KEY_QUERY_VALUE Or _
KEY_ENUMERATE_SUB_KEYS Or _
KEY_NOTIFY) And _
(Not SYNCHRONIZE))
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
Private Declare Function FindFirstFile Lib "kernel32" _
Alias "FindFirstFileA" _
(ByVal lpFileName As String, _
lpFindFileData As WIN32_FIND_DATA) As Long
Private Declare Function FindClose Lib "kernel32" _
(ByVal hFindFile As Long) As Long
Private Declare Function RegOpenKeyEx Lib "advapi32.dll" _
Alias "RegOpenKeyExA" _
(ByVal hKey As Long, _
ByVal lpSubKey As String, _
ByVal ulOptions As Long, _
ByVal samDesired As Long, _
phkResult As Long) As Long
Private Declare Function RegEnumValue Lib "advapi32.dll" _
Alias "RegEnumValueA" _
(ByVal hKey As Long, _
ByVal dwIndex As Long, _
ByVal lpValueName As String, _
lpcbValueName As Long, _
ByVal lpReserved As Long, _
lpType As Long, _
lpData As Any, _
lpcbData As Long) As Long
Private Declare Function RegQueryValueEx Lib "advapi32.dll" _
Alias "RegQueryValueExA" _
(ByVal hKey As Long, _
ByVal lpValueName As String, _
ByVal lpReserved As Long, _
lpType As Long, _
lpData As Any, _
lpcbData As Long) As Long
Private Declare Function RegCloseKey Lib "advapi32.dll" _
(ByVal hKey As Long) As Long
Private Declare Function lstrlenW Lib "kernel32" _
(ByVal lpString As Long) As Long
Private Declare Function SendMessage Lib "user32" _
Alias "SendMessageA" _
(ByVal hwnd As Long, _
ByVal wMsg As Long, _
ByVal wParam As Long, _
lParam As Any) As Long
Private Sub Form_Load()
With ListView1
.ColumnHeaders.Add , , "Shared DLL Files"
.ColumnHeaders.Add , , "Usage"
.ColumnHeaders.Add , , "File Exists"
.View = lvwReport
.FullRowSelect = True
.AllowColumnReorder = True
.LabelEdit = lvwManual
End With
Command1.Caption = "Shared DLL Info"
End Sub
Private Sub Command1_Click()
Dim hKey As Long
Dim sKey As String
Dim dwIndex As Long
Dim sValueName As String * MAX_PATH
Dim dwKeyType As Long
Dim sData As String * MAX_PATH
Dim dwValueNameSize As Long
Dim dwDataSize As Long
Dim dwDataUsage As Long
Dim itmx As ListItem
'obtain a handle to the key
sKey = "SOFTWARE\Microsoft\Windows\CurrentVersion\SharedDLLs"
hKey = OpenRegKey(HKEY_LOCAL_MACHINE, sKey)
'if valid
If hKey <> 0 Then
'initialize enum values
dwIndex = 0
dwValueNameSize = MAX_PATH
dwDataSize = MAX_PATH
'reduce flicker while updating
ListView1.Visible = False
'enumerate all keys under \SharedDLLs
Do While RegEnumValue(hKey, _
dwIndex, _
sValueName, _
dwValueNameSize, _
0, _
dwKeyType, _
ByVal sData, _
dwDataSize) = ERROR_SUCCESS
'retrieve the dword value
'representing the usage
'of a particular file
Call RegQueryValueEx(hKey, _
sValueName, _
0&, _
REG_DWORD, _
dwDataUsage, _
4)
'add data to the listview
Set itmx = ListView1.ListItems.Add(, , TrimNull(sValueName))
itmx.SubItems(1) = dwDataUsage
itmx.SubItems(2) = FileExists(sValueName)
'reset variables for next call
dwValueNameSize = MAX_PATH
dwDataSize = MAX_PATH
dwIndex = dwIndex + 1
Loop
Call RegCloseKey(hKey)
Call lvAutosizeControl(ListView1)
ListView1.ColumnHeaders(1).Text = "Shared DLL Files (" & _
ListView1.ListItems.Count & " entries)"
ListView1.Visible = True
End If
End Sub
Private Sub ListView1_ColumnClick(ByVal ColumnHeader As MSComctlLib.ColumnHeader)
ListView1.SortKey = ColumnHeader.Index - 1
ListView1.SortOrder = Abs(Not ListView1.SortOrder = 1)
ListView1.Sorted = True
End Sub
Private Function OpenRegKey(ByVal hKey As Long, _
ByVal lpSubKey As String) As Long
Dim hSubKey As Long
If RegOpenKeyEx(hKey, _
lpSubKey, _
0, _
KEY_READ, _
hSubKey) = ERROR_SUCCESS Then
OpenRegKey = hSubKey
End If
End Function
Private Function TrimNull(startstr As String) As String
TrimNull = Left$(startstr, lstrlenW(StrPtr(startstr)))
End Function
Private Function FileExists(sSource As String) As Boolean
Dim WFD As WIN32_FIND_DATA
Dim hFile As Long
hFile = FindFirstFile(sSource, WFD)
FileExists = hFile <> INVALID_HANDLE_VALUE
Call FindClose(hFile)
End Function
Private Sub lvAutosizeControl(lv As ListView)
'Size each column based on the maximum of
'EITHER the ColumnHeader text width, or,
'if the items below it are wider, the
'widest list item in the column
Dim col2adjust As Long
For col2adjust = 0 To lv.ColumnHeaders.Count - 1
Call SendMessage(lv.hwnd, _
LVM_SETCOLUMNWIDTH, _
col2adjust, _
ByVal LVSCW_AUTOSIZE_USEHEADER)
Next
End Sub |
| Comments |
|
|
|
|
|
|||||
|
|||||
|
|
|||||
|
Copyright ©1996-2011 VBnet and Randy Birch. All Rights Reserved. |
![]() |