Reputation: 1
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
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
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
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