kaisawind's blog
  • 关于
  • 所有帖子

windows查看dll依赖 - Fri, Nov 13, 2020

windows查看dll依赖

windows查看dll依赖

在 Windows 开发中,DLL(Dynamic Link Library)依赖关系的管理和排查是一个常见且重要的任务。当程序无法启动或出现运行时错误时,通常是因为缺少必要的 DLL 依赖。本文介绍多种查看和分析 Windows DLL 依赖的方法和工具。

DLL 依赖基础

什么是 DLL 依赖

DLL 依赖指的是一个可执行文件或 DLL 文件需要加载的其他 DLL 文件。这些依赖关系包括:

  • 直接依赖:程序显式加载的 DLL
  • 间接依赖:依赖的 DLL 所需的其他 DLL
  • 系统依赖:Windows 系统 DLL(如 kernel32.dll、user32.dll 等)
  • 第三方依赖:第三方库或框架的 DLL

DLL 搜索顺序

Windows 按以下顺序搜索 DLL:

  1. 应用程序所在目录
  2. 系统目录(C:\Windows\System32)
  3. 16 位系统目录(C:\Windows\SysWOW64)
  4. Windows 目录(C:\Windows)
  5. 当前工作目录
  6. PATH 环境变量中的目录

使用 dumpbin 查看依赖

基本使用

dumpbin 是 Visual Studio 提供的命令行工具,可以显示 PE 文件的详细信息。

打开 Developer Command Prompt

开始菜单 → Visual Studio 2019 → Developer Command Prompt for VS 2019

查看依赖的 DLL

dumpbin /dependents ice_ipcsdk.dll

输出示例:

Microsoft (R) COFF/PE Dumper Version 14.29.30133.0
Copyright (C) Microsoft Corporation.  All rights reserved.


Dump of file ice_ipcsdk.dll

File Type: DLL

  Image has the following dependencies:

    KERNEL32.dll
    MSVCR120.dll
    msvcrt.dll
  Summary

        1000 .data
        1000 .pdata
        2000 .rdata
        1000 .reloc
        1000 .rsrc
        3000 .text

dumpbin 常用选项

# 查看导出函数
dumpbin /exports filename.dll

# 查看导入函数
dumpbin /imports filename.dll

# 查看完整头信息
dumpbin /headers filename.dll

# 查看调试信息
dumpbin /debugdata filename.dll

# 查看重定位信息
dumpbin /relocations filename.dll

# 查看资源
dumpbin /resourceonly filename.dll

# 输出到文件
dumpbin /dependents filename.dll > output.txt

批量查看多个文件

# 查看目录下所有 DLL 的依赖
for %f in (*.dll) do echo === %f === && dumpbin /dependents %f

# 将结果保存到文件
for %f in (*.dll) do echo === %f === >> deps.txt && dumpbin /dependents %f >> deps.txt

使用 Dependency Walker

下载和安装

Dependency Walker 是一个图形化工具,适合深度分析 DLL 依赖关系。

下载地址:http://www.dependencywalker.com/

基本使用

  1. 打开 Dependency Walker
  2. File → Open,选择要分析的 DLL 或 EXE
  3. 查看树形结构的依赖关系

输出解读

Dependency Walker 的界面包含:

  • 树形视图:显示所有依赖及其层级关系
  • 模块列表:列出所有模块及其状态
  • 导入函数:显示导入的函数
  • 导出函数:显示导出的函数
  • CPU 类型:显示目标平台(x86/x64)
  • 错误信息:高亮显示缺失的依赖

命令行使用

# 命令行模式分析
depends.exe -c output.txt ice_ipcsdk.dll

# 生成详细报告
depends.exe -a -c report.txt ice_ipcsdk.dll

使用 Dependencies(Dependency Walker 替代品)

Dependencies 是 Dependency Walker 的现代替代品,支持 64 位和 Windows 10+。

下载和安装

GitHub 下载:https://github.com/lucasg/Dependencies

使用方法

  1. 打开 Dependencies
  2. 拖放 DLL 文件到窗口
  3. 查看依赖关系图

高级功能

  • 依赖图:可视化的依赖关系
  • 延迟加载:支持分析延迟加载的 DLL
  • 搜索:快速查找特定 DLL 或函数
  • 导出:导出依赖关系为 JSON 或 XML

使用 PowerShell

查看 DLL 依赖

# 使用 Add-Type 加载程序集
Add-Type -AssemblyName System.Reflection

# 加载 DLL 并查看依赖
$assembly = [System.Reflection.Assembly]::LoadFile("C:\path\to\ice_ipcsdk.dll")
$assembly.GetReferencedAssemblies() | Select-Object Name, Version

批量扫描

# 扫描目录下所有 DLL
$directory = "C:\MyApp\bin"
Get-ChildItem -Path $directory -Filter *.dll | ForEach-Object {
    Write-Host "=== $($_.Name) ==="
    try {
        $assembly = [System.Reflection.Assembly]::LoadFile($_.FullName)
        $assembly.GetReferencedAssemblies() | Select-Object Name, Version | Format-Table
    } catch {
        Write-Host "Error: $($_.Exception.Message)" -ForegroundColor Red
    }
}

使用 Process 类分析运行中进程

# 查看运行中进程的模块
$process = Get-Process -Name "notepad"
$process.Modules | Select-Object ModuleName, FileName, FileVersionInfo | Format-Table

使用 dumpbin 脚本自动化

创建分析脚本

创建 analyze_deps.bat:

@echo off
setlocal

if "%~1"=="" (
    echo 用法: %~nx0 ^<文件名^> [输出文件]
    exit /b 1
)

set FILE=%~1
set OUTPUT=%~2

if not exist "%FILE%" (
    echo 错误: 文件不存在: %FILE%
    exit /b 1
)

echo 分析文件: %FILE%
echo.

call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat"

if defined OUTPUT (
    dumpbin /dependents "%FILE%" > "%OUTPUT%"
    echo 结果已保存到: %OUTPUT%
) else (
    dumpbin /dependents "%FILE%"
)

endlocal

使用方法:

analyze_deps.bat ice_ipcsdk.dll output.txt

递归分析依赖

创建 recursive_deps.ps1:

param(
    [Parameter(Mandatory=$true)]
    [string]$FilePath,
    
    [string]$OutputDir = ".",
    
    [int]$MaxDepth = 3
)

function Get-DllDependencies {
    param(
        [string]$Path,
        [int]$CurrentDepth,
        [hashtable]$Visited,
        [array]$Result
    )
    
    if ($CurrentDepth -gt $MaxDepth) { return }
    if ($Visited.ContainsKey($Path)) { return }
    
    $Visited[$Path] = $true
    
    try {
        $deps = & dumpbin /dependents $Path 2>&1 | Select-String "\.dll"
        
        foreach ($dep in $deps) {
            $depName = $dep.Line.Trim()
            
            # 尝试在多个位置查找 DLL
            $searchPaths = @(
                (Split-Path $Path),
                "$env:SystemRoot\System32",
                "$env:SystemRoot\SysWOW64"
            )
            
            $foundPath = $null
            foreach ($searchPath in $searchPaths) {
                $testPath = Join-Path $searchPath $depName
                if (Test-Path $testPath) {
                    $foundPath = $testPath
                    break
                }
            }
            
            if ($foundPath) {
                $indent = "  " * $CurrentDepth
                $result += [PSCustomObject]@{
                    Path = $Path
                    Dependency = $depName
                    FullPath = $foundPath
                    Depth = $CurrentDepth
                }
                
                Get-DllDependencies -Path $foundPath -CurrentDepth ($CurrentDepth + 1) -Visited $Visited -Result $result
            } else {
                $indent = "  " * $CurrentDepth
                Write-Host "$indent[MISSING] $depName" -ForegroundColor Yellow
            }
        }
    } catch {
        Write-Host "Error analyzing $Path: $($_.Exception.Message)" -ForegroundColor Red
    }
    
    return $Result
}

# 执行分析
$visited = @{}
$result = @()

$finalResult = Get-DllDependencies -Path $FilePath -CurrentDepth 0 -Visited $visited -Result $result

# 输出结果
if ($OutputDir -ne ".") {
    $outputFile = Join-Path $OutputDir "dependencies.json"
    $finalResult | ConvertTo-Json -Depth 100 | Out-File $outputFile -Encoding UTF8
    Write-Host "结果已保存到: $outputFile"
} else {
    $finalResult | Format-Table Path, Dependency, FullPath, Depth -AutoSize
}

使用方法:

# 分析到屏幕
.\recursive_deps.ps1 ice_ipcsdk.dll

# 保存到文件
.\recursive_deps.ps1 ice_ipcsdk.dll -OutputDir .\output

常见问题和解决方案

1. 找不到 dumpbin

问题: dumpbin 命令不存在

解决方案:

# 查找 dumpbin 位置
where /R "C:\Program Files" dumpbin.exe

# 添加到 PATH 或使用完整路径
"C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30133\bin\Hostx64\x64\dumpbin.exe" /dependents ice_ipcsdk.dll

2. 缺少 DLL

问题: Dependency Walker 显示红色(缺失的 DLL)

解决方案:

# 查找 DLL 在系统中的位置
where /R C:\Windows missing_dll.dll

# 搜索所有驱动器
for %d in (C D E F) do @if exist %d:\ dir /s /b %d:\missing_dll.dll 2>nul

# 从网上下载并放到正确的位置
# 推荐位置:
# 1. 应用程序目录
# 2. System32 目录(需要管理员权限)

3. 32 位 vs 64 位

问题: 架构不匹配

解决方案:

# 检查 DLL 架构
dumpbin /headers ice_ipcsdk.dll | findstr /C:"machine (x86)"

# 32 位: machine (x86)
# 64 位: machine (x64)

# 使用正确版本的 dumpbin
# 32 位: vcvars32.bat
# 64 位: vcvars64.bat

4. DLL 版本冲突

问题: 多个版本的同名 DLL

解决方案:

# 查找所有版本的 DLL
Get-ChildItem -Path C:\ -Recurse -Filter "problematic.dll" -ErrorAction SilentlyContinue | Select-Object FullName, VersionInfo

# 比较版本
$files = Get-ChildItem -Path C:\ -Recurse -Filter "problematic.dll" -ErrorAction SilentlyContinue
$files | Select-Object FullName, @{Name="FileVersion"; Expression={$_.VersionInfo.FileVersion}} | Sort-Object FileVersion -Descending

5. 依赖地狱

问题: 复杂的依赖关系难以管理

解决方案:

  1. 使用应用程序本地化: 将依赖 DLL 放在应用目录
  2. 使用 DLL 重定向: 创建 app.local 文件
  3. 使用 SxS(Side-by-Side): Windows 并行程序集
  4. 使用依赖注入: 动态加载 DLL

最佳实践

  1. 依赖管理:

    • 将应用依赖的 DLL 放在应用目录
    • 使用版本控制管理依赖
    • 记录所有第三方库的版本
  2. 部署策略:

    • 使用安装程序打包所有依赖
    • 创建依赖检查脚本
    • 提供离线安装包
  3. 开发习惯:

    • 定期运行依赖分析
    • 使用静态链接减少依赖
    • 考虑使用容器化部署
  4. 文档化:

    • 记录所有依赖关系
    • 编写部署文档
    • 创建故障排查指南

自动化工具集成

CI/CD 集成

# GitLab CI 示例
analyze_dll:
  stage: analyze
  script:
    - echo "分析 DLL 依赖"
    - powershell -File analyze_deps.ps1 -FilePath .\output\myapp.exe -OutputDir .\output
    - powershell -Command "if (Test-Path .\output\missing.txt) { exit 1 }"
  artifacts:
    paths:
      - output/

构建后检查

# CMake 示例
add_custom_command(TARGET myapp POST_BUILD
    COMMAND ${CMAKE_COMMAND} -E echo "Checking DLL dependencies..."
    COMMAND powershell -File ${CMAKE_SOURCE_DIR}/scripts/check_deps.ps1 ${OUTPUT_DIR}
)

相关资源

  • dumpbin 文档: https://docs.microsoft.com/en-us/cpp/build/reference/dumpbin-reference
  • Dependency Walker: http://www.dependencywalker.com/
  • Dependencies: https://github.com/lucasg/Dependencies
  • PE 文件格式: https://docs.microsoft.com/en-us/windows/win32/debug/pe-format


辽ICP备2021007608号 | © 2026 | kaisawind

Facebook Twitter GitHub