枚举所有未被使用的 SharedDlls

来源:互联网 发布:ubuntu里的dash 编辑:程序博客网 时间:2024/05/21 23:32
首先,查找这些文件是否可用的原理在于注册表。注册表中的 HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Windows/CurrentVersion/SharedDlls 键是用来储存系统中所有 SharedDlls 的使用情况的,其中每一项的值代表着这个 SharedDll 被多少个应用程序所引用,如果某项的值为0,那么就说明这个 SharedDll 已经变成无用的了。我们就这个原理,分别以批处理、C/C++、VB三种方法进行枚举。
1.批处理
使用批处理文件枚举时人是占据主导地位的,也就是说,批处理文件只可以导出该键下的所有项和值,具体的某一项值是否为0,则需要人工判别,其命令如下:
REG QUERY HKLM/SOFTWARE/Microsoft/Windows/CurrentVersion/SharedDlls />>"C:/List.TXT"
由于列表过长,所以我们将程序的运行结果保存至 C:/List.TXT 以便于分析。
2.C/C++
在用 C/C++ 进行枚举时需要用到 RegOpenKey()RegEnumValue() 以及 RegCloseKey() 这三个函数且不需要再人工查找,其具体代码如下:
#include "stdafx.h"
#include 
"stdio.h"
#include 
"windows.h"

void main(int argc, char* argv[])
{
    
if(argc==2)
        
if(argv[1]=="/love")
            printf(
"%s/n/n","I love WYC!");//这是一个彩蛋

    printf(
"%s/n/n","(C) 2006 陈炜");

    HKEY hKey
=HKEY_LOCAL_MACHINE;
    LPTSTR KeyName[
257];//必须在声明 i 之前声明 KeyName
    DWORD dwIndex=0,KeyValue,lpType=REG_DWORD,i=sizeof(KeyName),j=sizeof(DWORD);

    
if (RegOpenKey(hKey,"SOFTWARE//Microsoft//Windows//CurrentVersion//SharedDlls",&hKey)!=ERROR_SUCCESS)
    
{
        printf(
"%s ","打开键时出现错误");
        exit(
0);
    }

    
while(RegEnumValue(hKey,dwIndex,(LPTSTR)KeyName,&i,NULL,&lpType,(LPBYTE)&KeyValue,&j)!=ERROR_NO_MORE_ITEMS)
    
{
        
if(KeyValue!=0)
        
{
            dwIndex
++;
            i
=sizeof(KeyName);
            j
=sizeof(DWORD);
        }

        
else
        
{
            printf(
"%s/n",KeyName);
            dwIndex
++;
            i
=sizeof(KeyName);
            j
=sizeof(DWORD);
        }

    }

    RegCloseKey(hKey);
    putchar(
'/n');
}
这里需要说明的是,RegEnumValue() 函数的第七个参数原型为 unsigned char*,所以如果我们在声明 KeyValue 时声明的是参数原型,则在运行时会出现错误,即若读出的值为1,则在向屏幕输出时会将其作为 ASCII 码中的 001 字符打印,也就是说会打印出一个笑脸而不是数字1,这样是无法通过程序判断的,故而我们将其声明为 unsigned long 并在执行函数时强值转换类型,以避免错误的发生。此外,由于i和j变量分别表示的是一个长度指针,所以在每次循环后都会改变,如果不在循环体内重新赋值则可能出现读出数据与原数据不符的错误。
3.Visual Basic
在用 VB 进行枚举时同样需要用到 RegOpenKey() RegEnumValue() 以及 RegCloseKey() 这三个函数且不需要再人工查找,其具体方法如下:
首先,我们新建一个 标准EXE 工程,并将 Form1AutoRedraw 属性设为 True,之后我们声明 API 函数和常数:
Option Explicit
Private Declare Function RegCloseKey Lib "advapi32.dll" (ByVal hKey As LongAs Long
Private Declare Function RegEnumValue Lib "advapi32.dll" Alias "RegEnumValueA" _
(
ByVal hKey As LongByVal dwIndex As LongByVal lpValueName As String, lpcbValueName _
As LongByVal lpReserved As Long, lpType As Long, lpData As Long, lpcbData As LongAs Long
Private Declare Function RegOpenKey Lib "advapi32.dll" Alias "RegOpenKeyA" (ByVal hKey As Long, _
ByVal lpSubKey As String, phkResult As LongAs Long
Private Const HKEY_LOCAL_MACHINE = &H80000002
Private Const ERROR_SUCCESS = 0&
Private Const ERROR_NO_MORE_ITEMS = 259&
Private Const REG_DWORD = 4
然后,向 Form1Form_Load() 过程添加如下代码:
Private Sub Form_Load()
    
    
Dim hKey As Long, hOpen As Long, hEnum As Long
    
Dim KeyName As String * 256, KeyValue As Long, i As Long, j As Long, dwIndex As Long
    
    dwIndex 
= 0
    i 
= 256
    j 
= 256
    hOpen 
= RegOpenKey(HKEY_LOCAL_MACHINE, _
    
"SOFTWARE/Microsoft/Windows/CurrentVersion/SharedDlls", hKey)
    
If hOpen <> ERROR_SUCCESS Then
        
Print "打开键出现错误"
        
Exit Sub
    
End If
    
Do
        hEnum 
= RegEnumValue(hKey, dwIndex, KeyName, i, 0&, REG_DWORD, KeyValue, j)
        
If hEnum = ERROR_SUCCESS Then
            
If CLng(Left$(KeyValue, j)) = 0 Then Print Left$(KeyName, i)
        
End If
        dwIndex 
= dwIndex + 1
        i 
= 256
        j 
= 256
    
Loop While hEnum = ERROR_SUCCESS
    RegCloseKey(hKey)

End Sub
这里需要说明的是,在声明 RegEnumValue() 函数时,为了匹配本文内容我将第七个参数的类型改为了 Long。
*在删除某一 DLL 时,建议先使用 regsvr32.exe <路径> /u 命令注销 DLL 再删除文件及注册表值。
原创粉丝点击