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.