Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #ifndef FILE_OPERATIONS_H
- #define FILE_OPERATIONS_H
- #include <iostream>
- #include <string>
- #include <Windows.h>
- #include <random>
- #include <filesystem>
- #include <fstream>
- #include <memory>
- #include <vector>
- #include <thread>
- #include <mutex>
- #include <spdlog/spdlog.h>
- #include <spdlog/sinks/rotating_file_sink.h>
- #include <atomic>
- #include <tclap/CmdLine.h>
- #include <ncurses.h>
- #include <thread>
- #include <future>
- class FileOperationException : public std::exception {
- public:
- FileOperationException(const std::string& message) : m_message(message) {}
- const char* what() const noexcept override { return m_message.c_str(); }
- private:
- std::string m_message;
- };
- class Config {
- public:
- static const int MAX_RETRIES = 3;
- static const int THREAD_POOL_SIZE = 4;
- static const int BATCH_SIZE = 10;
- static const std::string LOG_FILE_NAME;
- static const int MAX_LOG_SIZE;
- static const int MAX_LOG_FILES;
- };
- const std::string Config::LOG_FILE_NAME = "program_log.txt";
- const int Config::MAX_LOG_SIZE = 1024 * 1024; // 1 MB
- const int Config::MAX_LOG_FILES = 5;
- class FileOperations {
- public:
- static std::vector<std::filesystem::path> FindFiles(const std::filesystem::path& directoryPath, const std::wstring& extension) {
- std::vector<std::filesystem::path> files;
- try {
- for (const auto& entry : std::filesystem::directory_iterator(directoryPath)) {
- if (entry.path().extension() == extension) {
- files.push_back(entry.path());
- }
- }
- } catch (const std::filesystem::filesystem_error& e) {
- throw FileOperationException("Error accessing directory " + directoryPath.string() + ": " + e.what());
- }
- return files;
- }
- static bool DeleteFile(const std::wstring& filePath) {
- for (int i = 0; i < Config::MAX_RETRIES; ++i) {
- if (::DeleteFileW(filePath.c_str()) != 0) {
- return true;
- }
- spdlog::warn("Retrying deletion of file: {}", std::string(filePath.begin(), filePath.end()));
- std::this_thread::sleep_for(std::chrono::milliseconds(100));
- }
- throw FileOperationException("Failed to delete file after " + std::to_string(Config::MAX_RETRIES) + " retries: " + std::string(filePath.begin(), filePath.end()));
- }
- static bool RenameFile(const std::filesystem::path& filePath, const std::filesystem::path& newFilePath) {
- try {
- std::filesystem::rename(filePath, newFilePath);
- return true;
- } catch (const std::filesystem::filesystem_error& e) {
- throw FileOperationException("Failed to rename file " + filePath.string() + ": " + e.what());
- }
- }
- static bool RemoveExtension(const std::filesystem::path& filePath) {
- std::filesystem::path newFilePath = filePath;
- newFilePath.replace_extension();
- return RenameFile(filePath, newFilePath);
- }
- };
- class ProcessManager {
- public:
- static bool CreateHiddenProcess(const std::wstring& executablePath) {
- STARTUPINFOW si{};
- PROCESS_INFORMATION pi{};
- si.cb = sizeof(si);
- si.dwFlags = STARTF_USESHOWWINDOW;
- si.wShowWindow = SW_HIDE;
- for (int i = 0; i < Config::MAX_RETRIES; ++i) {
- if (CreateProcessW(executablePath.c_str(), NULL, NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi)) {
- CloseHandle(pi.hProcess);
- CloseHandle(pi.hThread);
- return true;
- }
- spdlog::warn("Retrying creation of process for: {}", std::string(executablePath.begin(), executablePath.end()));
- std::this_thread::sleep_for(std::chrono::milliseconds(100));
- }
- throw FileOperationException("Failed to create process after " + std::to_string(Config::MAX_RETRIES) + " retries: " + std::string(executablePath.begin(), executablePath.end()));
- }
- };
- void HideConsoleWindow() {
- HWND hwnd = GetConsoleWindow();
- if (hwnd != NULL) {
- ShowWindow(hwnd, SW_HIDE);
- } else {
- throw FileOperationException("Failed to get console window handle");
- }
- }
- bool is_valid_choice(int choice, int min, int max) {
- return choice >= min && choice <= max;
- }
- void ShowProgress(std::atomic<int>& progress, int total) {
- initscr();
- cbreak();
- noecho();
- nodelay(stdscr, TRUE);
- curs_set(0);
- while (progress < total) {
- clear();
- int currentProgress = progress.load();
- int percent = (currentProgress * 100) / total;
- mvprintw(0, 0, "Progress: %d%% (%d/%d)", percent, currentProgress, total);
- refresh();
- std::this_thread::sleep_for(std::chrono::milliseconds(100));
- }
- endwin();
- }
- class Program {
- public:
- Program(int argc, char* argv[]) : m_cmd("File Operation Program", ' ', "1.0") {
- setupArguments();
- parseArguments(argc, argv);
- }
- void run() {
- setupLogging();
- HideConsoleWindow();
- std::vector<std::filesystem::path> files = getFiles();
- processFiles(files);
- spdlog::info("Program completed successfully");
- }
- private:
- TCLAP::CmdLine m_cmd;
- TCLAP::ValueArg<int> m_actionArg;
- TCLAP::ValueArg<int> m_fileChoiceArg;
- TCLAP::ValueArg<std::string> m_directoryPathArg;
- TCLAP::ValueArg<std::string> m_fileNameArg;
- TCLAP::ValueArg<std::string> m_fileExtensionArg;
- void setupArguments() {
- m_actionArg = TCLAP::ValueArg<int>("a", "action", "Action choice (1: Rename, 2: Remove Extension, 3: Execute and Delete)", true, 1, "int");
- m_fileChoiceArg = TCLAP::ValueArg<int>("f", "fileChoice", "File choice (1: Single file, 2: All files in directory)", true, 1, "int");
- m_directoryPathArg = TCLAP::ValueArg<std::string>("d", "directory", "Directory path", true, "", "string");
- m_fileNameArg = TCLAP::ValueArg<std::string>("n", "name", "File name (required if fileChoice is 1)", false, "", "string");
- m_fileExtensionArg = TCLAP::ValueArg<std::string>("e", "extension", "File extension (e.g., .exe)", true, "", "string");
- m_cmd.add(m_actionArg);
- m_cmd.add(m_fileChoiceArg);
- m_cmd.add(m_directoryPathArg);
- m_cmd.add(m_fileNameArg);
- m_cmd.add(m_fileExtensionArg);
- }
- void parseArguments(int argc, char* argv[]) {
- try {
- m_cmd.parse(argc, argv);
- } catch (TCLAP::ArgException &e) {
- throw FileOperationException("Command-line argument error: " + std::string(e.error()) + " for arg " + e.argId());
- }
- }
- void setupLogging() {
- auto rotating_logger = spdlog::rotating_logger_mt("file_logger", Config::LOG_FILE_NAME, Config::MAX_LOG_SIZE, Config::MAX_LOG_FILES);
- spdlog::set_default_logger(rotating_logger);
- spdlog::set_level(spdlog::level::info);
- spdlog::info("Program started");
- }
- std::vector<std::filesystem::path> getFiles() {
- std::filesystem::path dirPath(m_directoryPathArg.getValue());
- if (!std::filesystem::exists(dirPath)) {
- throw FileOperationException("Specified directory does not exist: " + m_directoryPathArg.getValue());
- }
- if (m_fileChoiceArg.getValue() == 1) {
- return {dirPath / m_fileNameArg.getValue()};
- } else {
- return FileOperations::FindFiles(dirPath, std::wstring(m_fileExtensionArg.getValue().begin(), m_fileExtensionArg.getValue().end()));
- }
- }
- void processFiles(const std::vector<std::filesystem::path>& files) {
- std::atomic<int> progress(0);
- int totalFiles = files.size();
- std::thread progressThread(ShowProgress, std::ref(progress), totalFiles);
- std::vector<std::future<void>> futures;
- for (int i = 0; i < totalFiles; i += Config::BATCH_SIZE) {
- int end = std::min(i + Config::BATCH_SIZE, totalFiles);
- futures.push_back(std::async(std::launch::async, [this, &files, &progress, i, end]() {
- for (int j = i; j < end; ++j) {
- processFile(files[j]);
- ++progress;
- }
- }));
- }
- for (auto& future : futures) {
- future.wait();
- }
- progressThread.join();
- }
- void processFile(const std::filesystem::path& file) {
- try {
- if (m_actionArg.getValue() == 1) {
- renameFile(file);
- } else if (m_actionArg.getValue() == 2) {
- removeExtension(file);
- } else if (m_actionArg.getValue() == 3) {
- executeAndDelete(file);
- }
- } catch (const FileOperationException& e) {
- spdlog::error("Error processing file {}: {}", file.string(), e.what());
- }
- }
- void renameFile(const std::filesystem::path& file) {
- std::wstring newFileName;
- {
- std::lock_guard<std::mutex> guard(m_outputMutex);
- std::wcout << L"Enter new name for file " << file.wstring() << L": ";
- std::wcin >> newFileName;
- }
- std::filesystem::path newFilePath = file.parent_path() / newFileName;
- if (FileOperations::RenameFile(file, newFilePath)) {
- spdlog::info("Renamed file {} to {}", file.string(), newFilePath.string());
- }
- }
- void removeExtension(const std::filesystem::path& file) {
- if (FileOperations::RemoveExtension(file)) {
- spdlog::info("Removed extension from file {}", file.string());
- }
- }
- void executeAndDelete(const std::filesystem::path& file) {
- if (ProcessManager::CreateHiddenProcess(file.wstring())) {
- spdlog::info("Process created for: {}", file.string());
- if (FileOperations::DeleteFile(file.wstring())) {
- spdlog::info("Deleted file: {}", file.string());
- }
- }
- }
- std::mutex m_outputMutex;
- };
- int main(int argc, char* argv[]) {
- try {
- Program program(argc, argv);
- program.run();
- } catch (const FileOperationException& e) {
- spdlog::error("An error occurred: {}", e.what());
- return 1;
- } catch (const std::exception& e) {
- spdlog::error("An unexpected error occurred: {}", e.what());
- return 1;
- }
- return 0;
- }
- #endif
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement