문제

I write a c program using Win32 API FindNextFile to find files

#include<stdio.h>
#include<tchar.h>
#include<windows.h>

int _tmain(int argc, TCHAR *argv[])
{
    HANDLE hNextFile;
    WIN32_FIND_DATA findFileData;
    LPCTSTR fileName = argv[1]; //input argument "C:\test\file*.txt"

    hNextFile = FindFirstFile(fileName, &findFileData);

    while(hNextFile != INVALID_HANDLE_VALUE)
    {
        printf("long name: %s\t8dot3 name: %s\n", findFileData.cFileName, findFileData.cAlternateFileName);
        hNextFile = FindNextFile(fileName, &findFileData); //Unhandled exception here!
    }
    printf("%s", GetLastError());
    return 0;
}

When call FindNextFile firstly, it throw exception. Exception info:

Unhandled exception at 0x77178dc9 in findfile.exe: 0xC0000005: Access violation writing location 0x005c0080.

Could you give me some suggestions?

Thanks in advance.


I have modified my code like this, it works fine. Thanks for Pierre's explain.

#include<stdio.h>
#include<tchar.h>
#include<windows.h>

int _tmain(int argc, TCHAR *argv[])
{
    HANDLE hNextFind;
    WIN32_FIND_DATA findFileData;
    LPCTSTR fileName = argv[1];
    BOOL result = TRUE;

    if((hNextFind = FindFirstFile(fileName, &findFileData)) == INVALID_HANDLE_VALUE)
        return 1;

    while(result)
    {
        _tprintf(TEXT("long name: %s\t8dot3 name: %s\n"), findFileData.cFileName, findFileData.cAlternateFileName);
        result = FindNextFile(hNextFind, &findFileData);
    }
    FindClose(hNextFind);
    return 0;
}
도움이 되었습니까?

해결책

You have many errors in your code.

  • First, you do not use FindNextFile correctly, the prototype :

    BOOL WINAPI FindNextFile(
      _In_   HANDLE hFindFile,
      _Out_  LPWIN32_FIND_DATA lpFindFileData
    );
    
  • After, you do not use GetLastError() correctly, who fire an Exception. GetLastError return a DWORD, you can print it as a string. (http://msdn.microsoft.com/en-us/library/ms679360(v=vs.85).aspx)

Here is an example of what your code should look like :

#include<stdio.h>
#include<tchar.h>
#include<windows.h>

int _tmain(int argc, TCHAR *argv[])
{
    HANDLE hNextFile;
    WIN32_FIND_DATA findFileData;
    LPCTSTR fileName = argv[1]; //input argument "C:\test\file*.txt"

    hNextFile = FindFirstFile(fileName, &findFileData);
    BOOL res = TRUE;
  //^^^^^^^^^^^^^^^^

    while(hNextFile != INVALID_HANDLE_VALUE && res)
    //                                      ^^^^^^
    {
        printf("long name: %s\t8dot3 name: %s\n", findFileData.cFileName, findFileData.cAlternateFileName);
        res = FindNextFile(hNextFile, &findFileData); //Unhandled exception here!
      //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    }
    printf("%d", GetLastError());
    //      ^^  // You can also use FormatMessage as it is said in the documentation
    return 0;
}

다른 팁

FindNextFile returns TRUE or FALSE, it doesn't return a HANDLE. The original handle you got from FindFirstFile remains valid until you pass it to FindClose.

hNextFile = FindFirstFile(fileName, &findFileData);
if(hNextFile != INVALID_HANDLE_VALUE)
{
    do
    {
        printf("long name: %s\t8dot3 name: %s\n", findFileData.cFileName, findFileData.cAlternateFileName);
    } while (FindNextFile(fileName, &findFileData));
    FindClose(hNextFile);
}

There are some problems in your code.

Your original code reads:

hNextFile = FindNextFile(fileName, &findFileData);

But if you check the prototype of FindNextFile(), you will find:

BOOL WINAPI FindNextFile(
  _In_   HANDLE hFindFile,
  _Out_  LPWIN32_FIND_DATA lpFindFileData
);

So, the function returns a BOOL and the first parameter is a HANDLE, which is not what you have in your code.

Moreover, you have:

printf("long name: %s\t8dot3 name: %s\n", findFileData.cFileName,
       findFileData.cAlternateFileName);

But this is not coherent with the TCHAR model that you use in other parts of your code.
To be coherent, you should use _tprintf() instead of printf(), and decorate strings using _T("...") or TEXT("..."):

// Use _tprintf() and _T("...") for coherence with TCHAR model
_tprintf(_T("long name: %s\t8dot3 name: %s\n"), 
         findFileData.cFileName, findFileData.cAlternateFileName);

Moreover, you have:

printf("%s", GetLastError());

GetLastError() returns a DWORD, which is an unsigned 32-bit integer.
But in the printf() format string you used %s, which is the placeholder for a raw C string.
Instead, you may want to use the %u format specifier (and use _tprintf() for coherence with the TCHAR model):

_tprintf(_T("Last error code: %u\n"), GetLastError());

Note that MSDN has an example on Listing the Files in a Directory.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top