dlldepend/dll_handle.cpp
2024-03-08 11:35:52 +08:00

207 lines
5.9 KiB
C++

#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, &currentTime);
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();
}