Как получить класс исключений на стороне Delphi из общего исключения EDelphi в скрипте

Вызов боковой функции Delphi из сценария, который вызывает исключение, вызывает общее исключение EDelphi на стороне сценария. Это скрывает класс фактического исключения на стороне Delphi. Я пытался изучить реализацию интерфейса EDelphi Ijaddajadda, но мне не хватает навыков, чтобы увидеть способ извлечь побочный класс Delphi или хотя бы имя класса. Правда должна быть где-то рядом...

Пример, сторона сценария

Try
 MyDelphiSideFunction; // May raise EOutOfmemory
Except on E:Exception do
 PrintLn(E.ClassName);
End;

При этом всегда печатается «EDelphi», независимо от фактического класса исключений на стороне Delphi (в этом примере EOutOfmemory).

Как получить «настоящий» класс или имя класса из E?

Знайте свои исключения!
Знайте свои исключения!
В Java исключение - это событие, возникающее во время выполнения программы, которое нарушает нормальный ход выполнения инструкций программы. Когда...
Управление ответами api для исключений на Symfony с помощью KernelEvents
Управление ответами api для исключений на Symfony с помощью KernelEvents
Много раз при создании api нам нужно возвращать клиентам разные ответы в зависимости от возникшего исключения.
1
0
67
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы не можете напрямую получить тип класса исключения, поскольку обработчик исключений DWScript нигде не хранит эту информацию, а тип на стороне Delphi в любом случае не будет иметь смысла внутри сценария. Однако вы можете легко получить имя класса из объекта исключения на стороне сценария EDelphi через свойство EDelphi.ExceptionClass. Так:

Скрипт

try

  var x := 1/0;

except
  on E: EDelphi do
    WriteLn('Error: ' + E.Message + ' (' + E.ExceptionClass + ')');

  on E: Exception do
    WriteLn('Error: ' + E.Message);
else
  WriteLn('Unknown exception type');
end;

Выход

Error: Floating point division by zero (EZeroDivide)

Вы можете увидеть исходный код DWScript, который преобразует исключение на стороне Delphi в исключение на стороне сценария EDelphi здесь: https://github.com/EricGrange/DWScript/blob/2d61c8a95fb4a2aab328f3cc84bb9f243c927286/Source/dwsExprs.pas#L2244

Как я нашел ответ

Я просто поискал в исходнике на Github (поиск в основном репозитории Bitbucket отстой) по запросу «EDelphi»: https://github.com/search?q=repo%3AEricGrange%2FDWScript%20EDelphi&type=code

Это дало мне этот фрагмент кода:

// A Delphi exception. Transform it to a EDelphi-dws exception
exceptObj:=CreateEDelphiObj(mainException.ClassName, mainException.Message);

Затем я посмотрел на метод CreateEDelphiObj:

function TdwsProgramExecution.CreateEDelphiObj(const ClassName : String;
                                   const Message : String) : IScriptObj;
begin
   Result := IScriptObj(IUnknown(
      ProgramInfo.Vars[SYS_EDELPHI].Method[SYS_TOBJECT_CREATE].Call([ClassName, Message]).Value));
   (Result.ExternalObject as TdwsExceptionContext).ReplaceTop(LastScriptError); // temporary constructor expression
end;

Это похоже на вызов конструктора на стороне скрипта с передачей строк ClassName и Message в качестве параметров. Это нормально, но что происходит со значением ClassName?

Опять же, глядя на результат поиска, я заметил реализацию конструктора EDelphi на стороне Delphi:

procedure TDelphiExceptionCreateMethod.Execute(info : TProgramInfo; var ExternalObject: TObject);
begin
   inherited;
   Info.ValueAsVariant[SYS_EDELPHI_EXCEPTIONCLASS_FIELD]:=Info.ValueAsVariant['Cls']
end;

Таким образом, конструктор вызывает унаследованный конструктор, а затем сохраняет значение ClassName в поле FExceptionClass (значение константы SYS_EDELPHI_EXCEPTIONCLASS_FIELD).

На этом этапе я мог догадаться, что свойство будет называться ExceptionClass, поэтому я использовал свою DWScriptStudio IDE/отладчик, чтобы написать пример и проверить результат.

Большое спасибо @AndersMelander, это именно то, что я искал. Но где же вы нашли свойство ExceptionClass? Я часами просматривал исходники DWS в поисках чего-то подобного. И даже полный поиск ExceptionClass по всем источникам DWS не дал мне значимого намека. Не могли бы вы меня просветить? Интересный факт: DWS вполне доволен var x := 1/0, разрешая INF. Можно ли это изменить, чтобы вместо этого вызвать исключение?

LuWey 23.09.2023 17:55

Я обновил свой ответ, чтобы объяснить, как я нашел свойство ExceptionClass. Что касается INF и исключения, это может быть разница в том, как настроены наши маски исключений, или это может быть следующее: stackoverflow.com/questions/47611635/…

AndersMelander 23.09.2023 21:33

Прекрасное объяснение @AndersMelander. Очень ценю! И ваша DWScript Studio также представляет собой замечательную работу, которую я сейчас рассматриваю. Мне интересно, насколько сложно будет отказаться от этого дорогостоящего DevExpress.

LuWey 24.09.2023 21:02

Большинство элементов управления DevExpress имеют соответствующие эквивалентные элементы управления VCL, но некоторые их не имеют (например, TcxTreeList). Ленту можно легко заменить чем-то другим, поскольку вся логика пользовательского интерфейса делегируется действиям. Думаю, самой сложной частью будет система стыковки. Стыковочная система VCL... в лучшем случае проблематична.

AndersMelander 25.09.2023 02:07

Другие вопросы по теме