Advertisement
YaBoiSwayZ

FileOps v1

Jul 18th, 2024
107
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 10.38 KB | Source Code | 0 0
  1. #ifndef FILE_OPERATIONS_H
  2. #define FILE_OPERATIONS_H
  3.  
  4. #include <iostream>
  5. #include <string>
  6. #include <Windows.h>
  7. #include <random>
  8. #include <filesystem>
  9. #include <fstream>
  10. #include <memory>
  11. #include <vector>
  12. #include <thread>
  13. #include <mutex>
  14. #include <spdlog/spdlog.h>
  15. #include <spdlog/sinks/rotating_file_sink.h>
  16. #include <atomic>
  17. #include <tclap/CmdLine.h>
  18. #include <ncurses.h>
  19. #include <thread>
  20. #include <future>
  21.  
  22. class FileOperationException : public std::exception {
  23. public:
  24.     FileOperationException(const std::string& message) : m_message(message) {}
  25.     const char* what() const noexcept override { return m_message.c_str(); }
  26. private:
  27.     std::string m_message;
  28. };
  29.  
  30. class Config {
  31. public:
  32.     static const int MAX_RETRIES = 3;
  33.     static const int THREAD_POOL_SIZE = 4;
  34.     static const int BATCH_SIZE = 10;
  35.     static const std::string LOG_FILE_NAME;
  36.     static const int MAX_LOG_SIZE;
  37.     static const int MAX_LOG_FILES;
  38. };
  39.  
  40. const std::string Config::LOG_FILE_NAME = "program_log.txt";
  41. const int Config::MAX_LOG_SIZE = 1024 * 1024; // 1 MB
  42. const int Config::MAX_LOG_FILES = 5;
  43.  
  44. class FileOperations {
  45. public:
  46.     static std::vector<std::filesystem::path> FindFiles(const std::filesystem::path& directoryPath, const std::wstring& extension) {
  47.         std::vector<std::filesystem::path> files;
  48.         try {
  49.             for (const auto& entry : std::filesystem::directory_iterator(directoryPath)) {
  50.                 if (entry.path().extension() == extension) {
  51.                     files.push_back(entry.path());
  52.                 }
  53.             }
  54.         } catch (const std::filesystem::filesystem_error& e) {
  55.             throw FileOperationException("Error accessing directory " + directoryPath.string() + ": " + e.what());
  56.         }
  57.         return files;
  58.     }
  59.  
  60.     static bool DeleteFile(const std::wstring& filePath) {
  61.         for (int i = 0; i < Config::MAX_RETRIES; ++i) {
  62.             if (::DeleteFileW(filePath.c_str()) != 0) {
  63.                 return true;
  64.             }
  65.             spdlog::warn("Retrying deletion of file: {}", std::string(filePath.begin(), filePath.end()));
  66.             std::this_thread::sleep_for(std::chrono::milliseconds(100));
  67.         }
  68.         throw FileOperationException("Failed to delete file after " + std::to_string(Config::MAX_RETRIES) + " retries: " + std::string(filePath.begin(), filePath.end()));
  69.     }
  70.  
  71.     static bool RenameFile(const std::filesystem::path& filePath, const std::filesystem::path& newFilePath) {
  72.         try {
  73.             std::filesystem::rename(filePath, newFilePath);
  74.             return true;
  75.         } catch (const std::filesystem::filesystem_error& e) {
  76.             throw FileOperationException("Failed to rename file " + filePath.string() + ": " + e.what());
  77.         }
  78.     }
  79.  
  80.     static bool RemoveExtension(const std::filesystem::path& filePath) {
  81.         std::filesystem::path newFilePath = filePath;
  82.         newFilePath.replace_extension();
  83.         return RenameFile(filePath, newFilePath);
  84.     }
  85. };
  86.  
  87. class ProcessManager {
  88. public:
  89.     static bool CreateHiddenProcess(const std::wstring& executablePath) {
  90.         STARTUPINFOW si{};
  91.         PROCESS_INFORMATION pi{};
  92.  
  93.         si.cb = sizeof(si);
  94.         si.dwFlags = STARTF_USESHOWWINDOW;
  95.         si.wShowWindow = SW_HIDE;
  96.  
  97.         for (int i = 0; i < Config::MAX_RETRIES; ++i) {
  98.             if (CreateProcessW(executablePath.c_str(), NULL, NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi)) {
  99.                 CloseHandle(pi.hProcess);
  100.                 CloseHandle(pi.hThread);
  101.                 return true;
  102.             }
  103.             spdlog::warn("Retrying creation of process for: {}", std::string(executablePath.begin(), executablePath.end()));
  104.             std::this_thread::sleep_for(std::chrono::milliseconds(100));
  105.         }
  106.         throw FileOperationException("Failed to create process after " + std::to_string(Config::MAX_RETRIES) + " retries: " + std::string(executablePath.begin(), executablePath.end()));
  107.     }
  108. };
  109.  
  110. void HideConsoleWindow() {
  111.     HWND hwnd = GetConsoleWindow();
  112.     if (hwnd != NULL) {
  113.         ShowWindow(hwnd, SW_HIDE);
  114.     } else {
  115.         throw FileOperationException("Failed to get console window handle");
  116.     }
  117. }
  118.  
  119. bool is_valid_choice(int choice, int min, int max) {
  120.     return choice >= min && choice <= max;
  121. }
  122.  
  123. void ShowProgress(std::atomic<int>& progress, int total) {
  124.     initscr();
  125.     cbreak();
  126.     noecho();
  127.     nodelay(stdscr, TRUE);
  128.     curs_set(0);
  129.  
  130.     while (progress < total) {
  131.         clear();
  132.         int currentProgress = progress.load();
  133.         int percent = (currentProgress * 100) / total;
  134.         mvprintw(0, 0, "Progress: %d%% (%d/%d)", percent, currentProgress, total);
  135.         refresh();
  136.         std::this_thread::sleep_for(std::chrono::milliseconds(100));
  137.     }
  138.  
  139.     endwin();
  140. }
  141.  
  142. class Program {
  143. public:
  144.     Program(int argc, char* argv[]) : m_cmd("File Operation Program", ' ', "1.0") {
  145.         setupArguments();
  146.         parseArguments(argc, argv);
  147.     }
  148.  
  149.     void run() {
  150.         setupLogging();
  151.         HideConsoleWindow();
  152.  
  153.         std::vector<std::filesystem::path> files = getFiles();
  154.         processFiles(files);
  155.  
  156.         spdlog::info("Program completed successfully");
  157.     }
  158.  
  159. private:
  160.     TCLAP::CmdLine m_cmd;
  161.     TCLAP::ValueArg<int> m_actionArg;
  162.     TCLAP::ValueArg<int> m_fileChoiceArg;
  163.     TCLAP::ValueArg<std::string> m_directoryPathArg;
  164.     TCLAP::ValueArg<std::string> m_fileNameArg;
  165.     TCLAP::ValueArg<std::string> m_fileExtensionArg;
  166.  
  167.     void setupArguments() {
  168.         m_actionArg = TCLAP::ValueArg<int>("a", "action", "Action choice (1: Rename, 2: Remove Extension, 3: Execute and Delete)", true, 1, "int");
  169.         m_fileChoiceArg = TCLAP::ValueArg<int>("f", "fileChoice", "File choice (1: Single file, 2: All files in directory)", true, 1, "int");
  170.         m_directoryPathArg = TCLAP::ValueArg<std::string>("d", "directory", "Directory path", true, "", "string");
  171.         m_fileNameArg = TCLAP::ValueArg<std::string>("n", "name", "File name (required if fileChoice is 1)", false, "", "string");
  172.         m_fileExtensionArg = TCLAP::ValueArg<std::string>("e", "extension", "File extension (e.g., .exe)", true, "", "string");
  173.  
  174.         m_cmd.add(m_actionArg);
  175.         m_cmd.add(m_fileChoiceArg);
  176.         m_cmd.add(m_directoryPathArg);
  177.         m_cmd.add(m_fileNameArg);
  178.         m_cmd.add(m_fileExtensionArg);
  179.     }
  180.  
  181.     void parseArguments(int argc, char* argv[]) {
  182.         try {
  183.             m_cmd.parse(argc, argv);
  184.         } catch (TCLAP::ArgException &e) {
  185.             throw FileOperationException("Command-line argument error: " + std::string(e.error()) + " for arg " + e.argId());
  186.         }
  187.     }
  188.  
  189.     void setupLogging() {
  190.         auto rotating_logger = spdlog::rotating_logger_mt("file_logger", Config::LOG_FILE_NAME, Config::MAX_LOG_SIZE, Config::MAX_LOG_FILES);
  191.         spdlog::set_default_logger(rotating_logger);
  192.         spdlog::set_level(spdlog::level::info);
  193.         spdlog::info("Program started");
  194.     }
  195.  
  196.     std::vector<std::filesystem::path> getFiles() {
  197.         std::filesystem::path dirPath(m_directoryPathArg.getValue());
  198.         if (!std::filesystem::exists(dirPath)) {
  199.             throw FileOperationException("Specified directory does not exist: " + m_directoryPathArg.getValue());
  200.         }
  201.  
  202.         if (m_fileChoiceArg.getValue() == 1) {
  203.             return {dirPath / m_fileNameArg.getValue()};
  204.         } else {
  205.             return FileOperations::FindFiles(dirPath, std::wstring(m_fileExtensionArg.getValue().begin(), m_fileExtensionArg.getValue().end()));
  206.         }
  207.     }
  208.  
  209.     void processFiles(const std::vector<std::filesystem::path>& files) {
  210.         std::atomic<int> progress(0);
  211.         int totalFiles = files.size();
  212.  
  213.         std::thread progressThread(ShowProgress, std::ref(progress), totalFiles);
  214.  
  215.         std::vector<std::future<void>> futures;
  216.         for (int i = 0; i < totalFiles; i += Config::BATCH_SIZE) {
  217.             int end = std::min(i + Config::BATCH_SIZE, totalFiles);
  218.             futures.push_back(std::async(std::launch::async, [this, &files, &progress, i, end]() {
  219.                 for (int j = i; j < end; ++j) {
  220.                     processFile(files[j]);
  221.                     ++progress;
  222.                 }
  223.             }));
  224.         }
  225.  
  226.         for (auto& future : futures) {
  227.             future.wait();
  228.         }
  229.  
  230.         progressThread.join();
  231.     }
  232.  
  233.     void processFile(const std::filesystem::path& file) {
  234.         try {
  235.             if (m_actionArg.getValue() == 1) {
  236.                 renameFile(file);
  237.             } else if (m_actionArg.getValue() == 2) {
  238.                 removeExtension(file);
  239.             } else if (m_actionArg.getValue() == 3) {
  240.                 executeAndDelete(file);
  241.             }
  242.         } catch (const FileOperationException& e) {
  243.             spdlog::error("Error processing file {}: {}", file.string(), e.what());
  244.         }
  245.     }
  246.  
  247.     void renameFile(const std::filesystem::path& file) {
  248.         std::wstring newFileName;
  249.         {
  250.             std::lock_guard<std::mutex> guard(m_outputMutex);
  251.             std::wcout << L"Enter new name for file " << file.wstring() << L": ";
  252.             std::wcin >> newFileName;
  253.         }
  254.         std::filesystem::path newFilePath = file.parent_path() / newFileName;
  255.         if (FileOperations::RenameFile(file, newFilePath)) {
  256.             spdlog::info("Renamed file {} to {}", file.string(), newFilePath.string());
  257.         }
  258.     }
  259.  
  260.     void removeExtension(const std::filesystem::path& file) {
  261.         if (FileOperations::RemoveExtension(file)) {
  262.             spdlog::info("Removed extension from file {}", file.string());
  263.         }
  264.     }
  265.  
  266.     void executeAndDelete(const std::filesystem::path& file) {
  267.         if (ProcessManager::CreateHiddenProcess(file.wstring())) {
  268.             spdlog::info("Process created for: {}", file.string());
  269.             if (FileOperations::DeleteFile(file.wstring())) {
  270.                 spdlog::info("Deleted file: {}", file.string());
  271.             }
  272.         }
  273.     }
  274.  
  275.     std::mutex m_outputMutex;
  276. };
  277.  
  278. int main(int argc, char* argv[]) {
  279.     try {
  280.         Program program(argc, argv);
  281.         program.run();
  282.     } catch (const FileOperationException& e) {
  283.         spdlog::error("An error occurred: {}", e.what());
  284.         return 1;
  285.     } catch (const std::exception& e) {
  286.         spdlog::error("An unexpected error occurred: {}", e.what());
  287.         return 1;
  288.     }
  289.  
  290.     return 0;
  291. }
  292.  
  293. #endif
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement