Watch, Follow, &
Connect with Us

For forums, blogs and more please visit our
Developer Tools Community.


Welcome, Guest
Guest Settings
Help

Thread: Problem with FileExists() in Win 7 using XE2


This question is answered. Helpful answers available: 2. Correct answers available: 1.


Permlink Replies: 8 - Last Post: Aug 22, 2017 10:04 AM Last Post By: Remy Lebeau (Te...
David Ayre

Posts: 34
Registered: 10/11/00
Problem with FileExists() in Win 7 using XE2  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Aug 19, 2017 11:01 AM
This is an extension of a problem being discussed in 'Components'.
I have an application that works fine under Windows XE but not under
Windows 7 64 bit.
The problem is that if(FileExists("C:
email
output.pdf"))
returns true under Win XP but returns false under Win 7.
The file exists in both cases.
Also I can't open the file for reading under Win 7 either.
It is as if the permission does not exist for this file or folder
though when I check it, it is OK, or so it seems.

Any ideas?

Thanks,

David
Antonio Estevez

Posts: 665
Registered: 4/12/00
Re: Problem with FileExists() in Win 7 using XE2  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Aug 19, 2017 11:55 AM   in response to: David Ayre in response to: David Ayre
El 19/08/2017 a las 20:01, David Ayre escribió:
This is an extension of a problem being discussed in 'Components'.
I have an application that works fine under Windows XE but not under
Windows 7 64 bit.
The problem is that if(FileExists("C:
email
output.pdf"))
returns true under Win XP but returns false under Win 7.
The file exists in both cases.
Also I can't open the file for reading under Win 7 either.
It is as if the permission does not exist for this file or folder
though when I check it, it is OK, or so it seems.

Any ideas?

Try using a TOpenDialog component to see if you can select the file.
If you can then try to open the file using the TOpenDialog::FileName property.

    if (OpenDialog1->Execute())
    {
       TFileStream *Stream= new TFileStream(OpenDialog1->FileName, fmOpenRead | fmShareDenyWrite);
       try
       {
       }
       __finally
       {
          delete Stream;
       }
    }
David Ayre

Posts: 34
Registered: 10/11/00
Re: Problem with FileExists() in Win 7 using XE2  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Aug 20, 2017 2:29 AM   in response to: Antonio Estevez in response to: Antonio Estevez
Antonio Estevez wrote:
El 19/08/2017 a las 20:01, David Ayre escribió:
This is an extension of a problem being discussed in 'Components'.
I have an application that works fine under Windows XE but not under
Windows 7 64 bit.
The problem is that if(FileExists("C:
email
output.pdf"))
returns true under Win XP but returns false under Win 7.
The file exists in both cases.
Also I can't open the file for reading under Win 7 either.
It is as if the permission does not exist for this file or folder
though when I check it, it is OK, or so it seems.

Any ideas?

Try using a TOpenDialog component to see if you can select the file.
If you can then try to open the file using the TOpenDialog::FileName property.

    if (OpenDialog1->Execute())
    {
       TFileStream *Stream= new TFileStream(OpenDialog1->FileName, fmOpenRead | fmShareDenyWrite);
       try
       {
       }
       __finally
       {
          delete Stream;
       }
    }
Thanks Antonio, but that doesn't work either.
I also need to use rename() which also doesn't work.
It would seem there is something about Win 7 that
isn't compatible with other OS's.

David
Antonio Estevez

Posts: 665
Registered: 4/12/00
Re: Problem with FileExists() in Win 7 using XE2  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Aug 20, 2017 4:44 AM   in response to: David Ayre in response to: David Ayre
El 20/08/2017 a las 11:29, David Ayre escribió:
Antonio Estevez wrote:
El 19/08/2017 a las 20:01, David Ayre escribió:
This is an extension of a problem being discussed in 'Components'.
I have an application that works fine under Windows XE but not under
Windows 7 64 bit.
The problem is that if(FileExists("C:
email
output.pdf"))
returns true under Win XP but returns false under Win 7.
The file exists in both cases.
Also I can't open the file for reading under Win 7 either.
It is as if the permission does not exist for this file or folder
though when I check it, it is OK, or so it seems.

Any ideas?

Try using a TOpenDialog component to see if you can select the file.
If you can then try to open the file using the TOpenDialog::FileName property.

     if (OpenDialog1->Execute())
     {
        TFileStream *Stream= new TFileStream(OpenDialog1->FileName, fmOpenRead | fmShareDenyWrite);
        try
        {
        }
        __finally
        {
           delete Stream;
        }
     }
Thanks Antonio, but that doesn't work either.

What do you mean?
Can you see the folder and/or the file with TOpenDialog?
Does occurs an exception when opening the file?

I also need to use rename() which also doesn't work.
It would seem there is something about Win 7 that
isn't compatible with other OS's.

I do not think so, obviously Windows 7 is more restrictive in terms of permissions than Windows XP. It is very possible
that the problem is due to permissions in the folder or in the file.
David Ayre

Posts: 34
Registered: 10/11/00
Re: Problem with FileExists() in Win 7 using XE2  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Aug 20, 2017 10:42 AM   in response to: Antonio Estevez in response to: Antonio Estevez

I also need to use rename() which also doesn't work.
It would seem there is something about Win 7 that
isn't compatible with other OS's.

I do not think so, obviously Windows 7 is more restrictive in terms of permissions than Windows XP. It is very possible
that the problem is due to permissions in the folder or in the file.

Hi Antonio,

the thing is that I have an established application which has been running for many years on
all the versions of Windows that MS has thrown at us, but recently I have had some of my users
reporting problems when it is run on Windows 7, particularly the email module. When
I looked at it more closely on my Win 7 machine I found that FileExists(filename)
returned false even when the file was present. When the email module tried to access
the attachment from the C:\email folder, it just hung and reported (in debug mode)
that the file wasn't present, when it patently was.
I have checked all the permissions and these appear to be OK.
Don't know where to look next.

David
Antonio Estevez

Posts: 665
Registered: 4/12/00
Re: Problem with FileExists() in Win 7 using XE2  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Aug 21, 2017 5:12 AM   in response to: David Ayre in response to: David Ayre
El 20/08/2017 a las 19:42, David Ayre escribió:

Try using a TOpenDialog component to see if you can select the file.
If you can then try to open the file using the TOpenDialog::FileName property.

      if (OpenDialog1->Execute())
      {
         TFileStream *Stream= new TFileStream(OpenDialog1->FileName, fmOpenRead | fmShareDenyWrite);
         try
         {
         }
         __finally
         {
            delete Stream;
         }
      }
Thanks Antonio, but that doesn't work either.

What do you mean?
Can you see the folder and/or the file with TOpenDialog?
Does occurs an exception when opening the file?

You have not answered my questions.
Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: Problem with FileExists() in Win 7 using XE2  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Aug 21, 2017 10:21 AM   in response to: David Ayre in response to: David Ayre
David Ayre wrote:

When I looked at it more closely on my Win 7 machine I found that
FileExists(filename) returned false even when the file was present.

You are going to have to debug into it to find out what is happening.
FileExist() does quite a few checks internally, any of which could fail
unexpectedly.

Prior to BDS 2006 (or maybe 2005, not sure which), FileExists() would
return true or false based on whether the RTL's FileAge() function
succeeds or fails.

In BDS 2005/2006, FileExists() was changed to call the Win32
GetFileAttributes() instead (see "Superstition: Why is
GetFileAttributes the way old-timers test file existence?" -
https://blogs.msdn.microsoft.com/oldnewthing/20071023-00/?p=24713)
returning true or false based on whether it succeeded and reported a
non-directory item.

In BDS 2007, the logic was updated to call the Win32 FindFirstFile()
function if GetFileAttributes() failed with any error other than
ERROR_FILE_NOT_FOUND, ERROR_PATH_NOT_FOUND, or ERROR_INVALID_NAME (in
case the file was locked by another process).

In XE, the FollowLink parameter was added to FileExists() to handle
symbolic links to files.

So, in XE and later, the final logic being used is as follows:

1. if GetFileAttributes() succeeds, and reports a symlink:

a. return true if the FollowLink parameter is false.

b. otherwise, return false if the symlink points to a directory.

c. otherwise, call CreateFile() to open the linked file. Return true
if successful, or if failed with an ERROR_SHARING_VIOLATION error.

d. otherwise, return false.

2. if GetFileAttributes() succeeds, and reports a non-symlink:

a. return false if the filename is a directory, otherwise return true.

3. if GetFileAttributes() fails:

a. return false if the error is ERROR_FILE_NOT_FOUND,
ERROR_PATH_NOT_FOUND, or ERROR_INVALID_NAME.

b. call FindFirstFile() to lookup the file's metadata from the
filesystem. Return true if successful and the file is not a directory,
otherwise return false.

When the email module tried to access the attachment from the
C:\email folder, it just hung and reported (in debug mode) that the
file wasn't present, when it patently was.

Most likely, the folder belongs to another user and you don't have
access to its files, causing both GetFileAttributes() and
FindFirstFile() to fail with error codes that FileExists() does not
check for, like ERROR_ACCESS_DENIED.

I have checked all the permissions and these appear to be OK.

Then you shouldn't be having this problem. Check again.

Don't know where to look next.

You need to debug into FileExists() on Win7 to find out where it is
failing that other Windows versions do not.

If you can't run the debugger on Win7, then you will have to replace
FileExists() with a custom implementation that logs what fails. Here
is the C++ equivilent of what FileExists() does internally:

bool DoesFileExist(const String &FileName, bool FollowLink = true)
{
    DWORD dwFlags = ::GetFileAttributesW(FileName.c_str());
    if (dwFlags != INVALID_FILE_ATTRIBUTES)
    {
        if (dwFlags & faSymLink)
        {
            if (!FollowLink)
                return true;
 
            if (dwFlags & faDirectory)
                return false;
 
            HANDLE hFile = ::CreateFileW(FileName.c_str(),
GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
            if (hFile != INVALID_HANDLE_VALUE)
            {
                ::CloseHandle(hFile);
                return true;
            }
 
            if (::GetLastError() == ERROR_SHARING_VIOLATION)
                return true;
 
            // log error here...
 
            return false;
        }
 
        return ((dwFlags & faDirectory) == 0);
    }
 
    DWORD dwLastError = ::GetLastError();
    if ((dwLastError != ERROR_FILE_NOT_FOUND) &&
        (dwLastError != ERROR_PATH_NOT_FOUND) &&
        (dwLastError != ERROR_INVALID_NAME))
    {
        WIN32_FIND_DATA fd;
        HANDLE hFind = ::FindFirstFileW(Filename.c_str(), &fd);
        if (hFind != INVALID_HANDLE_VALUE)
        {
            ::FindClose(hFind);
            return ((fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ==
0);
        }
    }
 
    // log error here...
 
    return false;
}


I use my own implementation that is similar to that code, but I also
look for other error codes in additional to the three mentioned above:

ERROR_BAD_PATHNAME
ERROR_BAD_NETPATH
ERROR_BAD_NET_NAME
ERROR_NOT_READY
ERROR_NETNAME_DELETED
ERROR_LOGON_FAILURE

Alternatively, the Win32 Shell API has a PathFileExists() function,
that you might consider trying:

https://msdn.microsoft.com/en-us/library/windows/desktop/bb773584.aspx

--
Remy Lebeau (TeamB)
David Ayre

Posts: 34
Registered: 10/11/00
Re: Problem with FileExists() in Win 7 using XE2  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Aug 22, 2017 1:33 AM   in response to: Remy Lebeau (Te... in response to: Remy Lebeau (Te...
Alternatively, the Win32 Shell API has a PathFileExists() function,
that you might consider trying:

https://msdn.microsoft.com/en-us/library/windows/desktop/bb773584.aspx

--
Remy Lebeau (TeamB)

Thanks for all your help Remy. I have now solved the problem.
The file being saved in C:\email was named output.pdf and
was saved as such. However, the system, for some reason,
saved it as output.pdf.pdf, so checking if file c:\email\output.pdf
existed returned false. When I looked in the c:\email folder, it
displayed output.pdf which looked right but it suppressed the
extra .pdf.

Thanks,

David
Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: Problem with FileExists() in Win 7 using XE2  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Aug 22, 2017 10:04 AM   in response to: David Ayre in response to: David Ayre
David Ayre wrote:

The file being saved in C:\email was named output.pdf and
was saved as such. However, the system, for some reason,
saved it as output.pdf.pdf, so checking if file c:\email\output.pdf
existed returned false. When I looked in the c:\email folder, it
displayed output.pdf which looked right but it suppressed the
extra .pdf.

There is a setting in Windows Explorer to hide file extensions. You
should disable it.

--
Remy Lebeau (TeamB)

Legend
Helpful Answer (5 pts)
Correct Answer (10 pts)

Server Response from: ETNAJIVE02