2016-04-08 5 views
0

Когда я выполняю этот код без пакетов времени выполнения, у меня есть ошибка кода 32, это правильно. Но когда я activité пакеты времени выполнения (для Exemple только с «FireDACASADriver; YmagControlDB») код ошибки всегда «0»Delphi GetLastError с пакетами выполнения

procedure TForm1.Button1Click(Sender: TObject); 
Var 
    Stream: TStream; 
    iError : integer; 
begin 
    Stream := nil; 
    iError := -1; 
    try 
     try 
     Stream := TFileStream.Create('d:\toto.docx', fmOpenRead); 
     except 
     begin 
      iError := GetLastError; 
     end; 
     end; 
    finally 
     if Assigned(Stream) then 
     Stream.Free; 
    end; 
    showmessage('Erreur : ' + inttostr(iError)); 
end; 

Как я могу исправить GetLastError с пакетами во время выполнения?

ответ

4

Нет необходимости звонить по телефону GetLastError. Вы смешиваете две разные модели обработки ошибок.

Звоните GetLastError сразу же после вызова API, если в документации говорится об этом. Когда вы его назовете, что-то другое может быть очень хорошо вызвано SetLastError и сбросить значение.

Неправильно позвонить GetLastError, так как вы не используете функции Win32 и должны удалить звонок до GetLastError. Ваш код должен быть:

procedure TForm1.Button1Click(Sender: TObject); 
var 
    Stream: TStream; 
begin 
    Stream := TFileStream.Create('d:\toto.docx', fmOpenRead); 
    try 
    // ....  
    finally 
    Stream.Free; 
    end; 
end; 

Если есть ошибка, исключение будет поднято, который будет сообщен обработчиком исключений верхнего уровня.

Временные пакеты не должны влиять на выполнение этого кода.

Возможные причины ошибки в том, что файл не существует или он заблокирован.

Вы писали:

if Assigned(Stream) then 
    Stream.Free; 

Это всегда бессмысленно, так как метод Free также проверяет ссылка на объект является nil. На самом деле ваш код эквивалентен:

if Assigned(Stream) then 
    if Assigned(Stream) then 
    Stream.Destroy; 

Так чище полагаться на тест внутри Free и просто написать:

Stream.Free; 

В комментариях вы заявляете, что вы на самом деле хотите проверить независимо от того, заблокирован ли файл. Не используйте для этого поток файлов. Вместо этого выполните следующие действия:

  • Звоните CreateFile, чтобы открыть файл.
  • Проверьте обнаруженную ручку на INVALID_HANDLE_VALUE.
  • В случае ошибки используйте GetLastError, чтобы узнать причину ошибки.
  • В противном случае закройте ручку с помощью CloseHandle.

Однако это не рекомендуется. Вы можете использовать этот подход, чтобы определить, что файл не заблокирован, но к тому моменту, когда вы попытаетесь его прочитать, он заблокирован. Существует неотъемлемое состояние гонки.

В качестве общего руководства лучше просить прощения, чем разрешения.

+0

Хорошо, но я пишу этот код для обнаружения заблокированного документа. У getLastError без runtimepackge был код 32. Каков наилучший способ обнаружить, что файл заблокирован? – Joc02

+0

См. Мои последние изменения –

0

Активация исключения может сбрасывать код ошибки вызывающего потока. Просто не нужно вызывать GetLastError() внутри обработчика исключений.

Это, как говорится, если TFileStream не удается открыть файл, возникает исключение, которое содержит сообщение об ошибке обеспечиваемой системы (но не фактический код ошибки), например:

procedure TForm1.Button1Click(Sender: TObject); 
var 
    Stream: TStream; 
begin 
    try 
    Stream := TFileStream.Create('d:\toto.docx', fmOpenRead); 
    try 
     // use Stream as needed 
    finally 
     Stream.Free; 
    end; 
    except 
    on E: Exception do 
     ShowMessage('Erreur : ' + E.Message); 
    end; 
end; 

Если вам нужен доступ к коду ошибки, вы не можете использовать TFileStream, вы должны будете использовать CreateFile() непосредственно вместо:

procedure TForm1.Button1Click(Sender: TObject); 
var 
    hFile: THandle; 
    iError: DWORD; 
begin 
    hFile := CreateFile('d:\toto.docx', GENERIC_READ, 0, nil, OPEN_EXISTING, 0, 0); 
    if hFile <> INVALID_HANDLE_VALUE then 
    begin 
    try 
     // use hFile as needed... 
     // 
     // if you need to access the file as a TStream, you can 
     // instantiate a THandleStream passing hFile to its constructor... 
     // 
    finally 
     CloseHandle(hFile); 
    end; 
    end else 
    begin 
    iError := GetLastError; 
    ShowMessage('Erreur : ' + IntToStr(iError)); 
    if iError = ERROR_SHARING_VIOLATION then 
    begin 
     // do something... 
    end; 
    end; 
end; 

в качестве альтернативы:

procedure TForm1.Button1Click(Sender: TObject); 
var 
    hFile: THandle; 
begin 
    hFile := CreateFile('d:\toto.docx', GENERIC_READ, 0, nil, OPEN_EXISTING, 0, 0); 
    try 
    Win32Check(hFile <> INVALID_HANDLE_VALUE); 
    try 
     // use hFile as needed... 
    finally 
     CloseHandle(hFile); 
    end; 
    except 
    on E: EOSError do 
    begin 
     ShowMessage('Erreur : ' + IntToStr(E.ErrorCode)); 
     if E.ErrorCode = ERROR_SHARING_VIOLATION then 
     begin 
     // do something... 
     end; 
    end; 
    end; 
end; 
Смежные вопросы