first commit
This commit is contained in:
commit
4e0430cda2
17
.clang-format
Normal file
17
.clang-format
Normal file
@ -0,0 +1,17 @@
|
||||
# .clang-format
|
||||
|
||||
# 风格格式化
|
||||
BasedOnStyle: Google
|
||||
# 4 空格缩进
|
||||
IndentWidth: 4
|
||||
# 连续对齐变量的声明
|
||||
AlignConsecutiveDeclarations: true
|
||||
# 指针左侧对齐
|
||||
PointerAlignment: Left
|
||||
# 访问说明符(public、private等)的偏移
|
||||
AccessModifierOffset: -4
|
||||
# 大括号
|
||||
BreakBeforeBraces: Custom
|
||||
BraceWrapping:
|
||||
# 函数定义后面大括号在新行
|
||||
AfterFunction: true
|
12
.clangd
Normal file
12
.clangd
Normal file
@ -0,0 +1,12 @@
|
||||
Hover:
|
||||
ShowAKA: Yes
|
||||
Diagnostics:
|
||||
UnusedIncludes: None # 禁用未使用头文件提示
|
||||
Suppress: [
|
||||
anon_type_definition, # 禁用匿名的typedef提示
|
||||
unused-variable, # 禁用未使用变量提示
|
||||
unused-function, # 禁用未使用函数提示
|
||||
unused-includes
|
||||
]
|
||||
ClangTidy:
|
||||
Remove: misc-unused-alias-decls
|
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
bui*
|
||||
.vs
|
34
.vscode/settings.json
vendored
Normal file
34
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
{
|
||||
"files.autoSave": "onFocusChange",
|
||||
"editor.fontSize": 14,
|
||||
"editor.fontFamily": "'FiraCode Nerd Font Mono', 'FiraCode Nerd Font Mono', 'FiraCode Nerd Font Mono'",
|
||||
"cmake.configureOnOpen": true,
|
||||
"cmake.debugConfig": {
|
||||
"console": "externalTerminal",
|
||||
"args": [
|
||||
"G:\\ARTM\\bin\\x64\\Debug\\CaptureExe.exe"
|
||||
]
|
||||
},
|
||||
"cmake.options.statusBarVisibility": "visible",
|
||||
"cmake.generator": "Ninja",
|
||||
"C_Cpp.intelliSenseEngine": "disabled",
|
||||
"clangd.arguments": [
|
||||
"--header-insertion=never",
|
||||
"--all-scopes-completion",
|
||||
"--completion-style=detailed",
|
||||
"--clang-tidy",
|
||||
"-j=4",
|
||||
"--pch-storage=memory",
|
||||
"--compile-commands-dir=build",
|
||||
"--background-index",
|
||||
"--ranking-model=heuristics",
|
||||
"--function-arg-placeholders=false",
|
||||
"--query-driver=/usr/bin/clang++"
|
||||
],
|
||||
"editor.inlayHints.enabled": "off",
|
||||
"editor.unicodeHighlight.allowedLocales": {
|
||||
"ja": true,
|
||||
"zh-hant": true,
|
||||
"zh-hans": true
|
||||
}
|
||||
}
|
21
CMakeLists.txt
Normal file
21
CMakeLists.txt
Normal file
@ -0,0 +1,21 @@
|
||||
cmake_minimum_required (VERSION 3.8)
|
||||
project (dll-dependent)
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
|
||||
set(CMAKE_PREFIX_PATH "C:/Bin/Boost")
|
||||
|
||||
if(NOT CMAKE_BUILD_TYPE)
|
||||
set(CMAKE_BUILD_TYPE "Debug")
|
||||
endif()
|
||||
if (MSVC)
|
||||
add_compile_options(/source-charset:utf-8)
|
||||
add_compile_options(/EHsc)
|
||||
add_compile_options(-D_CRT_SECURE_NO_WARNINGS)
|
||||
endif()
|
||||
|
||||
set(Boost_USE_STATIC_LIBS OFF)
|
||||
find_package(Boost REQUIRED filesystem)
|
||||
include_directories(${Boost_INCLUDES})
|
||||
|
||||
add_executable(dll-dependent main.cpp dll_handle.cpp cmd_opr.cpp)
|
||||
target_link_libraries(dll-dependent PRIVATE ${Boost_LIBRARIES})
|
50
cmd_opr.cpp
Normal file
50
cmd_opr.cpp
Normal file
@ -0,0 +1,50 @@
|
||||
#include "cmd_opr.h"
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <iostream>
|
||||
|
||||
|
||||
std::string CmdOpr::exec_cmd(const std::string& cmd)
|
||||
{
|
||||
std::string result{};
|
||||
|
||||
FILE* pipe = _popen(cmd.c_str(), "r");
|
||||
if (!pipe) {
|
||||
return result;
|
||||
}
|
||||
|
||||
char buffer[128]{};
|
||||
while (!feof(pipe)) {
|
||||
if (fgets(buffer, 128, pipe) != nullptr) {
|
||||
result += buffer;
|
||||
}
|
||||
}
|
||||
|
||||
_pclose(pipe);
|
||||
return result;
|
||||
}
|
||||
|
||||
bool add_environment_path(const std::string& path)
|
||||
{
|
||||
// 获取当前的 PATH 变量需要动态调整缓冲区大小
|
||||
DWORD bufferSize = GetEnvironmentVariable("PATH", nullptr, 0);
|
||||
if (bufferSize == 0) {
|
||||
std::cerr << "Failed to get PATH variable size!" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
char* currentPath = new char[bufferSize];
|
||||
GetEnvironmentVariable("PATH", currentPath, bufferSize);
|
||||
|
||||
// 构造新的 PATH 变量值(在原有路径后面添加新路径)
|
||||
std::string newPath = std::string(currentPath) + ";" + path;
|
||||
|
||||
// 设置修改后的 PATH 变量到环境变量中
|
||||
if (!SetEnvironmentVariable("PATH", newPath.c_str())) {
|
||||
std::cerr << "Failed to set PATH variable!" << std::endl;
|
||||
}
|
||||
delete[] currentPath;
|
||||
return true;
|
||||
}
|
12
cmd_opr.h
Normal file
12
cmd_opr.h
Normal file
@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
|
||||
class CmdOpr
|
||||
{
|
||||
public:
|
||||
CmdOpr() = default;
|
||||
~CmdOpr() = default;
|
||||
public:
|
||||
static std::string exec_cmd(const std::string& cmd);
|
||||
static bool add_environment_path(const std::string& path);
|
||||
};
|
206
dll_handle.cpp
Normal file
206
dll_handle.cpp
Normal file
@ -0,0 +1,206 @@
|
||||
#include "dll_handle.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/dll.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <chrono>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
|
||||
namespace fs = boost::filesystem;
|
||||
|
||||
bool DllHandle::read_ini(const std::string& purpose_dir)
|
||||
{
|
||||
no_dlls_.clear();
|
||||
exe_dlls_.clear();
|
||||
|
||||
fs::path cur_exe = boost::dll::program_location();
|
||||
fs::path config_path = cur_exe.parent_path().append("config.txt");
|
||||
if (!fs::exists(config_path)) {
|
||||
std::cout << "配置文件不存在,不进行设置。" << std::endl;
|
||||
return false;
|
||||
}
|
||||
std::ifstream in(config_path.string(), std::ios::in);
|
||||
if (!in.is_open()) {
|
||||
std::cout << "打开配置文件失败:" << cur_exe.string()
|
||||
<< ", 不进行设置。\n";
|
||||
return false;
|
||||
}
|
||||
std::list<std::string> dirs{};
|
||||
|
||||
// dirs.push_back(purpose_dir);
|
||||
|
||||
std::string tmp{};
|
||||
|
||||
int add_status = 0;
|
||||
while (std::getline(in, tmp)) {
|
||||
dirs.push_back(tmp);
|
||||
}
|
||||
in.close();
|
||||
|
||||
for (const auto& data : dirs) {
|
||||
if (!fs::exists(data) || !fs::is_directory(data)) {
|
||||
continue;
|
||||
}
|
||||
for (auto const& entry : fs::recursive_directory_iterator(data)) {
|
||||
if (!entry.is_regular_file() ||
|
||||
entry.path().extension().string() != ".dll") {
|
||||
continue;
|
||||
}
|
||||
DllInfo info;
|
||||
info.name = entry.path().filename().string();
|
||||
info.full_path = entry.path().string();
|
||||
no_dlls_.push_back(info);
|
||||
}
|
||||
}
|
||||
handle_multi_dll();
|
||||
|
||||
for (auto const& entry : fs::recursive_directory_iterator(purpose_dir)) {
|
||||
if (!entry.is_regular_file() ||
|
||||
entry.path().extension().string() != ".dll") {
|
||||
continue;
|
||||
}
|
||||
DllInfo info;
|
||||
info.name = entry.path().filename().string();
|
||||
info.full_path = entry.path().string();
|
||||
exe_dlls_.push_back(info);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
std::list<std::string> DllHandle::get_dependents(const std::string& binary)
|
||||
{
|
||||
std::string cmd = "dumpbin /DEPENDENTS " + binary;
|
||||
std::string result = CmdOpr::exec_cmd(cmd);
|
||||
std::list<std::string> dlls{};
|
||||
|
||||
std::list<std::string> tmp{};
|
||||
boost::split(tmp, result, boost::is_any_of("\n"));
|
||||
for (const auto& data : tmp) {
|
||||
if (!boost::contains(data, ".dll") || boost::contains(data, "Dump")) {
|
||||
continue;
|
||||
}
|
||||
std::string dllname(data);
|
||||
boost::trim(dllname);
|
||||
dlls.push_back(dllname);
|
||||
}
|
||||
return dlls;
|
||||
}
|
||||
|
||||
// 将字符串转换为小写形式
|
||||
std::string toLower(const std::string& str)
|
||||
{
|
||||
std::string result = str;
|
||||
std::transform(result.begin(), result.end(), result.begin(), ::tolower);
|
||||
return result;
|
||||
}
|
||||
|
||||
bool DllHandle::find_dll(const std::string& name, DllInfo& info)
|
||||
{
|
||||
bool find = false;
|
||||
// 先在 exe 所在的目录找。
|
||||
for (const auto& data : exe_dlls_) {
|
||||
if (toLower(name) != toLower(data.name)) {
|
||||
continue;
|
||||
}
|
||||
info.name = name;
|
||||
info.full_path = data.full_path;
|
||||
find = true;
|
||||
break;
|
||||
}
|
||||
|
||||
// 如果找到了就不往下找了
|
||||
if (find) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (const auto& data : no_dlls_) {
|
||||
if (toLower(name) != toLower(data.name)) {
|
||||
continue;
|
||||
}
|
||||
info.name = name;
|
||||
info.full_path = data.full_path;
|
||||
find = true;
|
||||
break;
|
||||
}
|
||||
return find;
|
||||
}
|
||||
|
||||
// 手动筛选多个dll的情况
|
||||
void DllHandle::handle_multi_dll()
|
||||
{
|
||||
simple_dlls.clear();
|
||||
for (const auto& data : no_dlls_) {
|
||||
simple_dlls[toLower(data.name)].push_back(data);
|
||||
}
|
||||
|
||||
for (auto& data : simple_dlls) {
|
||||
if (data.second.size() > 1) {
|
||||
std::cout << "========================\n";
|
||||
std::cout << "多个重名的dll,选择哪一个?\n";
|
||||
int index = 0;
|
||||
for (auto& dll : data.second) {
|
||||
dll.index = ++index;
|
||||
std::cout << dll.index << ":" << dll.full_path << ".\n";
|
||||
}
|
||||
std::string input{};
|
||||
std::cin >> input;
|
||||
int select = std::stoi(input);
|
||||
data.second.remove_if(
|
||||
[&](const DllInfo& info) { return info.index != select; });
|
||||
}
|
||||
}
|
||||
no_dlls_.clear();
|
||||
for (const auto& data : simple_dlls) {
|
||||
no_dlls_.push_back(data.second.front());
|
||||
}
|
||||
}
|
||||
|
||||
bool DllHandle::is_have(const std::list<DllInfo>& vec, const std::string& name)
|
||||
{
|
||||
bool find = false;
|
||||
for (const auto& data : vec) {
|
||||
if (toLower(data.name) != toLower(name)) {
|
||||
continue;
|
||||
}
|
||||
find = true;
|
||||
break;
|
||||
}
|
||||
return find;
|
||||
}
|
||||
|
||||
void DllHandle::copy_dll(const std::string& purpose_dir,
|
||||
const std::list<DllInfo>& tasks)
|
||||
{
|
||||
fs::path report_dir = fs::path(purpose_dir).parent_path();
|
||||
auto now = std::chrono::system_clock::now();
|
||||
std::time_t currentTime = std::chrono::system_clock::to_time_t(now);
|
||||
|
||||
std::tm timeInfo;
|
||||
localtime_s(&timeInfo, ¤tTime);
|
||||
|
||||
char buffer[256]{};
|
||||
std::strftime(buffer, sizeof(buffer), "report_%Y%m%d%H%M%S.txt", &timeInfo);
|
||||
std::string report_name = report_dir.append(buffer).string();
|
||||
|
||||
std::ofstream out(report_name, std::ios::out);
|
||||
if (!out.is_open()) {
|
||||
std::cout << "打开报告文件:" << report_name << "失败,结束执行。\n";
|
||||
return;
|
||||
}
|
||||
for (const auto& data : tasks) {
|
||||
fs::path des = fs::path(purpose_dir).append(data.name);
|
||||
if (fs::exists(des)) {
|
||||
std::string s = "跳过已存在的文件:" + des.string();
|
||||
out << s << "\n";
|
||||
std::cout << s << "\n";
|
||||
} else {
|
||||
fs::copy(data.full_path, des);
|
||||
std::string s = "复制文件:" + data.full_path;
|
||||
out << s << "\n";
|
||||
std::cout << s << "\n";
|
||||
}
|
||||
}
|
||||
out.close();
|
||||
}
|
38
dll_handle.h
Normal file
38
dll_handle.h
Normal file
@ -0,0 +1,38 @@
|
||||
#pragma once
|
||||
|
||||
#include <list>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include "cmd_opr.h"
|
||||
|
||||
struct DllInfo {
|
||||
int index{};
|
||||
std::string name{};
|
||||
std::string full_path{};
|
||||
};
|
||||
|
||||
class DllHandle {
|
||||
public:
|
||||
DllHandle() = default;
|
||||
~DllHandle() = default;
|
||||
|
||||
public:
|
||||
// 读取配置文件
|
||||
bool read_ini(const std::string& purpose_dir);
|
||||
// 获取一个二进制文件的依赖(参数为全路径)
|
||||
std::list<std::string> get_dependents(const std::string& binary);
|
||||
// 查找配置文件中配置的目录中指定名称的dll的信息
|
||||
bool find_dll(const std::string& name, DllInfo& info);
|
||||
// 是否在容器中
|
||||
static bool is_have(const std::list<DllInfo>& vec, const std::string& name);
|
||||
// 处理dll复制
|
||||
static void copy_dll(const std::string& purpose_dir,
|
||||
const std::list<DllInfo>& tasks);
|
||||
// 手动筛选多个dll的情况
|
||||
void handle_multi_dll();
|
||||
|
||||
private:
|
||||
std::list<DllInfo> no_dlls_{};
|
||||
std::list<DllInfo> exe_dlls_{};
|
||||
std::map<std::string, std::list<DllInfo>> simple_dlls{};
|
||||
};
|
63
main.cpp
Normal file
63
main.cpp
Normal file
@ -0,0 +1,63 @@
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <iostream>
|
||||
|
||||
#include "dll_handle.h"
|
||||
|
||||
|
||||
namespace fs = boost::filesystem;
|
||||
|
||||
/*
|
||||
* 注意:
|
||||
1.配置文件若有中文需要GBK编码
|
||||
2.程序会递归查找指定目录下所有的dll,如果有重复内容,请指定排除目录。
|
||||
3.配置文件名为 config.txt,与当前程序同目录,内容格式为:
|
||||
每一行一个文件夹。
|
||||
*/
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
if (argc < 2) {
|
||||
|
||||
std::string info("参数不够,第二个参数传入要处理的二进制文件路径(注意需要全路径)\n"
|
||||
"配置文件名为 config.txt,与当前程序同目录,内容格式为:\n"
|
||||
"每一行一个文件夹。");
|
||||
std::cout << info << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
fs::path exe_path(argv[1]);
|
||||
if (!fs::exists(exe_path)) {
|
||||
std::cout << "传入的路径不存在,请检查。" << std::endl;
|
||||
return 0;
|
||||
}
|
||||
fs::path exe_dir = exe_path.parent_path();
|
||||
|
||||
DllHandle handle{};
|
||||
handle.read_ini(exe_dir.string());
|
||||
|
||||
// handle.get_dependents()
|
||||
|
||||
// // Get All Dlls Dependents
|
||||
std::list<std::string> tmp_list{};
|
||||
std::list<DllInfo> task{};
|
||||
tmp_list = handle.get_dependents(argv[1]);
|
||||
|
||||
DllInfo tmp_info{};
|
||||
while (!tmp_list.empty()) {
|
||||
std::string& name = tmp_list.front();
|
||||
if (DllHandle::is_have(task, name) ||
|
||||
!handle.find_dll(name, tmp_info)) {
|
||||
tmp_list.pop_front();
|
||||
continue;
|
||||
}
|
||||
// std::cout << tmp_info.name << "\n";
|
||||
auto dep = handle.get_dependents(tmp_info.full_path);
|
||||
for (const auto& data : dep) {
|
||||
tmp_list.push_back(data);
|
||||
}
|
||||
task.push_back(tmp_info);
|
||||
tmp_list.pop_front();
|
||||
}
|
||||
handle.copy_dll(exe_dir.string(), task);
|
||||
return 0;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user