App designer - custom global error handling

29 ビュー (過去 30 日間)
Jakub Devera
Jakub Devera 2022 年 4 月 1 日
コメント済み: Jakub Devera 2024 年 4 月 2 日
I am trying to add general custom error handling to App Designer application. One of the use cases is e.g. when an unhandled error would trigger a pop-up window with that error. I see this useful to me for a compiled application without command line.
If there is an error in any callback, AppManagementService instance will catch it in the tryCallback method. This method will also notify listeners using fireCallbackErroredEvent.
I naive way to try to listen that callback could be AppManagementService.instance() since it is referencing to a unique singleton.
function startupFcn(app)
service = appdesigner.internal.service.AppManagementService.instance();
addlistener(service, 'CallbackErrored', @app.displayErrorDialog);
end
However, it is not possible to connect to the notifier since access is restricted only to following to classes:
events (ListenAccess = {?appdesigner.internal.appalert.AppAlertController; ...
?appdesigner.internal.service.WebAppRunner})
% This event is fired when there's an exception or error happening
% in the app's callback or startup function
CallbackErrored
I am maybe overengineering the general custom error handling and I am not aware of some functionality in App Designer.
Do you have any suggestions how to approach this problem? Any advice is appreciated.
Edit:
I have created following class inherited from AppAlertController and this class is able to listen CallbackErrored from AppManagementService. It is working in classic Matlab IDE, but not after compilation to standalone app. It seems that supercalss is not being is imported to Matlab runtime.
classdef AppAllertErrorHandler < appdesigner.internal.appalert.AppAlertController
methods
function obj = AppAllertErrorHandler()
service = appdesigner.internal.service.AppManagementService.instance();
obj.CallbackErroredListener = addlistener(service, 'CallbackErrored', @obj.displayErrorDialog);
end
end
methods(Access = protected)
function doSendErrorAlertToClient(obj, appException)
% Empty implementation of superclass abstract method
end
end
methods(Access = private)
function displayErrorDialog(obj, event, source)
% display dialog
Error = source.Exception;
msg = sprintf('Unhandled exception \nIdentifier: %s\nMessage: %s in file %s at line %d ', ...
Error.identifier, Error.message, Error.stack(1).name, Error.stack(1).line);
msgbox(msg, 'Unhandled exception');
end
end
end
Following error is obtained after compilation
testApp.exe
Error using AppAllertErrorHandler
The specified superclass 'appdesigner.internal.appalert.AppAlertController' contains a parse error, cannot be found on MATLAB's search path, or is shadowed by another file with the same name.
Error in testApp/startupFcn (line 18)
Error in appdesigner.internal.service.AppManagementService/tryCallback (line 371)
Error in appdesigner.internal.service.AppManagementService/runStartupFcn (line 153)
Error in matlab.apps.AppBase/runStartupFcn (line 43)
Error in testApp (line 61)
MATLAB:class:InvalidSuperClass

採用された回答

Jakub Devera
Jakub Devera 2022 年 4 月 1 日
I have found a workaround for following error:
The specified superclass 'appdesigner.internal.appalert.AppAlertController' contains a parse error, cannot be found on MATLAB's search path, or is shadowed by another file with the same name.
I have just coppied AppAlertController.m to +appdesigner/+internal/+appalert in my application folder (the file cannot be linked directly since it is in a root folder) and added it as a dependency. I don't particularly like this workaround to shadow Matlab root files, but at least the functionality is working. If error occurs, user is notified by msgbox. If you will have any other tip for similar functionality, please contribute.
  3 件のコメント
R Hermans
R Hermans 2024 年 3 月 26 日
Update (using Matlab 2023a).
I tried to use the code from Jakub (1-apr-2022), with the Accepted answer but this failed for me.
Unfortunately i got an error (maybe something has changed in the matlab internals) between versions?
The problem is that the CallbackErrored event, is not a known event for the class AppManagementService.
I changed the code to use the CallbackErrorHandler instance (instead of AppManagement).
The code works from the matlab IDE, but not when deployed.
Unfortunately then i got the error
'Warning: In "C:\MY_PROJECT\600-PC-Software\644-AA-(sources)\Code\+appdesigner\+internal\+service\AppManagementService.m", "mlapp.internal.MLAPPMetadataReader" are excluded from packaging for the MATLAB Runtime environment according to the MATLAB Compiler license.'
The problem is in the usage of mlapp.internal.MLAPMetadataReader
Does anyone has a clue to solve this?
Regards René
classdef AppAlertErrorHandler < appdesigner.internal.appalert.AppAlertController
% AppAlertErrorHandler is a class which subscribes to event CallBackErrored so that an exception during
% callback can be logged.
%TODO1: this module doesnot work when deployed!! (it works perfect from matlab IDE).
% when creating the deployable below warning is generated:
% Warning: In "C:\MY_PROJECT\600-PC-Software\644-AA-(sources)\Code\+appdesigner\+internal\+service\AppManagementService.m", "mlapp.internal.MLAPPMetadataReader" are excluded from packaging for the MATLAB Runtime environment according to the MATLAB Compiler license.
%
properties (Access = public)
previousExceptionClass;
ExceptionCount int32 = 0;
logger; % reference to logger instance.
end
methods
function obj = AppAlertErrorHandler(logger)
%CONSTRUCTOR
obj.logger = logger;
obj.logger.info('AppAlertErrorHandler enter constructor');
callbackErrorHandler = appdesigner.internal.apprun.CallbackErrorHandler.instance();
if isempty(obj.CallbackErroredListener)
obj.CallbackErroredListener = addlistener(callbackErrorHandler, 'CallbackErrored', @obj.logUnhandledException);
end
obj.logger.info('AppAlertErrorHandler exit constructor');
end
end
methods(Access = protected)
function doSendErrorAlertToClient(obj, appException) %#ok<INUSD>
% Empty implementation of superclass abstract method
end
end
methods(Access = private)
function logUnhandledException(obj, event, source) %#ok<INUSD>
%logUnhandledException logs the exception to the logger.
obj.ExceptionCount = obj.ExceptionCount + 1;
currentException = source.Exception;
stackString = getReport(currentException, 'extended', 'hyperlinks', 'off');
fprintf('Unhandled exception;;Message: %s', stackString);
%Note: when invoking a msgbox at this place, strange things happen: then this handler is more times invoked for
% unknown reason.
end
end
end
Jakub Devera
Jakub Devera 2024 年 4 月 2 日
My provided solution sadly stopped working in Matlab2022b. I had the same problem as you, it worked in AppDesigner IDE but not when compiled. The functionality was depending on a callback that reported the error to the IDE and Mathworks is removing this callback for compiled environment. I guess there is no general solution now.

サインインしてコメントする。

その他の回答 (0 件)

カテゴリ

Help Center および File ExchangeWhos についてさらに検索

製品

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by