0

I'm looking to move a file from the directory of the current running application to another directory, but I can't seem to find a way of making it work. The code I have below was able to move the DLL I wanted, but it couldn't read the DLL properly, and it results in an error on injection (I don't get this error when I move it manually).

Also, if you have a solution in mind, i need one that can work without running as an admin.

current code:

std::ifstream src;
std::ofstream dst;
src.open("dll.dll", std::ios::in | std::ios::binary);
dst.open("C:\\subfolder \\dll.dll", std::ios::out | std::ios::binary);
dst << src.rdbuf(); 

src.close();
dst.close(); 

The best solution for me would be something like this:

CopyFile(L"dll.dll", L"C:\\subfolder\\newdll.dll", true);

But I don't know how to define the current directory.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
stefan
  • 1
  • 1
    Why not [std::filesystem::copy](https://en.cppreference.com/w/cpp/filesystem/copy)? – Ghasem Ramezani Aug 18 '21 at 23:00
  • 1
    @GhasemRamezani as its name implies, `std::filesystem::copy()` (and also `std::filesystem::copy_file()`) will **copy** the file, not **move** it. `std::filesystem::rename()` will **move** the file instead. – Remy Lebeau Aug 18 '21 at 23:36

3 Answers3

3

Unintuitively, the function that does it is called std::filesystem::rename

You can get the current directory with std::filesystem::current_path

For example, like this:

std::filesystem::rename(std::filesystem::current_path() / "dll.dll", "C:\\subfolder\\dll.dll");

NOTE:

I see the discrepancy pointed to by Remy, I was going from the question title: "Moving a file from the current directory..."

Getting the path to the current process may be OS-dependent. Found the detailed answer: Finding current executable's path without /proc/self/exe

Vlad Feinstein
  • 10,960
  • 1
  • 12
  • 27
  • can you give an example because im confused on how i can specify a specific file inside the current directory instead of just the directory itself – stefan Aug 18 '21 at 23:31
  • 2
    `std::filesystem::current_path` does not return the path of the folder where the app resides. The standard library does not have a function for that purpose. `current_path()` returns the calling process's working directory, which is a completely different concept. You need to get the app's path, such as from `argv[0]` or `GetModuleFileName(nullptr)` or equivalent, then chop off the app's filename, and then append the desired filename. – Remy Lebeau Aug 18 '21 at 23:33
  • @stefan please see updated answer for the code sample – Vlad Feinstein Aug 18 '21 at 23:34
0

You are opening the input file using just a filename by itself, so the OS will look for the file relative to the calling process's current working directory, which is not guaranteed to be pointing where you are expecting at any given moment.

If the input file is located relative to the exe, then you should obtain the exe's path first (such as from argv[0] or GetModuleFileName(nullptr) or equivalent), then replace the exe's filename with the desired filename, eg:

#include <filesystem>
#include <windows.h

char szPath[MAX_PATH] = {};
GetModuleFileName(nullptr, szPath, MAX_PATH);

std::filesystem::path inputFilePath(szPath);
inputFilePath.replace_filename("dll.dll");

std::filesystem::path outputFilePath("C:\\subfolder\\dll.dll");

And then you can use inputFilePath and outputFilePath as needed, eg:

#include <fstream>

std::ifstream src(inputFilePath, std::ios::binary);
if (src.is_open()) {
    std::ofstream dst(inputFilePath, std::ios::binary);
    if (dst.is_open()) {
        dst << src.rdbuf(); 
        dst.close(); 
    }
    else {
        // can't create output file...
    }
    src.close();
}
else {
    // can't open input file...
}
#include <filesytem>

std::error_code ec;
std::filesystem::rename(inputFilePath, outputFilePath, ec);
if (ec) {
    // can't move file...
}
#include <windows.h>

if (!MoveFileEx(inputFilePath.c_str(), outputFilePath.c_str(), MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING)) {
    // can't move file
}
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
0

How about something like the following where it takes the source file name and destination path as command line arguments.

#include <iostream>
#include <Windows.h>

std::wstring ExePath() {
    TCHAR buffer[MAX_PATH] = { 0 };
    GetModuleFileName(NULL, buffer, MAX_PATH);
    std::wstring::size_type pos = std::wstring(buffer).find_last_of(L"\\/");
    return std::wstring(buffer).substr(0, pos);
}

int wmain(int argc, wchar_t* argv[]) {

    if (argc !=3) {
        std::wcout << "Usage " << argv[0] << " [Source file current directory] [Destination]" << std::endl;
        return 1;
    }
    std::wstring file = argv[1];
    std::wstring dest = argv[2] + file;
    std::wstring full_src_path = ExePath() + L"\\" + file;

    if (MoveFileEx(full_src_path.c_str(), dest.c_str(), MOVEFILE_REPLACE_EXISTING)){
        std::wcout << "Moved " << full_src_path << " to " << dest.c_str() << std::endl;
        return 0;
    }
    else{
        DWORD err = GetLastError();
        std::wcout << "Error moving " << full_src_path << " to " << dest.c_str() << " - Error: " << err << std::endl;
        return err;
    }
}

You can run it:

movefile.exe dll.dll C:\test\

It will print either:

Moved C:\Users\test\source\repos\movefile\Debug\dll.dll to C:\test\dll.dll

or fail example:

Error moving C:\Users\test\source\repos\movefile\Debug\dll.dll to C:\test\dll.dll - Error: 2

In this case the file does not exist, error 2.

HelpingHand
  • 199
  • 1
  • 11