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