1
Vote

[Version 2.0] Initialization Issue through COM

description

Hello,

As mentioned in Discussion
https://avalondock.codeplex.com/discussions/443240
and
https://avalondock.codeplex.com/discussions/446010

there seems to be an issue with AvalonDock 2.0 when used through COM Object Generation/Call.

After the Thread from ShadesJeff I've decided to dig a bit deeper, but as stated I'm not good in this type of debugging.

I can confirm, that the Error is may be around the LayoutPanel and the Processing of Childs.
I'm not sure but guess it shouldn't be normal, that the child will be reprocessed multiple time for sizing/location (at least it looks like: First at Init LayoutPane, 2nd after Orientation-Check/Reset of the LayoutPane).

Simplified Flow explained
Com: Init - Childs - Orientation - Crash
Regular: Init - Childs - Orientation - Childs again - Show

I'll hope this explanation and the demo files help to find the real issue.
Sorry for not beeing a better help in it.

Forgot to Mention:
AvalonDock 1.3 works perfectly through COM (But I know this will not help for fixing the issue)

file attachments

comments

ShadesJeff wrote Nov 19, 2013 at 11:56 PM

Telaran,

Did you make any more progress on this? Like you, I am not overly strong in debugging this type of error.

Anyway, I downloaded your sample and played around with it. Sure enough, the MainWindow fails to load when invoked via COM.

However, and this was my workaround before, if you add an AssemblyResolve event handler to point back to the AvalonDock.dll, then the MainWindow will load correctly.

The ShowWindow function then looks like
        public void ShowWindow()
        {
            AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(AssemblyResolveEventHandler);
            if (this._mw1 == null)
            {
                this._mw1 = new MainWindow();
            }
            this._mw1.Show();
        }
Also add the actual event handler:
        [ComVisible(false)]
        private Assembly AssemblyResolveEventHandler(object sender, ResolveEventArgs args)
        {
            var asmName = new AssemblyName(args.Name);
            if (asmName.Name.Equals("AvalonDock"))
            {
                return Assembly.LoadFile(System.IO.Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "\\AvalonDock.dll");
            }
            return null;
        }
Build, run the VBScript (or however you are trying to instantiate the COM server), and voila, the MainWindow opens as expected.

But!

If you include the AvalonDock.dll as an embedded resource in the COM application (for example, to deploy only a single-file executable) and the AssemblyResolve event handler looks like:
        [ComVisible(false)]
        private Assembly AssemblyResolveEventHandler(object sender, ResolveEventArgs args)
        {
            var asmName = new AssemblyName(args.Name);
            if (asmName.Name.Equals("AvalonDock"))
            {
                using (var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("COMTryoutWPF.Library.AvalonDock.dll"))
                {
                    var assemblyBytes = new byte[stream.Length];
                    stream.Read(assemblyBytes, 0, assemblyBytes.Length);
                    return Assembly.Load(assemblyBytes);
                }
            }
            return null;
        }
Build, run the VBScript (or however you are trying to instantiate the COM server), and BAM! The program crashes again.

I started to read the documentation related to the CLR assembly loader and I quickly got a headache. Hopefully there is someone smarter than me who can quickly point to an issue in AvalonDock (or a bug in the CLR) so that we can get some resolution on this issue.

Jeff