cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
Reureu
Level 10

Bug: try catch endcatch no longer works in InstallScript projects

Hi,

I have noticed that try catch endcatch no longer works in InstallScript projects.

InstallScript code like:
function DoIt()
OBJECT comObject;
STRING errMsg;
begin
set comObject = CoCreateObject("MyProgID");
if (!IsObject(comObject)) then
errMsg = "comObject could not be created";
MessageBox(errMsg, SEVERE);
else
Err.Clear();
try
comObject.DoSomething();
catch
Sprintf( errMsg, "comObject.DoSomething(): exception thrown. Code 0x%lx", Err.Number );
MessageBox(errMsg, SEVERE);
endcatch;
endif;
set comObject = NOTHING;
end;

does not allow to catch exceptions.


  • This same code in a Basic MSI project allows to catch exceptions.
  • InstallShield 2011 (with/without Hotfix A) and 2010 (see corresponding thread here) are affected


If the underlying COM methods "throws" an exception, the setup does not catch it and crashes (see attachment), in spite of the "try catch endcatch"!

I know that it is not possible to pass exceptions across a COM interface, and that exceptions become HRESULT return codes.
But in a Basic MSI project, InstallScript seems to map this HRESULT to the Err object.

So any idea why it doesn't work in an InstallScript project?
Any workaround?
Labels (1)
0 Kudos
(3) Replies
joshstechnij
Level 10 Flexeran
Level 10 Flexeran

We haven't been able to reproduce any issues with try/catch in InstallScript projects. In a quick test, calling a COM method yields the following expected results in a try/catch block (the behavior is identical in a pure InstallScript project and an InstallScript custom action in a Basic MSI project):
- COM method returns successfully: script execution continues
- COM method returns a failed HRESULT: the HRESULT is captured by the InstallScript engine and an exception is generated by the engine, a script exception handler (try/catch) is used to catch the exception
- COM method throws an exception, for example, as a result of a NULL pointer dereference: an internal exception handler in the script engine catches the exception (assuming the exception did not corrupt the stack that the engine's thread is running on), the exception is then transfered to the nearest script exception handler with a status of RPC_E_SERVERFAULT (The server threw an exception)
- COM method returns status DISP_E_EXCEPTION: the dispatch exception information returned by the COM method is captured and the nearest script exception handler is called

The try/catch functionality and exception handling in InstallScript has not been changed since the InstallShield Professional 6.x release, so it would be unlikely that exception behavior changed in InstallShield 2010/2011 when no changes were made to the compiler or the engine with regards to exception handling.

Are you seeing this issue with all COM objects, or just one in particular? What is this method doing that is being called? Is this COM object a .NET assembly registered for .NET COM interop? Can you reproduce this issue with a sample COM object and InstallShield project that you can send us to test with?
0 Kudos
Reureu
Level 10

Hi Josh,

Thanks for your reply.
I have finally spotted the error. It was in my InstallScript code:

#define ERROR_OBJECT_CREATION -666

function TestCOMComponent()
OBJECT objComComponent;
begin
Err.Clear();

try
set objComComponent = CoCreateObject( "DummyComProject01.DummySimpleObject" );
if( !IsObject( objComComponent ) ) then
Err.Raise( ERROR_OBJECT_CREATION );
endif;
objComComponent.DoSomething();
catch
if( Err.Source = ERROR_OBJECT_CREATION ) then // THIS IS WRONG!
SprintfBox( SEVERE, "Error", "Could not instantiate objects" );
else
SprintfBox( SEVERE, "Error", "COM Exception caught: error code: 0x%lx\n", Err.Number );
endif;
endcatch;

set objComComponent = NULL;

end;


Comparing Err.Source with a number throws a Type Mismatch exception with code 0x80020005. As it is thrown from the catch endcatch block, I thought the COM exception wasn't caught!

Doh! Silly me!

The correct code should have been:
		if( Err.Number=  ERROR_OBJECT_CREATION ) then ...


So, yes, the error was on my side, but I think the InstallScript compiler should not have allowed to compare a string with a number.

Regards
0 Kudos
joshstechnij
Level 10 Flexeran
Level 10 Flexeran

The compiler does do some basic type checking on variable types that it has knowledge about. Unfortunately, no type checking can be applied to variables declared as OBJECT (which are COM objects). No type checking can be performed on these types of variables because they are all late-bound COM objects, meaning the compiler has no information about them at compile time (and there is no way to specify how to obtain such information, such as through a type library). The Err object is an implicit OBJECT implemented by the InstallScript engine, and it isn't treated any differently by the compiler compared to other OBJECT variables. Issues such as this with late-bound objects are also present in other languages, including C# with the 'dynamic' keyword that allows using late-binding. Errors in object/method use for late-bound objects are caught at runtime as a result.
0 Kudos