Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Monty241 ease analysis missing method exception #1701

Conversation

monty241
Copy link
Contributor

No description provided.

During analysis of a problem with a build, it occurred to me that when the first log destination fails, the virtual log (whatever that is) is neither fed with the log message.

This behaviour hinders analysis.

This patch improves logging capabilities, even when part of the log system is broken / generates an error.

```
{"itgenmsi151","Message":"** Info: === Logging started: 14-12-2024  14:32:14 ==="
{"itgenmsi501","Message":"First chance exception handling of type 'InstallerException':"
{"itgenmsi502","Message":"Exception of type 'Microsoft.Deployment.WindowsInstaller.InstallerException' was thrown. (type: InstallerException)"
{"itgenmsj681","Message":"No exception data to register."
{"itgenmsi504","Message":"Stack trace:"
{"itgenmsi505","Message":"   at System.Environment.GetStackTrace(Exception e, Boolean needFileInfo)"
{"itgenmsi505","Message":"   at System.Environment.get_StackTrace()"
{"itgenmsi505","Message":"   at Acme.Deploy.Error.CurrentDomain_FirstChanceException(Object sender, FirstChanceExceptionEventArgs e)"
{"itgenmsi505","Message":"   at Microsoft.Deployment.WindowsInstaller.Session.Message(InstallMessage messageType, Record record)"
{"itgenmsi505","Message":"   at Microsoft.Deployment.WindowsInstaller.Session.Log(String msg)"
{"itgenmsi505","Message":"   at WixSharp.MsiSessionAdapter.Log(String msg)"
{"itgenmsi505","Message":"   at Invantive.Deploy.Runtime.LogUtility.LogToSession(SessionState sessionState, String txt)"
{"itgenmsi505","Message":"   at Invantive.Deploy.Runtime.LogUtility.LogToSession(SessionState sessionState, TraceContext traceContext)"
{"itgenmsi505","Message":"   at Invantive.Deploy.Runtime.LogUtility.LogLine(SessionState sessionState, String txt, String messageCode)"
{"itgenmsi505","Message":"   at Invantive.Deploy.Runtime.LogUtility.LogLines(SessionState sessionState, String linePrefix, String[] lines, String messageCode)"
{"itgenmsi505","Message":"   at Invantive.Deploy.UI.ProgressDialog.ProcessMessage(InstallMessage messageType, Record messageRecord, MessageButtons buttons, MessageIcon icon, MessageDefaultButton defaultButton)"
{"itgenmsi505","Message":"   at WixSharp.UIShell.<>c__DisplayClass69_0.<ProcessMessage>b__1()"
{"itgenmsi505","Message":"   at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor)"
{"itgenmsi505","Message":"   at System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments)"
```
The method `InvoiceClientHandlers` calls a method on basis of the value of the defined property `WixSharp_Load_Handlers`.

Without this change, it is quite hard from the error log to pinpoint the cause when there are multiple handlers:

```
{"itgenmsi150","Message":"Start action indicated by user interface message from message record below - Load installation components."
{"itgenmsj687","Message":"Line: Action 14:32:15: WixSharp_Load_Action. "
{"itgenmsi151","Message":"** Info: Action start 14:32:15: WixSharp_Load_Action."
{"itgenmsi151","Message":"** Info: SFXCA: Extracting custom action to temporary directory: C:\\Windows\\Installer\\MSI36D7.tmp-\\"
{"itgenmsi151","Message":"** Info: SFXCA: Binding to CLR version v4.0.30319"
{"itgenmsi151","Message":"** Info: Calling custom action WixSharp!WixSharp.ManagedProjectActions.WixSharp_Load_Action"
{"itgenmsi151","Message":"** Info: WixSharp aborted the session because of the error:"
{"itgenmsi151","Message":"** Info: System.MissingMethodException: Kan geen abstracte klasse maken."
{"itgenmsi151","Message":"** Info:    bij System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck)"
{"itgenmsi151","Message":"** Info:    bij System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark)"
{"itgenmsi151","Message":"** Info:    bij System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark)"
{"itgenmsi151","Message":"** Info:    bij System.Activator.CreateInstance(Type type, Boolean nonPublic)"
{"itgenmsi151","Message":"** Info:    bij System.Activator.CreateInstance(Type type)"
{"itgenmsi151","Message":"** Info:    bij WixSharp.ManagedProject.InvokeClientHandlers(Session session, String eventName, IShellView UIShell)"
{"itgenmsi151","Message":"** Info: CustomAction WixSharp_Load_Action returned actual error code 1603 (note this may not be 100% accurate if translation happened inside sandbox)"
{"itgenmsi151","Message":"** Info: Action ended 14:32:16: WixSharp_Load_Action. Return value 3."
{"itgenmsi151","Message":"** Info: Action ended 14:32:16: INSTALL. Return value 3."
{"itgenmsi154","Message":"End installation with message record below."
{"itgenmsj685","Message":"Line: 1: Acme Program 24.0 2: {B117615F-ED98-4321-B110-94DA80017800} 3: 3 "
{"itgenmsi152","Message":"** ** CommonData: 1: 2 2: 0 "
{"itgenmsi152","Message":"** ** CommonData: 1: 2 2: 1 "
{"itgenmsi151","Message":"** Info: Action ended 14:32:16: INSTALL. Return value 3."
```

With this change, the logging will be easier to interprete.

Also, the exception is decorated with some background information to ease analysis when WixSharp logs these (our unhandled exception handler always prints these).
@monty241
Copy link
Contributor Author

monty241 commented Dec 14, 2024

As a side note: this error on missing method exception occurred due to the use of:

newWixManagedProject.Load += MsiLoad;

in the C# code. This data is duplicated into the WXS and then dynamically called using reflection. Great mechanism.

However, in combination with a private method and using DotBlur obfuscation, it was not really clear what was going wrong. The code compiled, but the event handler must be public to be discovered.

A suggestion is to check on registration in the WXS that the methods must be public to formally allow calling from the outside. I am aware that reflection allows calling private members normally, but in this case DotBlur obfuscation renamed the method :-)

Typically an error is registered like:

WixSharp failed to invoke WixSharp_Load_Handlers

when the member's name is obfuscated.

@oleg-shilo oleg-shilo merged commit 135257a into oleg-shilo:master Dec 15, 2024
1 check passed
@oleg-shilo
Copy link
Owner

A great addition to the error handling.
Txs
Merged.

@oleg-shilo
Copy link
Owner

A suggestion is to check on registration in the WXS that the methods must be public to formally allow calling from the outside.

Unfortunately this would prevent using lambda expressions as event handlers since lambdas are wrapped in non-public classes

image

image

In this case, WixSharp just follows the .NET lambda expression pattern for events - "invoke private type method"

@monty241
Copy link
Contributor Author

Yes, that is correct. Missed that one. Lambda expressions can be detected indirectly, but it is implementation dependant. Better to leave as you see as is.

@monty241 monty241 deleted the monty241-ease-analysis-missing-method-exception branch December 15, 2024 15:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants