Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 369
  • Last Modified:

FindFirstFile and SHFileOperation

I have a simple little code snippet that checks two files last write date/time to see whether they are different. If they are (or the Local doesn't exist), the code should then copy the Network copy over the local.

I am having two problems:
   1) The program is ALWAYS copying the file.
   2) The SHFileOperation sometimes comes back with it can't copy 'xxxx' file where 'xxxx' is just some stray garbage.

Here is the code snippet. Any suggestions?

      // create the paths to the database
      CString LocalDatabasePath,NetworkDatabasePath;
      if (CSPECFileName.IsEmpty()) NetworkDatabasePath = (LimitsDatabasePath + "\\Limits");
      else NetworkDatabasePath = (LimitsDatabasePath + "\\" + CSPECFileName);
      if (CSPECFileName.IsEmpty()) LocalDatabasePath = (LocalDataPath + "\\Limits");
      else LocalDatabasePath = (LocalDataPath + "\\" + CSPECFileName);

      // find file and get it's info (display error if we get invalid handles)
      WIN32_FIND_DATA NetFileInfo,LocFileInfo;
      if ((FindFirstFile((NetworkDatabasePath + ".dbf"),&NetFileInfo) == INVALID_HANDLE_VALUE) &&
            (FindFirstFile((LocalDatabasePath + ".dbf"),&LocFileInfo) == INVALID_HANDLE_VALUE))
            AfxMessageBox("Unable To Open Network Or Local Limits Files.\nNetwork Not Available Or Paths Incorrect.",
                  MB_OK | MB_ICONEXCLAMATION);
      // if we get good net handle and the file dates do not match, copy the net to the local
      else if (NetworkStatus)
            {
            if (NetFileInfo.ftLastWriteTime.dwLowDateTime != LocFileInfo.ftLastWriteTime.dwLowDateTime ||
                  NetFileInfo.ftLastWriteTime.dwHighDateTime != LocFileInfo.ftLastWriteTime.dwHighDateTime)
                  {
                  SHFILEOPSTRUCT sfo;
                  memset(&sfo,0,sizeof(sfo));
                  sfo.hwnd = ::GetTopWindow(NULL);
                  sfo.wFunc = FO_COPY;
                  sfo.pFrom = (NetworkDatabasePath + ".*\0\0");
                  sfo.pTo = (LocalDataPath + "\0\0");
                  sfo.fFlags = FOF_NOCONFIRMATION | FOF_SIMPLEPROGRESS;
                  sfo.lpszProgressTitle = ("Copying Modified Limits Database Files - Please Wait...");
                  ::SHFileOperation(&sfo);
                  }
            }
0
maknight
Asked:
maknight
  • 5
  • 4
  • 3
1 Solution
 
jtwine100697Commented:
  At first glance (I am tired), I do not know why the files is always being copied, but here is a guess for your "garbage filenames xxx" problem:

   When you use (CString + "constant") you are creating a temporary object.  Try storing composite filenames in a seperate CString object, AND putting NULLs into a CString tends to confuse the CString class.  Try using a regular char buffer.

-=- James.
0
 
jtwine100697Commented:
Two more things:

   o  You should be storing the HANDLE returned by FindFirstFile(...) to use with FindClose(...) later on.

   o  Check the ftLastWriteTime structures for both the remote and the local file:  If any of them they are zero (initalize them first with ZeroMemory(...) ), it means that the times could not be obtained.

-=- James.
0
 
chensuCommented:
There is a logical error in your code.

Look at
if ((FindFirstFile((NetworkDatabasePath + ".dbf"),&NetFileInfo) == INVALID_HANDLE_VALUE) && 
(FindFirstFile((LocalDatabasePath + ".dbf"),&LocFileInfo) == INVALID_HANDLE_VALUE))

Shouldn't you use || instead of &&?
0
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

 
jtwine100697Commented:
  chensu...  Yes, there is a logical error in his error checking, and he would need still further (more robust) error checking to make it right, but that answers neither of his questions.

-=- James.
0
 
chensuCommented:
jtwine,

I should have indicated that this error is likely to cause those two problems if only one of the FindFirstFile() functions returns INVALID_HANDLE_VALUE.
0
 
maknightAuthor Commented:
I am aware of the  of the lack of robust error-checking. That in itself should not cause the failure altogether of FindFirstFile to get the correct LastWriteTime. Added robustness is a secondary issue I'll resolve once the core code functions.

The && is correct since I am looking for the case when both files are not available- meaning the system cannot continue (handled elsewhere). The additional conditions in the else just make sure that at least the network copy is available for copying.

Let me look over your comments further and see if they point the way. I think I'm running into a NetWare issue (network file) since my local file is returning the LastWriteTime data properly.
0
 
maknightAuthor Commented:
jtwine, Got your first comment taken care of. I knew that about CString. Guess I was tired yesterday as well...
0
 
chensuCommented:
I don't think the usage of CString causes any problems. Yes, it is a temporary object. But it is alive as long as the execution does not go out of the scope. Using a regular char buffer is the same unless you use a global or static char buffer. The best way is to debug it carefully. Use TRACE and ASSERT liberally. They will help you avoid many problems.
0
 
maknightAuthor Commented:
I removed the TRACE and ASSERT statements from what I posted to make it cleaner for you folks here to read. They tend to clutter code sometimes <g>. Once I changed the two CStrings in the SHFILEOPSTRUCT to char SomeVar[Max_Path] that problem went away. The double NULL (\0\0) was seemingly driving it nuts. It was a soft drive to insanity b/c it would never really trap anything I could put in to try to trap it, but nonetheless it was going nuts.
0
 
maknightAuthor Commented:
Everything appears to be functioning well now. Thanks.
0
 
chensuCommented:
You should have rejected my answer and given the points to jtwine since he did mention "putting NULLs into a CString tends to confuse the CString class". I didn't notice the double NULL problem.
0
 
maknightAuthor Commented:
Oops! Actually I didn't look to see who had it locked. Assumed the first to respond had locked it, but jtwine had only commented. Sorry, James. Thanks both.

About CString: It's nice, but it can also be a pain in the rear end sometimes since it seems several things can confuse it.
0

Featured Post

What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

  • 5
  • 4
  • 3
Tackle projects and never again get stuck behind a technical roadblock.
Join Now