FileHandle = FileOpen("MyFile.txt",fmOpenReadWrite|fmShareDenyNone);
then I opened the same file later on like this to read something...
no problem, (Note: I did not close the file handle above)
FileHandle2 = FileOpen("MyFile.txt", fmOpenRead |fmShareDenyNone);
...
FileClose(FileHandle2);
Finally I have this code I am using (not my code)
and is WinAPI and try to open the file similar to the
read operation above BUT IT FAILS!!
HANDLE hf =
CreateFile("MyFile.txt",GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,0,NULL);
// returns 0xffffffff
Any suggestions on how to get the 3rd line of code to behave like the
2nd line. Or, is an int FileHandle like what you see in 2nd line the
same as the HANDLE in the third.
Colin B Maharaj
> Finally I have this code I am using (not my code)
> and is WinAPI and try to open the file similar to the
> read operation above BUT IT FAILS!!
What does GetLastError() return when CreateFile() fails? Since you are
using relative paths, not absolute paths, I ma guessing that the API code is
trying to open a file that does not actually exist.
> Or, is an int FileHandle like what you see in 2nd line the
> same as the HANDLE in the third.
Yes.
Gambit
void __fastcall TForm1::Button1Click(TObject *Sender)
{
AnsiString A = ExtractFilePath(ParamStr(0));
A += "MyFile.txt";
ShowMessage(A);
// Create the file myfile.txt in the same place as the EXE.
{
int h = FileCreate(A);
AnsiString SomeText = "The file contents\r\n";
FileWrite(h, SomeText.c_str(), SomeText.Length());
FileClose(h);
}
// open the file...
int FileHandle = FileOpen(A, fmOpenReadWrite|fmShareDenyNone);
// open it again....
int FileHandle2 = FileOpen(A, fmOpenRead |fmShareDenyNone);
FileSeek(FileHandle2, (int)0, 0);
char s[64];
FileRead(FileHandle2, s, 63);
FileClose(FileHandle2);
// close the second instance....
ShowMessage(s);
// open it using the CreateFile Winapi...and handle possible error...
HANDLE hf =
CreateFile(A.c_str(),GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,0,NULL);
if (hf == (HANDLE)0xffffffff)
{
char *lpMsgBuf;
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM,NULL,
GetLastError(),MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),(LPTSTR)
&lpMsgBuf,0,NULL);
MessageBox( NULL, lpMsgBuf, "GetLastError",
MB_OK|MB_ICONINFORMATION );
LocalFree( lpMsgBuf );
}
else
{
CloseHandle(hf);
}
// close off the initial handle....
FileClose(FileHandle);
}
//---------------------------------------------------------------------------
> if (hf == (HANDLE)0xffffffff)
Use the INVALID_HANDLE_VALUE macro instead:
if (hf == INVALID_HANDLE_VALUE)
> char *lpMsgBuf;
> FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
> FORMAT_MESSAGE_FROM_SYSTEM,NULL,
> GetLastError(),MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),(LPTSTR)
> &lpMsgBuf,0,NULL);
The VCL has a SysErrorMessage() function that does that work for you:
ShowMessage(SysErrorMessage(GetLastError()));
In any case, GetLastError() is returning ERROR_SHARING_VIOLATION (32, "The
process cannot access the file because it is being used by another
process."). Which means your call to CreateFile() is not asking for enough
sharing rights to allow it to succeed.
If you take your second call to FileOpen():
int FileHandle2 = FileOpen(A, fmOpenRead | fmShareDenyNone);
And look at how FileOpen() is implemented in SysUtils.pas (if you have the
VCL source code installed), you will see that it expands to the following
CreateFile() call:
... = CreateFile(FileName, GENERIC_READ, FILE_SHARE_READ |
FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
Notice the extra FILE_SHARE_WRITE flag? That is the key to making your code
work.
Your first call to FileOpen() specifies the fmOpenReadWrite flag:
int FileHandle = FileOpen(A, fmOpenReadWrite|fmShareDenyNone);
That expands to this:
... = CreateFile(FileName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ
| FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
Since the file is writable, any subsequent opening of the file while the
first handle is still active must specify the FILE_SHARE_WRITE flag or the
opening fails. That is why your second call to FileOpen() succeeds but your
call to CreateFile() fails.
Gambit
Thanks again Remy.