Moving files from one directory into another - c++

I would like to copy all files from test1 into test2. The code compiles but nothing happens.
#include <iostream>
#include <stdlib.h>
#include <windows.h>
using namespace std;
int main()
{
string input1 = "C:\\test1\\";
string input2 = "C:\\test2\\";
MoveFile(input1.c_str(), input2.c_str());
}
I was considering xcopy but it would not accept a pre defined string. Is there a work around?

std::string GetLastErrorAsString()
{
//Get the error message, if any.
DWORD errorMessageID = ::GetLastError();
if (errorMessageID == 0)
return std::string(); //No error message has been recorded
LPSTR messageBuffer = nullptr;
size_t size = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, errorMessageID, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&messageBuffer, 0, NULL);
std::string message(messageBuffer, size);
//Free the buffer.
LocalFree(messageBuffer);
return message;
}
int main()
{
string input1 = "C:\\test1\\";
string input2 = "C:\\test2\\";
if (!MoveFile(input1.c_str(), input2.c_str()))
{
string msg = GetLastErrorAsString();
cout << "fail: " << msg << endl;
}
else {
cout << "ok" << endl;
}
system("pause");
}
Your code works for me, you may have to set the character set to use multi-byte character set in your project properties.
If not, provide us with the error.
Check if you have the write rights on C:.
Check if there already is a test2 folder in C: (or if there is not a test1 folder in C:).

I resovled the issue by removing the \\ from test2. Folder test 2 doesn't exist. Thank you for the replies and the test code. I think SHFileOperation will be a better option as I have to transfer files from a floppy to my C drive. string input1 = "C:\\test1\\";
string input2 = "C:\\test2";

Related

Access is denied error while moving file using MoveFileEx on Windows

I am using MoveFileEx() API to move an existing file to a new file. I'm executing below program multiple times via a script.
Below program creates a unique file on every execution, and moves it to some file, say FinalCAFile.txt.
But, for some process execution, I'm getting an "Access is denied" error.
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <string>
#include <iostream>
#include <fstream>
#include <process.h>
using namespace std;
#define BUFSIZE 1024
void PrintError(LPCTSTR errDesc,string process_id);
int main(int argc, TCHAR* argv[])
{
BOOL fSuccess = FALSE;
//Get process id to create unique file
std::string process_id = std::to_string(_getpid());
std::string tempCaFile = "C://Users//Administrator//source//repos//MyProgram//Debug//tempCAFile" + process_id + ".txt";;
std::string finalCaFile = "C://Users//Administrator//source//repos//MyProgram//Debug//FinalCAFile.txt";
//Create unique temp CA file
std::ofstream file(tempCaFile);
std::string my_string = "Hello from process " + process_id;
file << my_string;
std::wstring sourceTempCAFile = std::wstring(tempCaFile.begin(), tempCaFile.end());
std::wstring finalCAFile = std::wstring(finalCaFile.begin(), finalCaFile.end());
file.close();
//move temporary created file to FinalCAFile.txt
fSuccess = MoveFileEx(sourceTempCAFile.c_str(),
finalCAFile.c_str(),
MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH);
if (!fSuccess)
{
cout<<endl<<"\nMoveFileEx failed for"<<process_id;
file.close();
PrintError(TEXT("MoveFileEx failed"),process_id);
return (9);
}
else
{
cout << endl<<"\nMoveFileEx Success for " << process_id;
std::string passedFileName = "C://Users//Administrator//source//repos//MyProgram//Debug//PassedFile" + process_id + ".txt";
std::ofstream passedFile(passedFileName);
std::string my_string = "Passed for process id: " + process_id;
passedFile << my_string;
passedFile.close();
}
file.close();
return (0);
}
// ErrorMessage support function.
// Retrieves the system error message for the GetLastError() code.
// Note: caller must use LocalFree() on the returned LPCTSTR buffer.
LPCTSTR ErrorMessage(DWORD error, string process_id)
{
LPVOID lpMsgBuf;
//error = 5;
printf("\nDWORD=%d", (unsigned int)error);
std::string failedFileName = "C://Users//Administrator//source//repos//MyProgram//Debug//FailedFile" + process_id + ".txt";
std::ofstream failedFile(failedFileName);
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER
| FORMAT_MESSAGE_FROM_SYSTEM
| FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
error,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&lpMsgBuf,
0,
NULL);
std::string my_string = "Failed for process id: " + process_id + " due to " + std::to_string((unsigned int)error) ;
failedFile << my_string;
return((LPCTSTR)lpMsgBuf);
}
// PrintError support function.
// Simple wrapper function for error output.
void PrintError(LPCTSTR errDesc, string process_id)
{
LPCTSTR errMsg = ErrorMessage(GetLastError(), process_id);
_tprintf(TEXT("\n** ERROR ** %s: %s\n"), errDesc, errMsg);
Sleep(10000);
LocalFree((LPVOID)errMsg);
}
MyScript.bat
FOR /L %%i IN (1,1,50) DO (
start C:\Users\Administrator\source\repos\ConsoleApplication4\Debug\MyProgram.exe
)
As per my understanding, we get the "Access is denied" error if there is a write permission issue.
But here, in my case, I'm executing the same program multiple times, so I don't know how a permission issue comes into the picture.
So, there seems to be some synchronization issue.
Also, there may be the possibility that MoveFileEx() doesn't support a proper locking mechanism internally.
I doubt if there is a synchronization issue with MoveFileEx(), then others might also get this issue.
Any suggestion to avoid this issue?
This above script starts executing MyProgram.exe 50 times, and on some executions few processes are giving the "Access is denied" error.
The result is inconsistent, I don't get the error on every script run, but after 2-3 runs I'm able to get the error.

C++ How do I make it so my program wouldn't delete files that are in use?

So basically, I'm listing all of the files in my temp directory, and then deleting them. Obviously, some of the files are in use and the program itself is using the files that it's deleting. I tried fiddling around with SHFileOperation with no success. (tbh I got no idea how to use it). How do I make it check if the file is in use by another program before deleting it? Thanks!
This is giving me the error: fs::remove_all(entry.path());
Code:
#include <iostream>
#include <Windows.h>
#include <filesystem>
#include <lmcons.h>
#include <fileapi.h>
#include "cColors.h"
using namespace std;
namespace fs = filesystem;
char type;
int main()
{
SetConsoleTextAttribute(h, 15);
while (true)
{
cout << "[~] Are you sure you want to run Windows Cleaner? [Y/N]";
cin >> type;
if (type == 'n')
{
break;
exit(0);
}
else if (type == 'y')
{
cout << "[#] Cleaning temp directory\n";
for (const auto& entry : fs::directory_iterator(fs::temp_directory_path()))
{
cout << "[#] Deleting " << entry.path();
fs::remove_all(entry.path()); //This is giving me the error
}
}
else
{
break;
exit(0);
}
}
}
Here's what I came up with. A recursive delete function which uses CreateFile. My original comment
Maybe you could use CreateFile with desired access 0 and share mode OPEN_EXISTING. Then you have to check the failing reason. If it doesn't fail; close and delete.
wasn't 100% correct. dwDesiredAccess should be 0, dwShareMode should be FILE_SHARE_DELETE, dwCreationDisposition should be OPEN_EXISTING and dwFlagsAndAttributes should be FILE_FLAG_DELETE_ON_CLOSE. If then a valid handle is received the last CloseHandle on the file will lead to deletion (see here).
Here's an example:
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <tchar.h>
#include <iostream>
#include <filesystem>
#ifdef _UNICODE
auto& cout = std::wcout;
#else
using std::cout;
#endif // _UNICODE
using std::endl;
namespace fs=std::filesystem;
void deleteRecursive(const fs::path& path);
void tryDeleteFile(const fs::path& path);
int main(int argc, char* argv[])
{
TCHAR tempDir[255];
GetEnvironmentVariable(_T("TEMP"), tempDir, 255);
deleteRecursive(fs::path(tempDir));
return 0;
}
void deleteRecursive(const fs::path& path)
{
fs::directory_iterator dirs(path);
for (const auto& entry : dirs)
{
const auto& path = entry.path();
if (entry.is_directory())
{
deleteRecursive(path);
if (fs::is_empty(path))
{
if (!RemoveDirectory(path.c_str()))
{
cout << _T("Can't delete dir: ") << path << endl;
}
}
}
else
{
tryDeleteFile(path);
}
}
}
void tryDeleteFile(const fs::path& path)
{
const auto file = path.c_str();
HANDLE fileHandle = CreateFile(
file, // lpFileName,
0, // dwDesiredAccess,
FILE_SHARE_DELETE, // dwShareMode,
NULL, // lpSecurityAttributes,
OPEN_EXISTING, // dwCreationDisposition,
FILE_FLAG_DELETE_ON_CLOSE, // dwFlagsAndAttributes,
NULL // hTemplateFile
);
if (fileHandle == INVALID_HANDLE_VALUE)
{
DWORD lastErr = GetLastError();
if (lastErr != ERROR_FILE_NOT_FOUND) // gone in the mean time
{
cout << _T("Can't delete file: ") << file << endl;
}
}
else
{
CloseHandle(fileHandle);
}
}
tryDeleteFile contains the crucial part.
Catch the exception Just ignore the error and continue. Or use the second form and pass an error_code argument. Than you get no exception and you can check the reason why it failed.
If the file is in use you get an error. So you can't delete it. If you have no rights you can't delete it too.
Checking the usage first is a race condition. After the check, the file might get closed and you may be able to delete it safely. There is no difference in checking first and than delete it or trying to delete it and it fails.

Why is URLDownloadToFile() not downloading my file?

So I am trying to create a function to download a file with a variable address depending on the user with a string input using URLDownloadToFile() however it does not seem to actually download the file to the disk. It skips S_OK, E_OUTOFMEMORY and INET_E_DOWNLOAD_FAILURE to UNKNOWN_ERROR. Using GetLastError() returns 2, checking up online said that meant "Not Found". I'm not sure whether this was the website I was using or not (it's my own server with Node.JS using res.download(path, filename)). Hope for help, the code is below.
Just a note, everything is properly included as needed and the process (safely) runs with SE_DEBUG_NAME so it hopefully should not be a permission error.
// Convert String To Wide String
wstring S2WS(const string& str) {
int length;
int slength = (int)str.length() + 1;
length = MultiByteToWideChar(CP_ACP, 0, str.c_str(), slength, 0, 0);
wchar_t* buffer = new wchar_t[length];
MultiByteToWideChar(CP_ACP, 0, str.c_str(), slength, buffer, length);
wstring out(buffer);
delete[] buffer;
return out;
}
// Download File
int download(string url) {
wstring wUrl = S2WS(url);
LPCWSTR lUrl = wUrl.c_str();
TCHAR path[MAX_PATH];
GetCurrentDirectory(MAX_PATH, path);
HRESULT response = URLDownloadToFile(NULL, lUrl, path, 0, NULL);
if (response == S_OK) {
cout << "S_OK" << endl;
} else if (response == E_OUTOFMEMORY) {
cout << "E_OUTOFMEMORY" << endl;
} else if (response == INET_E_DOWNLOAD_FAILURE) {
cout << "INET_E_DOWNLOAD_FAILURE" << endl;
} else {
cout << "UNKNOWN_ERROR" << endl;
}
return 0;
}
// Example Usage
int main() {
download("http://somewebsite.com/files/textfile.txt");
}
From URLDownloadToFile, the path should be file path not a directory path. You could append some file name to the path variable and it should work.
TCHAR path[MAX_PATH];
GetCurrentDirectory(MAX_PATH, path);
wcscat_s(path, L"\\filename.txt");

C++ ifstream is_open() fails [duplicate]

This question already has answers here:
Where to place file in order to read?
(4 answers)
Closed 6 years ago.
Why does my is_open() always fail and goes into the else statement which displays the error message?
Another method of mine is similar to this yet it worked.
#include <iostream>
#include <fstream>
using namespace std;
int main() {
string userName;
cout << "Please login to your account here!" << endl;
cout << "Username: ";
cin >> userName;
ifstream openSalt;
openSalt.open("salt.txt"); //open the file
if(openSalt.is_open()) //if file is open
{
string temp;
while (getline(openSalt,temp))
{
//gets content
//if user exists, login
//else, exit
}
openSalt.close();
}
else
{
cout << "Error opening file!" << endl;
exit(1);
}
return 0;
}
Assuming code is main function etc, the code works for me.
The issue is more likely to be that what ether tool/IDE you are using to compile the program sets the current folder to a different place to what you are expecting, and then is not the place the salt.txt file is in.
Check two things.
If the file really exists in the current folder from where you program is run ?
Do you have correct permissions to open the file ?
use this function to get the error :
std::string GetLastErrorAsString()
{
//Get the error message, if any.
DWORD errorMessageID = ::GetLastError();
if (errorMessageID == 0)
return std::string(); //No error message has been recorded
LPSTR messageBuffer = nullptr;
size_t size = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, errorMessageID, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&messageBuffer, 0, NULL);
std::string message(messageBuffer, size);
//Free the buffer.
LocalFree(messageBuffer);
return message;
}
then call it in your else
else
{
cout << GetLastErrorAsString() << endl;
system("pause");
exit(1);
}
I used your code and it worked, make sure the file is in the same directory, make sure you are not working with a salt.txt.txt file (common mistake)

Winsock remote device discovery

I am new to winsock and I wish to use bluetooth for my project.
I wrote a simple code taking help from online resources to find remote devices
It should print the name of the remote devices but instead it prints some hex value I think...I dont know what that is
The code is
#include "stdafx.h"
#include<iostream>
#include<winsock2.h>
#include<ws2bth.h>
#include<bluetoothapis.h>
#include<stdlib.h>
using namespace std;
#define SUCCESS 0
#pragma comment(lib, "ws2_32.lib")
#pragma comment(lib, "irprops.lib")
int main()
{
WSADATA data;
int result;
result = WSAStartup(MAKEWORD(2, 2), &data);
if (result != SUCCESS)
{
cout << "error occured while initialising winsock...";
exit(result);
}
cout << "winsock initialisation successful\n";
WSAQUERYSET queryset;
memset(&queryset, 0, sizeof(WSAQUERYSET));
queryset.dwSize = sizeof(WSAQUERYSET);
queryset.dwNameSpace = NS_BTH;
HANDLE hLookup;
result = WSALookupServiceBegin(&queryset, LUP_CONTAINERS, &hLookup);
if (result != SUCCESS)
{
cout << "error in initialising look up service\n";
exit(result);
}
cout << "initialising lookup service successful\n";
BYTE buffer[4096];
memset(buffer, 0, sizeof(buffer));
DWORD bufferLength = sizeof(buffer);
WSAQUERYSET *pResults = (WSAQUERYSET*)&buffer;
while (result == SUCCESS)
{
result = WSALookupServiceNext(hLookup, LUP_RETURN_NAME | LUP_CONTAINERS | LUP_RETURN_ADDR | LUP_FLUSHCACHE | LUP_RETURN_TYPE | LUP_RETURN_BLOB | LUP_RES_SERVICE, &bufferLength, pResults);
if (result == SUCCESS)
{
//DEVICE FOUND
LPTSTR s = pResults->lpszServiceInstanceName;
cout << s << endl;
Sleep(1000);
}
}
WSALookupServiceEnd(hLookup);
return 0;
}
I require help in solving this issue
Thanks in advance for any help
You have a (potential) mismatch of character encodings. The line
LPTSTR s = pResults->lpszServiceInstanceName;
expands to
LPWSTR s = pResults->lpszServiceInstanceName;
if you have your project's character encoding set to Unicode (default setting). To output a Unicode string, you have to use std::wcout instead of std::cout:
LPCWSTR s = pResults->lpszServiceInstanceName;
wcout << s << endl;
To reduce the odds of inadvertently using an unexpected character encoding, code should explicitly specify the character encoding it uses. The code in the question should use WSAQUERYSETW, and call WSALookupServiceBeginW and WSALookupServiceNextW instead.
Explanation of the observed behavior:
std::cout interprets a const char* as a C-style string, and displays the characters until it finds a NUL character (see operator<<(std::basic_ostream)).
A const wchar_t*, on the other hand, is not interpreted to mean anything special. std::cout treats it like any other pointer, and prints its value using the hexadecimal numeral system by default (see std::basic_ostream::operator<<).