207 lines
5.9 KiB
C++
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, ¤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();
|
|
}
|