파일의 존재유무를 확인하고자 할때는 CreateFile을 사용하지 않는 것이 좋습니다.
CreateFile은 파일의 핸들을 얻어오는 함수이지 파일의 존재를 확인하는 함수가 아니기 때문입니다.

CreateFile이 핸들을 얻어오는데 실패하는 여러가지 경우가 존재합니다.

    1) 파일의 NTFS 권한이 없는 경우  (ERROR_ACCESS_DENIED)
    2) CreateFile함수의 인자에 핸들을 얻어오기 위한 적절한 권한이 설정되지 않은 경우 (ERROR_SHARING_VIOLATION)
    3) 파일이 존재하지 않는 경우 (ERROR_FILE_NOT_FOUND)
    4)  핸들 Leak이 발생하여 핸들 생성에 실패한 경우 (??)
    5) ... ??

HANDLE WINAPI CreateFile(
      __in      LPCTSTR lpFileName,
      __in      DWORD dwDesiredAccess,
      __in      DWORD dwShareMode,
      __in_opt  LPSECURITY_ATTRIBUTES lpSecurityAttributes,
      __in      DWORD dwCreationDisposition,
      __in      DWORD dwFlagsAndAttributes,
      __in_opt  HANDLE hTemplateFile
);


Visual Studio를 띄워놓은 상태에서 폴더를 복사하려고 시도하면 오류가 발생하는데 바로 3)번 관련된 상황입니다.

예를 들어 A.exe라는 프로세스가 CreateFile의 세번째 인자인 dwShareMode에 FILE_SHARE_WRITE 를 설정하여 CreateFile한 상태에서 B.exe라는 프로세스가 FILE_SHARE_READ만 준 상태에서 CreateFile을 시도하면 B.exe는 핸들을 얻어오는데 실패하게 됩니다. 요약하면 CreateFile의 두번째 인자는 반드시 세번째 인자에 포함되어야 하고, 세번째 인자는 이전에 호출된 CreateFile의 세번째 인자들을 포함해야 합니다.

아래의 MSDN을 참고하세요.

    http://msdn.microsoft.com/en-us/library/aa363858%28VS.85%29.aspx
    http://msdn.microsoft.com/en-us/library/aa363874%28VS.85%29.aspx


파일의 존재여부를 확인하고자 하신다면 다음과 같은 함수를 사용하시는게 좋습니다. 아래의 함수들은 파일의 핸들을 얻는게 아니라 Directory에 대한 읽기 작업을 통해 파일의 존재여부를 확인합니다. (따라서 파일 자체에 권한이 없어도 존재여부 확인이 가능한 반면에, 상위 디렉토리에 읽기 혹은 실행 권한이 없다면 실패할 수 있습니다.)

FindFirstFile
  - kernel32.dll에 들어있어 그냥 사용 가능하지만 얻어진 핸들에 대해 FindClose() 해주어야 함.
  - Windows2000 이상에서 지원
PathFileExists, PathIsFile, PathIsDirectory
  - 사용법이 가장 간단
  - shlwapi.h 에 들어있으며, shlwapi.lib (import library) 를 포함시켜줘야 함.
  - Windows95/98  지원

   
굳이 CreateFile을 사용하시려면,  CreateFile에 실패한 경우 GetLastError하여 실패코드가 ERROR_FILE_NOT_FOUND 인 경우에만 파일이 존재하지 않는 것으로 판단하시어 다른 조치를 취하시면 될 것 같습니다.

반면에, 만약 다른 프로세스가 먼저 Open한 파일이라도 핸들을 반드시 얻어야 한다면, 아래 코드처럼 처음부터 dwShareMode를 좀 쎄게(?) 주는 것도 방법이 될 수 있겠죠. ^^

Posted by kuaaan
,


사랑합니다. 편안히 잠드소서