I am extending an existing InstallScript project and need to call a method in an assembly that targets .NET 4.0.
The project already calls a method in another class in the same assembly: so I know that much works.
Mirroring what I see for the existing .NET method call, here is what I have so far:
//////////////////////////////////////////////////////////////////////////////
// SomeFunction
//
// Wraps SomeAssembly.SomeClass.SomeMethod.
//////////////////////////////////////////////////////////////////////////////
prototype number SomeFunction();
function number SomeFunction()
string szDLL, szAssemblyandClassName;
OBJECT oSomeClass;
number nResult;
begin
ChangeDirectory(SRCDIR); // changed from ChangeDirectory(SUPPORTDIR), which yielded error number -2147219705 in the try-catch below
szDLL = "SomeAssembly.dll";
szAssemblyAndClassName = "SomeAssembly.SomeClass";
try
SprintfBox(INFORMATION, "Debug", "Calling DotNetCoCreateObject(\"%s\", \"%s\", \"\")..."), szDLL, szAssemblyAndClassName); // FORNOW
set oSomeClass = DotNetCoCreateObject(szDLL, szAssemblyAndClassName, "");
catch
SprintfBox(SEVERE, "Error", "Error %i:\n\n%s\n\n%s", Err.Number, Err.Description, Err.LastDllError);
abort;
endcatch;
SprintfBox(INFORMATION, "Debug", "Calling oSomeClass.SomeMethod()..."); // FORNOW
nResult = oSomeClass.SomeMethod();
SprintfBox(INFORMATION, "Debug", "oSomeClass.SomeMethod() returned %i.", nResult); // FORNOW
return nResult;
end;
When SomeFunction()
executes in the setup I have built, I see the following output...
Calling DotNetCoCreateObject("SomeAssembly.dll", "SomeAssembly.SomeClass", "")...
Calling oSomeClass.SomeMethod()...
..., but then the setup immediately exits without any apparent error. Getting no indication of what goes wrong makes this frustrating to troubleshoot. Searching for a likely cause, I have found nothing so far.
Why would oSomeClass.SomeMethod()
cause the setup to exit immediately with no apparent error?
EDIT:
Per @MichaelUrman's comment asking for more details about what differs between the existing class (OrigClass
) that works and the new one (SomeClass
) that does not:
public sealed
.OrigMethod
and SomeMethod
) are public
.ComVisible
attribute; but their assembly (SomeAssembly
) has [assembly: ComVisible(true)]
in its AssemblyInfo.cs
.The differences between Existing.rul
(that successfully integrates with SomeAssembly.OrigClass.OrigMethod
) and New.rul
(that does not successfully integrate with SomeAssembly.SomeClass.SomeMethod
) are as follows (using a patch file):
2c2
< // OrigFunction
---
> // SomeFunction
4c4
< // Wraps SomeAssembly.OrigClass.OrigMethod.
---
> // Wraps SomeAssembly.SomeClass.SomeMethod.
6,7c6,7
< prototype number OrigFunction();
< function number OrigFunction()
---
> prototype number SomeFunction();
> function number SomeFunction()
9c9
< OBJECT oOrigClass;
---
> OBJECT oSomeClass;
14c14
< szAssemblyAndClassName = "SomeAssembly.OrigClass";
---
> szAssemblyAndClassName = "SomeAssembly.SomeClass";
18c18
< set oOrigClass = DotNetCoCreateObject(szDLL, szAssemblyAndClassName, "");
---
> set oSomeClass = DotNetCoCreateObject(szDLL, szAssemblyAndClassName, "");
24,26c24,26
< SprintfBox(INFORMATION, "Debug", "Calling oOrigClass.OrigMethod()..."); // FORNOW
< nResult = oOrigClass.OrigMethod();
< SprintfBox(INFORMATION, "Debug", "oOrigClass.OrigMethod() returned %i.", nResult); // FORNOW
---
> SprintfBox(INFORMATION, "Debug", "Calling oSomeClass.SomeMethod()..."); // FORNOW
> nResult = oSomeClass.SomeMethod();
> SprintfBox(INFORMATION, "Debug", "oSomeClass.SomeMethod() returned %i.", nResult); // FORNOW
OrigFunction
and SomeFunction
use a try
-catch
-endcatch
to respectively ensure that oOrigClass
and oSomeClass
are set to a valid reference. The InstallScript Language Reference's DotNetCoCreateObject documentation explains that "[the] function throws an exception if the object cannot be created".
The problem turned out to have a simple explanation.
There was a mismatch between SomeMethod
in oSomeClass.SomeMethod()
and the actual name of the .NET SomeClass
method available to call - i.e. oSomeClass.SomeMethod()
should have been oSomeClass.SomeOtherMethod()
.
In my case, the mismatch was not so drastic and simply due to pluralization I initially overlooked in the defined .NET method's name - e.g. oSomeClass.SomeStringMethod()
(singular) where oSomeClass.SomeStringsMethod()
(plural) was in order.
That the setup immediately exited without any apparent error made it a booger to identify the simple cause of the problem.