trinitrotoluene
asked on
Usage of FirstFileW
Looks like this is a very basic query but pardon my ignorance. I have the following case where I find FindFirstFileW returning an invalid handle error
std::wstring fname;
fname = L"c:\be?a\*";
FindFirstFileW(fname.c_str (), ....);
I understand that this API supports wild characters but does it support wild chars in the middle?
std::wstring fname;
fname = L"c:\be?a\*";
FindFirstFileW(fname.c_str
I understand that this API supports wild characters but does it support wild chars in the middle?
you put '?' character in the middle of the fname which is illegal.
FindFirstFileW - uses wide chars.
ASKER
so the issue may not be the '?" in the middle??
Nope - that should be ok. (It is OK if you open a cmd window and perform a dir with a pattern containing a ? in the middle).
I'm not an expert on the stl but I think the c_str is the narrow char string, not the wchar that the 'W' version of the FindFirstFile is expecting
I'm not an expert on the stl but I think the c_str is the narrow char string, not the wchar that the 'W' version of the FindFirstFile is expecting
ASKER
Andy: i use c_str() to convert the wstring to an LPCWSTR
what is the error number returned?
use GetLastError(errNumberRetu rned) to get the error description
use GetLastError(errNumberRetu
OK, if the c_str does return wchars then taht bit isn't the problem
fname = L"c:\be?a\*";
should that not be:
fname = L"c:\\be?a\\*";
fname = L"c:\be?a\*";
should that not be:
fname = L"c:\\be?a\\*";
Just done a quick console app:
this fails
int _tmain(int argc, _TCHAR* argv[])
{
WIN32_FIND_DATAW x;
HANDLE hFind = FindFirstFileW(L"c:\a?d*", &x);
if (hFind == INVALID_HANDLE_VALUE)
{
printf ("Invalid File Handle. GetLastError reports %d\n",
GetLastError ());
return (0);
}
else
{
printf ("The first file found is %s\n",
x.cFileName);
FindClose(hFind);
return (1);
}
}
but this works (note the double backslash)
int _tmain(int argc, _TCHAR* argv[])
{
WIN32_FIND_DATAW x;
HANDLE hFind = FindFirstFileW(L"c:\\a?d*" , &x);
if (hFind == INVALID_HANDLE_VALUE)
{
printf ("Invalid File Handle. GetLastError reports %d\n",
GetLastError ());
return (0);
}
else
{
printf ("The first file found is %s\n",
x.cFileName);
FindClose(hFind);
return (1);
}
}
this fails
int _tmain(int argc, _TCHAR* argv[])
{
WIN32_FIND_DATAW x;
HANDLE hFind = FindFirstFileW(L"c:\a?d*",
if (hFind == INVALID_HANDLE_VALUE)
{
printf ("Invalid File Handle. GetLastError reports %d\n",
GetLastError ());
return (0);
}
else
{
printf ("The first file found is %s\n",
x.cFileName);
FindClose(hFind);
return (1);
}
}
but this works (note the double backslash)
int _tmain(int argc, _TCHAR* argv[])
{
WIN32_FIND_DATAW x;
HANDLE hFind = FindFirstFileW(L"c:\\a?d*"
if (hFind == INVALID_HANDLE_VALUE)
{
printf ("Invalid File Handle. GetLastError reports %d\n",
GetLastError ());
return (0);
}
else
{
printf ("The first file found is %s\n",
x.cFileName);
FindClose(hFind);
return (1);
}
}
It could just be nothing matches the pattern "c:\be?a\*"
Have you checked this?
"If the function fails or fails to locate files from the search string in the lpFileName parameter, the return value is INVALID_HANDLE_VALUE"
http://msdn.microsoft.com/en-us/library/aa364418(VS.85).aspx
Have you checked this?
"If the function fails or fails to locate files from the search string in the lpFileName parameter, the return value is INVALID_HANDLE_VALUE"
http://msdn.microsoft.com/en-us/library/aa364418(VS.85).aspx
ASKER
folks thanks for the suggestions.
Will try it out and let you know. The file definitely exists so I guess its something to do with my searchstring
Will try it out and let you know. The file definitely exists so I guess its something to do with my searchstring
>> The file definitely exists so I guess its something to do with my searchstring
The file may exist but (as you elude) the glob pattern may not match it. A quick call to GetLastError() will confirm this (or not).
http://msdn.microsoft.com/en-us/library/ms679360(v=VS.85).aspx
The file may exist but (as you elude) the glob pattern may not match it. A quick call to GetLastError() will confirm this (or not).
http://msdn.microsoft.com/en-us/library/ms679360(v=VS.85).aspx
ASKER
andy:
the // works but doesn't return the first file in the directory rather it returns the directory name.
for eg.
have a directory as c:\dir3 and try the below
HANDLE hFind = FindFirstFileW(L"c:\\d?r3* ", &x);
you will get dir3 as the filename. Is this expected behaviour. I was expecting the first file in the directory?
the // works but doesn't return the first file in the directory rather it returns the directory name.
for eg.
have a directory as c:\dir3 and try the below
HANDLE hFind = FindFirstFileW(L"c:\\d?r3*
you will get dir3 as the filename. Is this expected behaviour. I was expecting the first file in the directory?
Why as a file name? The function return names of the files and subdirectories.
http://msdn.microsoft.com/en-us/library/aa364418(VS.85).aspx
When you have the name you can check with GetFileAttributes if this is a directory: FILE_ATTRIBUTE_DIRECTORY.
Here is an example with FindFirstFile and GetFileAttribute:
http://msdn.microsoft.com/en-us/library/aa365522(v=VS.85).aspx
http://msdn.microsoft.com/en-us/library/aa364418(VS.85).aspx
When you have the name you can check with GetFileAttributes if this is a directory: FILE_ATTRIBUTE_DIRECTORY.
Here is an example with FindFirstFile and GetFileAttribute:
http://msdn.microsoft.com/en-us/library/aa365522(v=VS.85).aspx
OK, I've done a further change
int _tmain(int argc, _TCHAR* argv[])
{
std::wstring s = L"c:\\a?t*";
WIN32_FIND_DATAW x;
HANDLE hFind = FindFirstFileW(s.c_str(), &x);
if (hFind == INVALID_HANDLE_VALUE)
{
wprintf (L"Invalid File Handle. GetLastError reports %d\n",
GetLastError ());
return (0);
}
else
{
wprintf (L"The first file found is %s\n",
x.cFileName);
FindClose(hFind);
return (1);
} return 0;
}
There are no directories and only one file that matches the pattern - the file is found and the name printed out to the console.
int _tmain(int argc, _TCHAR* argv[])
{
std::wstring s = L"c:\\a?t*";
WIN32_FIND_DATAW x;
HANDLE hFind = FindFirstFileW(s.c_str(), &x);
if (hFind == INVALID_HANDLE_VALUE)
{
wprintf (L"Invalid File Handle. GetLastError reports %d\n",
GetLastError ());
return (0);
}
else
{
wprintf (L"The first file found is %s\n",
x.cFileName);
FindClose(hFind);
return (1);
} return 0;
}
There are no directories and only one file that matches the pattern - the file is found and the name printed out to the console.
Just one 'minor' point. I hope you are looping through ALL the files returned to check, they are NOT sorted the way they are with a dir command.
ASKER
AndyA
I understand what you are trying to tell me. Its not an issue with string conversions. I guess i didn't explain my scenario properly
I have the following directory structure
C:\Dir3
In Dir3 I could be having several files/folders
I get a string pattern from another module "C:\Di?3*" and I am expected to find the C:\Dir3 and also list out all the files and folders inside Dir3.
What happens is that FindFirstFileW(L"C:\Di?3*" , ...) returns Dir3 and not the files/folders within C:\Dir3.
Now doing a FindNextFileW() is inconsequential and it just bumps out.
I hope you understand the situation now. All I want you folks to confirm is that the Win API is working correctly and I might need to add special logic of my own to handle this weird case
I understand what you are trying to tell me. Its not an issue with string conversions. I guess i didn't explain my scenario properly
I have the following directory structure
C:\Dir3
In Dir3 I could be having several files/folders
I get a string pattern from another module "C:\Di?3*" and I am expected to find the C:\Dir3 and also list out all the files and folders inside Dir3.
What happens is that FindFirstFileW(L"C:\Di?3*"
Now doing a FindNextFileW() is inconsequential and it just bumps out.
I hope you understand the situation now. All I want you folks to confirm is that the Win API is working correctly and I might need to add special logic of my own to handle this weird case
From my point of view Win32 API works properly. Actually, it does not matter - I need my app to work properly. For your case, I think, it should be L"C:\Di?3*\*.*".
ASKER
pgnatyuk: thats not the expression I get from the other module. I cannot assume its a directory and add \*.* at the end.
all I get from the other module is C:\Di?r* or maybe C:\D?or or maybe C:\Dir* and I am supposed to handle all the cases
all I get from the other module is C:\Di?r* or maybe C:\D?or or maybe C:\Dir* and I am supposed to handle all the cases
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
>>pgnatyuk: thats not the expression I get from the other module. I cannot assume its a directory and add \*.* at the end.
You don't need to assume. You may check the names you get from the FindFirstFile are directories or files with GetFileAttribute.
Maybe you can formulate the task?
Seems like you already understand FindFirstFile function.
You don't need to assume. You may check the names you get from the FindFirstFile are directories or files with GetFileAttribute.
Maybe you can formulate the task?
Seems like you already understand FindFirstFile function.
ASKER
Thats right Andy!
What happens is that FindFirstFileW(L"C:\Di?3*" , ...) returns Dir3 and not the file/folders within C:\Dir3 as would have been the case if i had used FindFirstFileW(L"C:\\Dir3" , ...) so in this case I would have had to determine whether its a file/directory and then proceed further
What happens is that FindFirstFileW(L"C:\Di?3*"
From the help files - Retrieving and Changing File Attributes
#include <windows.h>
#include <stdio.h>
void main()
{
WIN32_FIND_DATA FileData;
HANDLE hSearch;
DWORD dwAttrs;
TCHAR szDirPath[] = TEXT("c:\\TextRO\\");
TCHAR szNewPath[MAX_PATH];
BOOL fFinished = FALSE;
// Create a new directory.
if (!CreateDirectory(szDirPath, NULL))
{
printf("Could not create new directory.\n");
return;
}
// Start searching for text files in the current directory.
hSearch = FindFirstFile(TEXT("*.txt"), &FileData);
if (hSearch == INVALID_HANDLE_VALUE)
{
printf("No text files found.\n");
return;
}
// Copy each .TXT file to the new directory
// and change it to read only, if not already.
while (!fFinished)
{
lstrcpy(szNewPath, szDirPath);
lstrcat(szNewPath, FileData.cFileName);
if (CopyFile(FileData.cFileName, szNewPath, FALSE))
{
dwAttrs = GetFileAttributes(FileData.cFileName);
if (dwAttrs==INVALID_FILE_ATTRIBUTES) return;
if (!(dwAttrs & FILE_ATTRIBUTE_READONLY))
{
SetFileAttributes(szNewPath,
dwAttrs | FILE_ATTRIBUTE_READONLY);
}
}
else
{
printf("Could not copy file.\n");
return;
}
if (!FindNextFile(hSearch, &FileData))
{
if (GetLastError() == ERROR_NO_MORE_FILES)
{
printf("Copied all text files.\n");
fFinished = TRUE;
}
else
{
printf("Could not find next file.\n");
return;
}
}
}
// Close the search handle.
FindClose(hSearch);
}
One of the possible attributes is: FILE_ATTRIBUTE_DIRECTORY
ASKER
Helped in stimulating my grey cells. Sorry about the long delay. Got mired in work