How I could ignore the error msgbox if the uninstall.vsf file does not exists when calling LoadVCLStyle_UnInstall function in this code?
I supposed that using a Try block with an empty Except will be enough as in other languages, but this is not the case.
// Import the LoadVCLStyle function from VclStylesInno.DLL
procedure LoadVCLStyle_UnInstall(VClStyleFile: String); external 'LoadVCLStyleA#{app}\uninstall.dll stdcall uninstallonly';
//E: Occurs when the uninstaller initializes.
function InitializeUninstall: Boolean;
begin
Result := True;
// Initialize the VCL skin style.
try
LoadVCLStyle_UnInstall(ExpandConstant('{app}\uninstall.vsf'));
except
finally
end;
end;
The possibility to check for the file existence beforehand was already mentioned.
The user TLama mentioned that the code in the question is not regular pascal program code, but Inno Setup script code and and that my answer doesn't apply in this case. Because the following text could be of interest for pascal programmers we keep it.
The EXCEPT statement by itself doesn't handle the exception, it marks only the point where program execution should continue after an error has occured. When the exception isn't handled/caught in the EXCEPT ... END block it will be transferd to the next higher EXCEPT statement. (Freepacal reference guide chapter 17)
I also don't think that TRY ... EXCEPT ... FINALLY ... END will work. Either EXCEPT or FINALLY, not both.
If you want to capture the exception you must do something like:
TRY
LoadVCLStyle_UnInstall(ExpandConstant('{app}\uninstall.vsf'));
EXCEPT
On EWhateverException DO ...;
END;
If the exception class for this error isn't defined in the documentation, you can use the following trick to find the exception class name:
TRY
LoadVCLStyle_UnInstall(ExpandConstant('{app}\uninstall.vsf'));
EXCEPT
ON Exception DO WriteLn(ExceptObject.ClassName);
END;
With ON Exception DO .. you can catch any exception, but i don't recomend to use that variant for the definite program.
Related
There is a code in which every line can cause an exception and I want to continue my execution even if an error occurred in any of the lines of code
I will implement this in the below-mentioned way
begin
code that might throw an exception
rescue
logger
end
begin
code that might throw an exception
rescue
logger
end
begin
code that might throw an exception
rescue
logger
end
begin
code that might throw an exception
rescue
logger
end
is there any better way to handle this type of error handling if yes please explain how can I write better code
every line can cause an exception
please explain how can I write better code
You can write better code by not designing it in such a way that every line can raise an exception. Especially this idea that the code should "plough on ahead, regardless of any trail of errors are left in its wake".
At an extreme, you code could contain all sorts of spelling mistakes / invalid method calls / whatever, and your proposed design would attempt to continue executing the remainder of the code, regardless of how broken it is.
However, I cannot really give concrete advice on how to do this, without seeing some actual code.
I apologize for this relatively simple question but I am new to Oracle and DBMS Workspace Manager. I have a stored procedure that checks the current workspace and if it differs from the workspace being passed in it will execute the DBMS_WM.GOTOWORKSPACE. All the examples show using EXEC while calling DBMS_WM.GOTOWORKSPACE but when I have the following syntax inside TOAD it says its invalid, if I take the EXEC off no errors shown.
Which is correct?
//Toad Does not like this synatx
IF UPPER(l_current_workspace) != UPPER(i_workspace) THEN
EXEC DBMS_WM.GOTOWORKSPACE (i_workspace);
END IF;
OR
//TOAD is fine with this
IF UPPER(l_current_workspace) != UPPER(i_workspace) THEN
DBMS_WM.GOTOWORKSPACE (i_workspace);
END IF;
I would guess that the examples are in a form something like EXEC DBMS_WM.GOTOWORKSPACE (<>);and not between a conditionalIF...END IF;`
EXEC is not a PLSQL reserved word. It is a macro/shortcut in the client rather than the database server, that expands to wrap the statement it precedes into a BEGIN ... END; block.
It is used very widely on the command-line (SQLPlus and SQLcl) and editors like Toad and SQLDeveloper et al. often support it, but it is supported as a monolithic command only (EXEC as a prelude to the block) rather than inside of the block (Nested EXEC is not supported, nor is an EXEC inside of another BEGIN...END; block).
Since it isn't a reserved word, expanding it when it is in another block is a problem. Parsing it becomes ambiguous -- one could define one's own function called EXEC and it would be perfectly valid to run in a PLSQL block. The editor would then need to make an uncertain call about what to do when it encountered the word. The below example would break if EXEC were expanded instead of being recognized as a procedure in the PLSQL block:
CREATE PROCEDURE EXEC(PARAM_1 IN VARCHAR2)
IS
BEGIN
DBMS_OUTPUT.PUT_LINE(UTL_LMS.FORMAT_MESSAGE('Param is:[%s]',PARAM_1));
END EXEC;
/
BEGIN
EXEC('VOLTRON');
END;
/
So the second example is correct (presuming it is housed in another BEGIN...END; block), and is universally compatible since it doesn't need to be intercepted and modified client-side.
i manage to do "something"(like deleting files,etc) when exit or exit! is called from Object.
by changing the method exit and exit! inside Object class. (at_exit is too unreliable)
but then the "something" never execute if there's error such as NameError, etc.
is there way so i can make "something" that still execute if there's error.
(any error possible if necessary).
something like at_exit but works with all errors
thanks in advance for assistance. and forgive me if there's already question ask for this.
i do search a lot before asking here. and found nothing.
edit: i don't know where the original author of the code place the method. since the original author load it from dll files in the exe program the author used for launcher. (i can only edit After the original code take place...). so i think i need another approach for this... but i manage to make a workaround for my problem... by putting begin rescue in other places that send data to the original object. i filter the data send and throw my own error before it reach the main program... so i guess this works too.
Borrowing from an answer on a different thread, and definitely along the lines of what Marek commented, this is how you should handle errors in Ruby:
begin
# something which might raise an exception
rescue SomeExceptionClass => some_variable
# code that deals with some exception
rescue SomeOtherException => some_other_variable
# code that deals with some other exception
else
# code that runs only if *no* exception was raised
ensure
# ensure that this code always runs, no matter what
end
Original credit: Begin, Rescue and Ensure in Ruby?
I have a bunch of functions in packages that first check the validity of the work being requested and throw exceptions if not.
Example:
package body foo as
function implode (
i_foo_id number
) return implode_id as
not_implodable exception;
implode_id number;
begin
if not is_implodable(i_foo_id) then
raise not_implodable;
end if;
//Implode logic here.
return implode_id;
exception
when not_implodable then
raise_application_error(-20005, 'Imploding is not possible on this foo.');
end implode;
end foo;
I have turned on warning reporting and get something like this when I compile.
Warning(67,3): PLW-05005: subprogram IMPLODE returns without value at line 14.
If I put a return statement after the raise_application_error then the warning goes away. Since raising the error exits the call stack, is there any good reason to return null anyways?
No. It is not a best practice for functions to return after raising and error in PL/SQL.
It is possible and sometimes even recommended to add code just to shut up the compiler, like:
exception
when fooex then
raise_application_error(-20100, 'invalid number');
return null; -- silence PLW-05005
end;
Be sure to document such a peculiar code !
Generally I don't like a code that is just there to satisfy compiler warning, but there is always exceptions to this rule. In this particular case I'd say the problem is more the compiler than the code. In my opinion code like below is perfectly valid and compiler should not complain about it. In fact I think compiler should warn if a block has statements after raise as it's effectively a dead-code (unreachable code).
Let's consider the following function:
$ cat foo.sql
create or replace function foo(p_in in number)
return number is
fooex exception;
begin
if p_in < 1 then
raise fooex;
end if;
return p_in;
exception
when fooex then
raise_application_error(-20100, 'invalid number');
end;
/
show errors
Running this in Oracle 11g XE:
-- By default the warnings are disabled
SQL> #foo
Function created.
No errors.
Usually I want all warnings:
SQL> alter session set plsql_warnings = 'ENABLE:ALL';
Session altered.
SQL> #foo
SP2-0806: Function created with compilation warnings
Errors for FUNCTION FOO:
LINE/COL ERROR
-------- -----------------------------------------------------------------
1/1 PLW-05005: subprogram FOO returns without value at line 13
1/1 PLW-05018: unit FOO omitted optional AUTHID clause; default
value DEFINER used
After reviewing the code I found out the warnings above are incorrect, so I disable them for this compilation unit only:
SQL> alter session set plsql_warnings = 'ENABLE:ALL, DISABLE:(5005,5018)';
Session altered.
SQL> #foo
Function created.
No errors.
SQL>
Now all is good and great.
My recommendation is to turn on all warnings by default and then turn off wrong positives per compilation unit (alter session set plsql_warnings = 'ENABLE:ALL, DISABLE:(5005,5018)';). If possible: alter system plsql_warnings = 'ENABLE:ALL'; but in practice this might be a bit too harsh ...
And oh, it is a recommended practice to turn on all compiler error checks. We as a programmers need all the help the compilers can give to us ! Unfortunately with Oracle PL/SQL compiler this needs to be compromised.
Best practice is to always raise any exceptions that your function (or procedure, as the case may be) doesn't know how to handle.
For example, if your function queries a table, and the logic is "if no rows are found, return 0" or something, then I'd expect your function to handle the exception and return a sane value.
If your function gets an unexpected exception, e.g. VALUE_ERROR (e.g. due to bad data in the table caused by some bug in a data load procedure, or a missing constraint), that's arguably not the responsibility of the function; I'd expect your function to propagate the exception to the caller (although I might write the function to at least log the error before re-raising the exception).
This is why you should always have a RAISE; in any WHEN OTHERS exception handler.
The only time I'd make an exception to this rule is if I'm coding an API for some legacy system which can't handle exceptions, and expects an "error flag" (e.g. as an out parameter). In that case, I might use a WHEN OTHERS THEN exception handler to log the unexpected error, and return the error flag to the caller. It's not good coding style though, because it puts a lot of trust in the calling code to check the "error flag" before assuming the function did its work without error.
It doesn't matter one way or the other. Adding a return will make the whatever code validator your using happy. The statement will never get reached as raising the application error puts control in caller's exception handler if exists or execution ends.
Personally, I code according the syntax of the language and hope the validators eventually correct their mistakes.
I have this code:
procedure EstablishCommunication;
var
State : TStates;
Attempts : Byte;
procedure IncAttempts;
begin
Inc(Attempts);
end;
begin
State := stReadDeviceID;
Attempts := 0;
while True do
begin
if Attempts >= MAX_ATTEMPTS then
begin
State := stError;
end;
case State of
stReadDeviceID:
begin
// some code
IncAttempts;
end;
stError:
begin
// Error code
end;
...
...
...
I'd like to put the code that set state to stError within of the procedure IncAttempts, resulting:
procedure EstablishCommunication;
var
State : TStates;
Attempts : Byte;
procedure IncAttempts;
begin
Inc(Attempts);
if Attempts >= MAX_ATTEMPTS then
begin
State := stError;
end;
end;
begin
State := stReadDeviceID;
Attempts := 0;
while True do
begin
case State of
stReadDeviceID:
begin
// some code
IncAttempts;
end;
stError:
begin
// Error code
end;
...
...
...
So, can I move the code to IncAttempts?
Is this a code smell?
If yes, Can you advice me a better way?
I would see this as perfect valid code. I ask myself the following questions when declaring a method inside another. Most of the time I don't do it, but sometimes it's results in better code.
Will the internal function ever need to change as in a descendant class?
Can I override External method without calling the internal method and be OK?
Does the internal function have practical application outside of external method?
Is the internal function complex enough that it should be unit tested outside the scope of there external method?
If any of the above apply don't use an Internal Method.
However if if you don't have any of the above, and it can remove repeated code and/or simplify the design then you can consider using a internal function.
No real problem with that, should work just fine. You are already modifying another local variable Attempts so there is no reason why modifying State should smell more.
I do think you should be careful of using inline functions to much. The code often ends up hard to read/understand.
I would say that the new code have some whiff...
It all depends on how many states you manage in current code, and if the number of states could change in the future. Beware of how and when you set the state, and beware of how and when you check the state.
In the two code snippets you show, there is a minor difference:
In the first, original code, the current state is preserved through the iteration, and the new error-state is set in the beginning of the iteration, and it is always checked.
In the second, refactored code, the state is changed in the middle of the iteration, and it is only altered if the state is stReadDeviceID.
Now, if the last line in this while True do-iteration is if State = stError then Break;, then your first code will run the iteration one more time, changing the state to stError in the beginning if the iteration. Your second code will exit at the end of the current iteration, and the code in the stError-section of the case-statement will never be executed...
If you want to go all the way, and study the GoF's State Design Pattern, then take a look at these pages:
http://en.wikipedia.org/wiki/State_pattern (no Delphi code...)
http://sourcemaking.com/design_patterns/state (with Delphi code!)
http://www.dofactory.com/Patterns/PatternState.aspx (no Delphi code...)
http://conferences.embarcadero.com/article/32129#_Toc12157322 (with Delphi code!)