Avatar of titanium0203
titanium0203

asked on 

How to use copyfile in vc6?

Hi,

Currently I can not copy files from one folder to others. I'm using copyfile but the process failed without an error.
check code snippet as below :

	LPCTSTR lpExistingFileName = "C:\\\\Product\\New\\\\product1.txt";
	LPCTSTR lpNewFileName = "C:\\\\Product\\\\Beta\\\\";

	CString msgbuf;
	CopyFile(lpExistingFileName,lpNewFileName,false);
	printf(msgbuf, "Cannot open file %s [err=%ld]\n",GetLastError());
                OutputDebugString(msgbuf);

No Error when I try to output getlasterror.

I'm using vc6.


Thanks
Editors IDEsC++.NET ProgrammingVisual C++.NET

Avatar of undefined
Last Comment
sarabande
SOLUTION
Avatar of AndyAinscow
AndyAinscow
Flag of Switzerland image

Blurred text
THIS SOLUTION IS ONLY AVAILABLE TO MEMBERS.
View this solution by signing up for a free trial.
Members can start a 7-Day free trial and enjoy unlimited access to the platform.
See Pricing Options
Start Free Trial
Avatar of titanium0203
titanium0203

ASKER

Hi,

Actually I want to copy product1.txt to folder c:\product\beta.

thanks.
Avatar of AndyAinscow
AndyAinscow
Flag of Switzerland image

You need to specify the FILE NAME to copy to.
Avatar of Todd Gerbert
Todd Gerbert
Flag of United States of America image

>> PCTSTR lpNewFileName = "C:\\\\Product\\\\Beta\\\\product1.txt";

In C, C#, C++, etc, a back-slash in a hard-coded string (i.e. a string literal) has special meaning - the backslash means "this is the start of a special code", for example to separate two words with a tab you would write "hello\tworld". If you just want a plain backslash in your string you need a way to tell the compiler "this is not the start of a special code, just put a backslash in my string" and the way you do that is to use two consecutive backslashes.  The point of all this is that your file names are being interpreted by the compiler as C:\\Product\\Beta\\product1.txt, but in Windows we normally separate path components with just a single backslash.

Your string should be C:\Product\Beta\product1.txt, and to make that string you'd write in your code: LPCTSTR lpNewFileName = "C:\\Product\\Beta\\product1.txt.

LPCTSTR lpString = "Hello\tWorld";    is    Hello    World
LPCTSTR lpString = "Hello\\World";    is    Hello\World
LPCTSTR lpString = "Hello\\\\World";  is    Hello\\World

That's probably not affecting your FileCopy, just thought I'd mention it since it seems like it may be applicable to your other question (and your other question seems like it's related to this one).
SOLUTION
Avatar of Todd Gerbert
Todd Gerbert
Flag of United States of America image

Blurred text
THIS SOLUTION IS ONLY AVAILABLE TO MEMBERS.
View this solution by signing up for a free trial.
Members can start a 7-Day free trial and enjoy unlimited access to the platform.
Avatar of Todd Gerbert
Todd Gerbert
Flag of United States of America image

>> printf(msgbuf, "Cannot open file %s [err=%ld]\n",GetLastError());

Plus, your format string has a "%s" and then a "%ld", which means you need to provide two additional arguments to (s)printf - the first one should be a string and the second one a number:

sprintf(msgbuf, "Cannot open file %s [err=%ld]\n", lpExistingFileName, GetLastError());

Open in new window

Avatar of titanium0203
titanium0203

ASKER

Hi tgerbert,

I got error below :

1. The system cannot find the path specified.

Thanks
Avatar of AndyAinscow
AndyAinscow
Flag of Switzerland image

Did you do as I initially said and supply the file name?
Avatar of titanium0203
titanium0203

ASKER

Hi,

Yes, and now I got this error :

The process cannot access the file because it is being used by another process.

Do I need to clear any buffer or close the Copyfile?

Thanks
Avatar of AndyAinscow
AndyAinscow
Flag of Switzerland image

You shouldn't need to close it, unless you have it opened in an editor elsewhere for example that is.

Simplest - do a reboot and try to run your code.
Avatar of titanium0203
titanium0203

ASKER

Hi,

I think My program cannot copy file in real time mode. The Code as below:
...
while (TRUE)
{

CString FileName = CString(Buffer[0].FileName);
CString AbsPathFileName = m_dir + "\\"+ CString(Buffer[0].FileName).Left(Buffer[0].FileNameLength / 2);

switch(Buffer[0].Action)
 {
   case FILE_ACTION_ADDED:
      printf("%s\n+: %s\n","Triggered by add", AbsPathFileName);
      ProcessFile(AbsPathFileName,FileName);
      break;
}

}//while
CloseHandle( hDir );
return 0;
}

char ProcessFile(CString AbsFileName,CString FileNm)
{
char ADir[100];
char Inipath2[255];
CString CADir = ADir;

      LPCTSTR lpExistingFileName = AbsFileName;
      strcat (ADir,FileNm);
      LPCTSTR lpNewFileName = ADir;

                                 if(CopyFile(lpExistingFileName, lpNewFileName, false) == 0)
            {
                  ShowErrorMessageDebug( GetLastError() );
            }
            else
            {
                  OutputDebugString("Copy Succeeded");
            }


      return 1;

}

When I pumped in one file to the monitored folder it return me with :
"The process cannot access the file because it is being used by another process."

Do I need to refresh the directory list, if yes could someone enhance the query above.

Thanks
Avatar of AndyAinscow
AndyAinscow
Flag of Switzerland image

CloseHandle( hDir );

Erm, what is that there for ?  Should it be before the while loop ?
Avatar of titanium0203
titanium0203

ASKER

Hi,

Sorry,

miss this line :

int ret = ReadDirectoryChangesW(hDir,&Buffer,sizeof(Buffer),TRUE,FILE_NOTIFY_CHANGE_FILE_NAME|FILE_NOTIFY_CHANGE_LAST_WRITE,&dwBytes,NULL,NULL);

It should be before :
CString FileName = CString(Buffer[0].FileName);

Thanks
Avatar of AndyAinscow
AndyAinscow
Flag of Switzerland image

Look at what you are doing and look at the error message:
"The process cannot access the file because it is being used by another process."

Now take a wild guess.  ;-)
Avatar of titanium0203
titanium0203

ASKER

Hi,

No Idea. How could I fix it?

Thanks
Avatar of AndyAinscow
AndyAinscow
Flag of Switzerland image

Weel you now inform us that there is some processing of directories going in in your app.  Don't perform any processing of the directories you are copying from/to.
Avatar of Todd Gerbert
Todd Gerbert
Flag of United States of America image

Can you post your complete code (copy/paste it so you don't miss any lines accidentally)?
Avatar of titanium0203
titanium0203

ASKER

Hi,

Please check below. Main purpose of this code is to
1. check any new/existing file pump in to the targeted folder.
2. automatically copy the new/existing files to new folder.

Regards,
titanium
#include "stdafx.h"
#include "stdio.h"
#include "WinBase.h"
#include "Windows.h"



int CheckFiles()
{
	DWORD	dwWaitStatus;
	HANDLE	dwChangeHandle;
	BOOL	fFinished = FALSE;
	char	SourceDir[100];
	int		Times=0,FailureCount=0;
	char	Inipath2[255];

	TCHAR	szBuffer[640] = {0}; 
	DWORD	dwOffset = 0;
	FILE_NOTIFY_INFORMATION* pInfo = NULL;
	DWORD	dwBytes;
	

	//Configuration file
	strcpy(Inipath2, "f:\\tracsdata\\admin.ini");



	//Source Directory
	GetPrivateProfileString("LOAD","MAINDIR","f:\\product\\beta\\",SourceDir,sizeof(SourceDir),Inipath2);

	OutputDebugString("* 2");
	OutputDebugString(SourceDir);


	FILE_NOTIFY_INFORMATION Buffer[1024];
	DWORD BytesReturned;
	

	CString m_dir("F:\\PRODUCT\\FILES");
	HANDLE hDir = CreateFile( CString(SourceDir),		// pointer to the file path 
     FILE_LIST_DIRECTORY,								// access (read/write) mode
     FILE_SHARE_READ|FILE_SHARE_WRITE,					// share mode
     NULL,												// security descriptor
     OPEN_EXISTING,										// how to create
     FILE_FLAG_BACKUP_SEMANTICS,						//|FILE_FLAG_OVERLAPPED,         // file attributes
     NULL												// file with attributes to copy
	);




	//endless loop
	while (TRUE)
	{
	
		OutputDebugString("Watch Targeted Directory");
	
			int ret = ReadDirectoryChangesW(hDir,&Buffer,sizeof(Buffer),TRUE,FILE_NOTIFY_CHANGE_FILE_NAME|FILE_NOTIFY_CHANGE_LAST_WRITE,&dwBytes,NULL,NULL);
	
			CString FileName = CString(Buffer[0].FileName);
			CString AbsPathFileName = m_dir + "\\"+ CString(Buffer[0].FileName).Left(Buffer[0].FileNameLength / 2);
		 
				 switch(Buffer[0].Action)
				 {
				   case FILE_ACTION_ADDED: 
					printf("%s\n+: %s\n","Triggered by add", AbsPathFileName);
					OutputDebugString("A");
					OutputDebugString(AbsPathFileName);
					HChange.ProcessFile(AbsPathFileName,FileName);
					break; 
				   case FILE_ACTION_REMOVED: 
					printf("%s\nx: %s\n","Triggered by removed", AbsPathFileName);
					OutputDebugString("B");
					OutputDebugString(AbsPathFileName);
					break; 
				   case FILE_ACTION_MODIFIED: 
					printf("%s\nm: %s\n","Triggered by modified", AbsPathFileName);
					OutputDebugString("C");
					OutputDebugString(AbsPathFileName);
				//	ProcessFile(filename);
					break; 
				   case FILE_ACTION_RENAMED_OLD_NAME: 
					printf("%s\n%s -> %s\n","Triggered by rename", AbsPathFileName);
					//filename = CString(Buffer[1].FileName).Left(Buffer[1].FileNameLength / 2));
					OutputDebugString(AbsPathFileName);
					break; 
				   case FILE_ACTION_RENAMED_NEW_NAME: 
					printf("%s\n -> %s\n","Triggered by rename 2", AbsPathFileName);
					OutputDebugString("E");
					OutputDebugString(AbsPathFileName);
					break;
				 }
		 
	
	}//while
	CloseHandle( hDir );
	return 0;
}

char HandleChange::ProcessFile(CString AbsPath,CString FileNm)
{
	
	char TarDir[100];
	char Inipath2[255];
	CString CLcsDir = LcsDir;
	
	strcpy(Inipath2, "f:\\tracsdata\\admin.ini");
	GetPrivateProfileString("BETA","MAINDIR","f:\\product\\release\\",TarDir,sizeof(TarDir),Inipath2);


		if(!strcmp(TarDir,"DEFAULT"))
		{
			LogFile("TarDir Not Found in INI File");
			return 0;
		}
	

		if(CLcsDir.Find("\\\\0")<0)
			CLcsDir += "\\";

	
		LPCTSTR lpExistingFileName = AbsPath;
		strcat (TarDir,FileNm);
		LPCTSTR lpNewFileName = TarDir;
		
			
		OutputDebugString("Process File");
		OutputDebugString(lpExistingFileName);
		OutputDebugString(lpNewFileName);
		OutputDebugString(FileNm);



		if(CopyFile(lpExistingFileName, lpNewFileName, false) == 0)
		{
			OutputDebugString("NOT OK");
			ShowErrorMessageDebug( GetLastError() );
		}
		else
		{
			OutputDebugString("OK");
			OutputDebugString("Copy Succeeded"); 
		}


	return 1;
}


void HandleChange::ShowErrorMessageDebug(DWORD err)
{
	TCHAR errorMessage[256];
	FormatMessage(
			FORMAT_MESSAGE_FROM_SYSTEM,
			NULL,
			err,
			NULL,
			errorMessage,
			256,
			NULL);
	OutputDebugString(errorMessage);
}

Open in new window

Avatar of titanium0203
titanium0203

ASKER

Increase Point to 300
Avatar of AndyAinscow
AndyAinscow
Flag of Switzerland image

I suggested earlier to not perform processing of the directories as you copy.  Have you tried it yet?
Avatar of sarabande
sarabande
Flag of Luxembourg image

The statement

   if(CLcsDir.Find("\\\\0")<0)

probably doesn't do what you expect.

it would search for string \\0 cause two of the backslashes were interpreted as escape characters.

if you intended to search for a final backslash (closed by right-hand zero character), you can't use a literal like "\\\0"  (note, it is 3 backslashes), cause any literal is looked from left to right for the first occurrence of a zero character '\0'. so the '\0' in the literal wasn't used for searchstring which only has one backslash and nothing else.

but the error you got has different reason: as far as i understand your code you are trying to watch a directory for file changes made by (an)other application(s). if you got such an event you take the filename and pass it as output-filename to HandleChange::ProcessFile. then you read inifile for output temp directory. the code inside the ProcessFile function is not very good. you were defining local string variables CLcsDir which wasn't used later. you use temporary LPCTSTR pointer where you assign a CString object (what could work cause CString has appropriate cast operator) but is not needed and not good code. but what you didn't consider is that the file you got from ReadDirectoryChangesW most likely exclusively is opened by the application it belongs to. if so, your CopyFile fails because of that cause you need at least read access to the file. another reason for the error you got can be that your output directory doesn't exist and will not be created from CopyFile. last possibility zoppo already mentioned is that you opened the output file yourself with some editor or similar.

Sara  
Avatar of titanium0203
titanium0203

ASKER

AndyAinscow,

How can I do that? If I disable processing of directories so many application is not in real time anymore.

sarabande,

Could you please enhance the code above?

Thanks
Avatar of AndyAinscow
AndyAinscow
Flag of Switzerland image

>>How can I do that? If I disable processing of directories so many application is not in real time anymore.

Consider.  Your current approach does NOT work as you have found out.  

Why can't the file be copied?  
Because your code is stopping it
Because another application/process is stopping it

If you tried to turn off your code when attempting the copy then
It copies - your code is at fault
It fails - another process it stopping it BUT your code still might be stopping it

Why do we try this.  Because when one finds the problem one can start solving it.  Just guessing what is the problem then making a solution might be lucky, or it might just waste a lot of time and effort.
ASKER CERTIFIED SOLUTION
Avatar of sarabande
sarabande
Flag of Luxembourg image

Blurred text
THIS SOLUTION IS ONLY AVAILABLE TO MEMBERS.
View this solution by signing up for a free trial.
Members can start a 7-Day free trial and enjoy unlimited access to the platform.
.NET Programming
.NET Programming

The .NET Framework is not specific to any one programming language; rather, it includes a library of functions that allows developers to rapidly build applications. Several supported languages include C#, VB.NET, C++ or ASP.NET.

137K
Questions
--
Followers
--
Top Experts
Get a personalized solution from industry experts
Ask the experts
Read over 600 more reviews

TRUSTED BY

IBM logoIntel logoMicrosoft logoUbisoft logoSAP logo
Qualcomm logoCitrix Systems logoWorkday logoErnst & Young logo
High performer badgeUsers love us badge
LinkedIn logoFacebook logoX logoInstagram logoTikTok logoYouTube logo