Skip to content

Commit e0b523d

Browse files
committed
fix:修复忽略 C++ 运行库的问题, C++ 运行库也会被一并复制;
1 parent 7ab7fef commit e0b523d

File tree

5 files changed

+105
-78
lines changed

5 files changed

+105
-78
lines changed

CMakeLists.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,15 @@ cmake_minimum_required(VERSION 3.10)
44
string(TIMESTAMP PROJECT_YEAR "%Y")
55

66
project(win_deploy
7-
VERSION 1.1.0.0
7+
VERSION 1.1.1.0
88
DESCRIPTION "Windows DLL dependency analyzer and deployment tool"
99
LANGUAGES CXX
1010
)
1111

1212
# Project version configuration (explicit for flexibility)
1313
set(PROJECT_VERSION_MAJOR 1)
1414
set(PROJECT_VERSION_MINOR 1)
15-
set(PROJECT_VERSION_PATCH 0)
15+
set(PROJECT_VERSION_PATCH 1)
1616
set(PROJECT_VERSION_TWEAK 0)
1717
set(PROJECT_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}.${PROJECT_VERSION_TWEAK}")
1818
set(PROJECT_NAME "win_deploy")

README.md

Lines changed: 36 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,19 @@
1-
# WinDeploy - Windows Dependency DLL Analysis and Deployment Tool
1+
# WinDeploy - Windows DLL Dependency Analysis and Deployment Tool
22

3-
**[English](README.MD) | [中文](README_CN.MD)**
3+
## Introduction
44

5-
## Project Introduction
6-
7-
WinDeploy is a command-line tool for analyzing the dependency DLLs of Windows executable files (.exe) and optionally copying these DLL files to a specified directory. This tool is particularly useful for the deployment and distribution of Windows applications, helping developers collect all necessary dependency libraries.
5+
WinDeploy is a command-line tool for analyzing the DLL dependencies of Windows executable files (.exe) and dynamic-link libraries (.dll), with an option to copy these dependent DLL files to a specified directory. This tool is particularly useful for Windows application deployment and distribution, helping developers collect all necessary dependencies.
86

97
## Features
108

11-
- Analyze PE headers of Windows executable files to extract the list of dependent DLLs
12-
- Support recursive analysis of all levels of DLL dependencies
13-
- Support searching for DLL files in multiple locations (executable directory, system directories, PATH environment variables, etc.)
9+
- Analyze PE headers of Windows executables and DLLs to extract lists of dependent DLLs
10+
- Support recursive analysis of DLL dependencies at all levels
11+
- Support searching for DLL files in multiple locations (executable directory, system directories, PATH environment variable, etc.)
1412
- Support loading additional search directories and ignore lists from files
15-
- Optionally copy dependent DLLs to a specified directory
16-
- Automatically identify and skip Windows system core DLLs (such as KERNEL32.dll, USER32.dll, etc.)
17-
- Support for x64 and x86 architecture PE files
18-
- Use RAII pattern to manage Windows resources, ensuring proper resource release
13+
- Option to copy dependent DLLs to a specified directory
14+
- Automatically identify and skip Windows core DLLs (such as KERNEL32.dll, USER32.dll, etc.)
15+
- Support both x64 and x86 architecture PE files
16+
- Use RAII pattern for Windows resource management, ensuring proper resource cleanup
1917
- Detailed error handling and log output
2018

2119
## Build Requirements
@@ -49,40 +47,43 @@ cmake .. -G "Ninja" -DCMAKE_BUILD_TYPE=Release
4947
cmake --build .
5048
```
5149

52-
After building, the executable file will be located in the `build/bin` directory.
50+
After building, the executable will be located in the `build/bin` directory.
5351

5452
## Usage
5553

5654
### Basic Usage
5755

5856
```bash
59-
# Analyze dependency DLLs of an executable (first level only)
57+
# Analyze executable file's dependent DLLs (first level only)
6058
win_deploy.exe C:\Path\To\YourApp.exe
6159

62-
# Recursively analyze all levels of dependency DLLs
60+
# Analyze DLL file's dependencies
61+
win_deploy.exe C:\Path\To\YourLibrary.dll
62+
63+
# Recursively analyze all levels of dependent DLLs
6364
win_deploy.exe C:\Path\To\YourApp.exe --recursive
6465

65-
# Recursively analyze with specified maximum depth (default: 20)
66+
# Recursively analyze with specified maximum depth (default 20)
6667
win_deploy.exe C:\Path\To\YourApp.exe --recursive 10
6768
```
6869

6970
### Release Mode
7071

7172
```bash
72-
# Release mode: Recursively analyze dependencies (depth: 2) and copy to executable's directory
73+
# Release mode: recursively analyze dependencies (depth 2) and copy to executable directory
7374
win_deploy.exe C:\Path\To\YourApp.exe --release
7475

7576
# Release mode with specified recursion depth
7677
win_deploy.exe C:\Path\To\YourApp.exe --release 3
7778
```
7879

79-
### Copy Dependency DLLs
80+
### Copying Dependent DLLs
8081

8182
```bash
82-
# Copy dependency DLLs to a specified directory
83+
# Copy dependent DLLs to specified directory
8384
win_deploy.exe C:\Path\To\YourApp.exe --copy C:\DestDir
8485

85-
# Copy dependency DLLs to the executable's directory
86+
# Copy dependent DLLs to executable file's directory
8687
win_deploy.exe C:\Path\To\YourApp.exe --copy-exe-dir
8788

8889
# Copy all DLLs (including system core DLLs)
@@ -101,7 +102,7 @@ win_deploy.exe C:\Path\To\YourApp.exe --search-dirs search_paths.txt
101102
# # Lines starting with # or ; are treated as comments
102103
```
103104

104-
### Using Ignore List
105+
### Using Ignore Lists
105106

106107
```bash
107108
# Load ignore list from file
@@ -123,23 +124,23 @@ win_deploy.exe C:\Path\To\YourApp.exe --ignore-dll ignore.txt
123124
win_deploy.exe C:\Path\To\YourApp.exe --release --search-dirs search_paths.txt --ignore-dll ignore.txt
124125
```
125126

126-
### Command Line Arguments
127+
### Command Line Parameters
127128

128129
```
129-
Usage: win_deploy.exe <executable_path> [options]
130+
Usage: win_deploy.exe <executable_path|dll_path> [options]
130131
131132
Options:
132-
--release [depth] Release mode: Recursively analyze dependencies (default depth: 2)
133-
and copy to the executable's directory
133+
--release [depth] Release mode: recursively analyze dependencies (default depth: 2) and copy to file's directory
134134
--recursive [depth] Recursively analyze all DLL dependencies (default depth: 20)
135-
--copy <target_dir> Copy dependency DLLs to the specified directory
136-
--copy-exe-dir Copy dependency DLLs to the executable's directory
135+
--copy <dest_dir> Copy dependent DLLs to specified directory
136+
--copy-exe-dir Copy dependent DLLs to the file's directory
137137
--copy-all Copy all DLLs (including system core DLLs)
138138
--search-dirs <file> Load additional search directories from file (one path per line)
139139
--ignore-dll <file> Load ignore list from file (DLL names, paths, or directories)
140140
141141
Examples:
142142
win_deploy.exe C:\Path\To\YourApp.exe
143+
win_deploy.exe C:\Path\To\YourLibrary.dll
143144
win_deploy.exe C:\Path\To\YourApp.exe --release
144145
win_deploy.exe C:\Path\To\YourApp.exe --release 3
145146
win_deploy.exe C:\Path\To\YourApp.exe --recursive
@@ -160,20 +161,18 @@ Examples:
160161

161162
## How It Works
162163

163-
1. **PE File Analysis**: The tool reads the PE header of the executable file, parses the Import Directory and Delay Load Import Directory, and obtains all dependent DLL names.
164-
165-
2. **Recursive Analysis**: If recursive mode is enabled, the tool will逐层 analyze the dependencies of each dependent DLL until the maximum recursion depth is reached or all dependencies are analyzed.
166-
167-
3. **DLL Search**: Search for DLL files in the following priority order:
164+
1. **PE File Analysis**: The tool reads the PE header of the executable or DLL, parsing the Import Directory and Delay Import Directory to obtain all dependent DLL names.
165+
2. **Recursive Analysis**: If recursive mode is enabled, the tool analyzes the dependencies of each dependent DLL level by level until the maximum recursion depth is reached or all dependencies are analyzed.
166+
3. **DLL Search**: DLL files are searched in the following priority order:
168167

169168
- **Additional specified search directories** (specified via `--search-dirs` parameter, highest priority)
170-
- Executable file directory
169+
- Directory of the analyzed file
171170
- Current working directory
172171
- System directory (System32)
173172
- Windows directory
174-
- All directories in the PATH environment variable
173+
- All directories in PATH environment variable
174+
4. **File Copying**: If copy options are specified, the tool copies found DLL files to the target directory:
175175

176-
4. **File Copying**: If the copy option is specified, the tool will copy the found DLL files to the target directory:
177176
- Automatically identify and skip Windows system core DLLs (unless using `--copy-all`)
178177
- Skip DLLs in the ignore list
179178
- Automatically create target directory
@@ -183,9 +182,9 @@ Examples:
183182

184183
- Use Windows API for file operations and PE file parsing
185184
- Implement RVA (Relative Virtual Address) to file offset conversion
186-
- Support parsing of regular import tables and delay load import tables
185+
- Support parsing both regular import tables and delay-load import tables
187186
- Use RAII pattern to manage Windows handles and memory-mapped views
188-
- Support detection of various PE file architectures (x64, x86)
187+
- Support detection of multiple PE file architectures (x64, x86)
189188
- Include complete error handling and boundary checks
190189
- Automatically detect system core DLL list, including KERNEL32, USER32, GDI32, ADVAPI32, etc.
191190

@@ -204,18 +203,3 @@ windeployexe/
204203
## License
205204

206205
MIT
207-
208-
## Contributing
209-
210-
Bug reports and feature requests are welcome. If you want to contribute code, please ensure:
211-
212-
1. Code follows the project's coding style
213-
2. Add appropriate comments and documentation
214-
3. Ensure the code compiles and runs correctly on the target platform
215-
216-
## Contact
217-
218-
For questions or suggestions, please contact through:
219-
220-
- Create a GitHub Issue
221-
- Send an email to the project maintainer

README_CN.MD

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
## 项目简介
44

5-
WinDeploy 是一个命令行工具,用于分析 Windows 可执行文件(.exe)的依赖 DLL,并可以选择性地将这些 DLL 文件复制到指定目录。该工具特别适用于 Windows 应用程序的部署和分发,帮助开发者收集所有必要的依赖库。
5+
WinDeploy 是一个命令行工具,用于分析 Windows 可执行文件(.exe)和动态链接库(.dll)的依赖关系,并可以选择性地将这些依赖的 DLL 文件复制到指定目录。该工具特别适用于 Windows 应用程序的部署和分发,帮助开发者收集所有必要的依赖库。
66

77
## 功能特点
88

@@ -57,6 +57,9 @@ cmake --build .
5757
# 分析可执行文件的依赖 DLL(仅第一层)
5858
win_deploy.exe C:\Path\To\YourApp.exe
5959

60+
# 分析 DLL 文件的依赖
61+
win_deploy.exe C:\Path\To\YourLibrary.dll
62+
6063
# 递归分析所有层级的依赖 DLL
6164
win_deploy.exe C:\Path\To\YourApp.exe --recursive
6265

@@ -124,19 +127,20 @@ win_deploy.exe C:\Path\To\YourApp.exe --release --search-dirs search_paths.txt -
124127
### 命令行参数
125128

126129
```
127-
用法: win_deploy.exe <可执行文件路径> [选项]
130+
用法: win_deploy.exe <可执行文件路径|DLL文件路径> [选项]
128131
129132
选项:
130-
--release [depth] 发布模式:递归分析依赖(默认深度:2)并复制到可执行文件所在目录
133+
--release [depth] 发布模式:递归分析依赖(默认深度:2)并复制到文件所在目录
131134
--recursive [depth] 递归分析所有 DLL 依赖(默认深度:20)
132135
--copy <目标目录> 复制依赖 DLL 到指定目录
133-
--copy-exe-dir 复制依赖 DLL 到可执行文件所在目录
136+
--copy-exe-dir 复制依赖 DLL 到文件所在目录
134137
--copy-all 复制所有 DLL(包括系统核心 DLL)
135138
--search-dirs <文件> 从文件加载额外的搜索目录(每行一个路径)
136139
--ignore-dll <文件> 从文件加载忽略列表(DLL 名称、路径或目录)
137140
138141
示例:
139142
win_deploy.exe C:\Path\To\YourApp.exe
143+
win_deploy.exe C:\Path\To\YourLibrary.dll
140144
win_deploy.exe C:\Path\To\YourApp.exe --release
141145
win_deploy.exe C:\Path\To\YourApp.exe --release 3
142146
win_deploy.exe C:\Path\To\YourApp.exe --recursive
@@ -157,12 +161,12 @@ win_deploy.exe C:\Path\To\YourApp.exe --release --search-dirs search_paths.txt -
157161

158162
## 工作原理
159163

160-
1. **PE 文件分析**工具读取可执行文件的 PE 头,解析导入表(Import Directory)和延迟加载导入表,获取所有依赖的 DLL 名称。
164+
1. **PE 文件分析**工具读取可执行文件或 DLL 的 PE 头,解析导入表(Import Directory)和延迟加载导入表,获取所有依赖的 DLL 名称。
161165
2. **递归分析**:如果启用递归模式,工具会逐层分析每个依赖 DLL 的依赖关系,直到达到最大递归深度或所有依赖都被分析完毕。
162166
3. **DLL 搜索**:按照以下优先级顺序搜索 DLL 文件:
163167

164168
- **额外指定的搜索目录**(通过 `--search-dirs` 参数指定,优先级最高)
165-
- 可执行文件所在目录
169+
- 被分析文件所在目录
166170
- 当前工作目录
167171
- 系统目录(System32)
168172
- Windows 目录

main.cc

Lines changed: 55 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,8 @@ std::string GetWindowsDirectory()
398398
}
399399

400400
// 系统核心DLL列表
401+
// 注意:C++ 运行库 (MSVCR*.dll, MSVCP*.dll, UCRTBASE.dll, VCRUNTIME*.dll, VCCORLIB*.dll)
402+
// 不在此列表中,需要被复制
401403
const std::set<std::string> systemCoreDLLs = {
402404
"KERNEL32.dll",
403405
"KERNEL32.DLL",
@@ -425,22 +427,6 @@ const std::set<std::string> systemCoreDLLs = {
425427
"VERSION.DLL",
426428
"IMM32.dll",
427429
"IMM32.DLL",
428-
"MSVCRT.dll",
429-
"MSVCRT.DLL",
430-
"MSVCR100.dll",
431-
"MSVCR100.DLL",
432-
"MSVCR110.dll",
433-
"MSVCR110.DLL",
434-
"MSVCR120.dll",
435-
"MSVCR120.DLL",
436-
"MSVCP100.dll",
437-
"MSVCP100.DLL",
438-
"MSVCP110.dll",
439-
"MSVCP110.DLL",
440-
"MSVCP120.dll",
441-
"MSVCP120.DLL",
442-
"UCRTBASE.dll",
443-
"UCRTBASE.DLL",
444430
"NTDLL.dll",
445431
"NTDLL.DLL",
446432
"CRYPT32.dll",
@@ -478,6 +464,50 @@ bool IsSystemCoreDLL(const std::string &dllName)
478464
return false;
479465
}
480466

467+
// 检查是否为 C++ 运行库 DLL
468+
bool IsCppRuntimeDLL(const std::string &dllName)
469+
{
470+
// 转换为大写进行比较
471+
std::string upperDllName = dllName;
472+
std::transform(upperDllName.begin(), upperDllName.end(), upperDllName.begin(), ::toupper);
473+
474+
// 检查是否为 C 运行库 (MSVCR*.dll, VCRUNTIME*.dll)
475+
if (upperDllName.find("MSVCR") == 0 && upperDllName.find(".DLL") == upperDllName.length() - 4)
476+
{
477+
return true;
478+
}
479+
if (upperDllName.find("VCRUNTIME") == 0 && upperDllName.find(".DLL") == upperDllName.length() - 4)
480+
{
481+
return true;
482+
}
483+
484+
// 检查是否为 C++ 标准库 (MSVCP*.dll)
485+
if (upperDllName.find("MSVCP") == 0 && upperDllName.find(".DLL") == upperDllName.length() - 4)
486+
{
487+
return true;
488+
}
489+
490+
// 检查是否为 C++/CX 库 (VCCORLIB*.dll)
491+
if (upperDllName.find("VCCORLIB") == 0 && upperDllName.find(".DLL") == upperDllName.length() - 4)
492+
{
493+
return true;
494+
}
495+
496+
// 检查是否为 Universal C Runtime (UCRTBASE.dll)
497+
if (upperDllName == "UCRTBASE.DLL")
498+
{
499+
return true;
500+
}
501+
502+
// 检查是否为 ConcRT 库 (CONCRT*.dll)
503+
if (upperDllName.find("CONCRT") == 0 && upperDllName.find(".DLL") == upperDllName.length() - 4)
504+
{
505+
return true;
506+
}
507+
508+
return false;
509+
}
510+
481511
// 判断DLL路径是否位于系统核心目录
482512
bool IsSystemDirectory(const std::string &dllPath)
483513
{
@@ -486,6 +516,15 @@ bool IsSystemDirectory(const std::string &dllPath)
486516
return false;
487517
}
488518

519+
// 提取 DLL 文件名
520+
std::string dllName = std::filesystem::path(dllPath).filename().string();
521+
522+
// 如果是 C++ 运行库,即使位于系统目录也不跳过
523+
if (IsCppRuntimeDLL(dllName))
524+
{
525+
return false;
526+
}
527+
489528
// 转换为大写进行路径比较
490529
std::string upperPath = dllPath;
491530
std::transform(upperPath.begin(), upperPath.end(), upperPath.begin(), ::toupper);

version.rc.in

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,11 @@ BEGIN
1717
BEGIN
1818
BLOCK "040904b0"
1919
BEGIN
20-
VALUE "CompanyName", "Your Company Name"
20+
VALUE "CompanyName", "icloudwar"
2121
VALUE "FileDescription", "@PROJECT_DESCRIPTION@"
2222
VALUE "FileVersion", "@PROJECT_VERSION_MAJOR@.@PROJECT_VERSION_MINOR@.@PROJECT_VERSION_PATCH@.@PROJECT_VERSION_TWEAK@"
2323
VALUE "InternalName", "@PROJECT_NAME@"
24-
VALUE "LegalCopyright", "Copyright @PROJECT_YEAR@"
24+
VALUE "LegalCopyright", "icloudwar Copyright @PROJECT_YEAR@"
2525
VALUE "OriginalFilename", "@[email protected]"
2626
VALUE "ProductName", "@PROJECT_NAME@"
2727
VALUE "ProductVersion", "@PROJECT_VERSION_MAJOR@.@PROJECT_VERSION_MINOR@.@PROJECT_VERSION_PATCH@.@PROJECT_VERSION_TWEAK@"

0 commit comments

Comments
 (0)