c++winapic++builderc++builder-6

CopyFile API function not working after using GetOpenFileName to get the file path


I am using GetOpenFileName() to get the file path, and then CopyFile() to copy the file to the same directory with a different file name.

By using GetLastError(), I am getting an error code:

0x2 - The system cannot find the file specified.

But when I used MessageBox() to see the file names, it showed the correct file names.

In addition to this, I have also tried to StrTrim() the file name, but still it did not work.

I am using Borland C++Builder 6.0.


CODE

OPENFILENAME ofn;
char szFile[260];
ZeroMemory(&ofn, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner =  Form1->Handle;
ofn.lpstrFile = szFile;
ofn.lpstrFile[0] = '\0';
ofn.nMaxFile = sizeof(szFile);
ofn.lpstrFilter = "All\0*.*\0Text\0*.txt\0";
ofn.nFilterIndex = 1;
ofn.lpstrFileTitle = NULL;
ofn.nMaxFileTitle = 0;
ofn.lpstrInitialDir = NULL;
ofn.Flags = 0;
GetOpenFileName(&ofn);

LPSTR FileName;
FileName = ofn.lpstrFile;
MessageBox (Form1->Handle, FileName, "File Name", MB_OK);
MessageBox (Form1->Handle, strcat(FileName, ".newfile"), "New File Name", MB_OK);
CopyFile(FileName, strcat(FileName,".newfile"), false);

EDITED CODE

I have tried using two variables, but it is still not working. Can anyone suggest a correction?

LPSTR FileName;
LPSTR NewFileName;
FileName = ofn.lpstrFile;
NewFileName = FileName;
strcat(NewFileName, ".newfile");
MessageBox (Form1->Handle, FileName, "File Name", MB_OK);
MessageBox (Form1->Handle, NewFileName, "New File Name", MB_OK);
CopyFile(FileName, NewFileName, false);

WORKING CODE

The below code works, but I had to add a Text Box / Edit Control. Is there way to do it without adding any extra control?

LPSTR FileName;
AnsiString NewFileName;
FileName = ofn.lpstrFile;
Edit1->Text = FileName;
NewFileName = Edit1->Text + ".bak";
MessageBox (Form1->Handle, FileName, "File Name", MB_OK);
MessageBox (Form1->Handle, NewFileName.c_str(), "New File Name", MB_OK);

Solution

  • You are using a single buffer for both arguments of CopyFile(), and you are appending the new extension to that buffer, so of course CopyFile() is not going to find the file to copy.

    You need to use two separate buffers for the two arguments of CopyFile(), eg:

    TCHAR szSrcFile[MAX_PATH];
    TCHAR szDstFile[MAX_PATH+12];
    
    OPENFILENAME ofn;
    ZeroMemory(&ofn, sizeof(ofn)); ofn.lStructSize = sizeof(ofn);
    ofn.hwndOwner = Form1->Handle;
    ofn.lpstrFile = szSrcFile;
    ofn.lpstrFile[0] = TEXT('\0');
    ofn.nMaxFile = MAX_PATH;
    ofn.lpstrFilter = TEXT("All\0*.*\0Text\0*.txt\0");
    ofn.nFilterIndex = 1;
    ofn.lpstrFileTitle = NULL;
    ofn.nMaxFileTitle = 0;
    ofn.lpstrInitialDir = NULL;
    ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
    
    if (GetOpenFileName(&ofn))
    {    
        lstrcpy(szDstFile, szSrcFile);
        lstrcat(szDstFile, TEXT(".newfile"));
        MessageBox(Form1->Handle, szSrcFile, TEXT("File Name"), MB_OK);    
        MessageBox(Form1->Handle, szDstFile, TEXT("New File Name"), MB_OK);
        CopyFile(szSrcFile, szDstFile, FALSE);
     }
    

    That being said, since you are using Borland's VCL framework, you should use the TOpenDialog component instead of GetOpenFileName() directly, and then you can use String variables for easy concatenation:

    // these properties can also be set at design-time instead...
    OpenDialog1->Filter = "All|*.*|Text|*.txt";
    OpenDialog1->FilterIndex = 1;
    OpenDialog1->Options = TOpenOptions() << ofPathMustExist << ofFileMustExist;
    
    if (OpenDialog1->Execute())
    {
        String SrcFile = OpenDialog1->FileName;
        String DstFile = SrcFile + ".newfile";
        CopyFileA(SrcFile.c_str(), DstFile.c_str(), FALSE);
    }