stefan
stefan

Reputation: 1

Moving a file from the current directory to a new location

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.

Upvotes: 0

Views: 1172

Answers (3)

HelpingHand
HelpingHand

Reputation: 209

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.

Upvotes: 0

Remy Lebeau
Remy Lebeau

Reputation: 596111

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
}

Upvotes: 0

Vlad Feinstein
Vlad Feinstein

Reputation: 11311

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

Upvotes: 3

Related Questions