Exception in WPF with DevExpress

Hi.
Delphi 7 host
.Net 4.8 WPF plugin with Devexpress

I’ve been trying to track down an exception which occurs the second time I load a .Net WPF plugin. I’ve traced it to the first instance not being correctly unloaded due to release failing.

Attached is a simplified sample project to replicate what I’m seeing.
Delphi 7 host with source and a WPF plugin.

test project

In my main project the user loads Hydra plugins into a pageControl. Each plugin creating
tab. The plugins are stored in an objectList whilst in use. When a plugin close is requested the plugin is located in the ObjectList and a ReleaseInstance is called using the IHYVisualPlugin property. The release is failing.

// Find plugin to be closed
ItemIndex := fDockedFormManager.FindItemIndexByInstanceID(anInstanceID);

// This release is failing silently.  IntfPointer set to Nil, but unload ater it fails 
ModuleManager.ReleaseInstance(DockedFormManager.Items[ItemIndex].IntfPointer);

// Delete objectList Item

// Check if all instances of plugin closed first, then unload.
if (not FoundInstance) then begin

  i := ModuleManager.InstanceCount;
  ModuleManager.UnloadModule(i_PluginFileName);

  TrimWorkingSet();
end;

///
type
  TDockedForm = class(TObject)
  private 
    FTabPage: TcxTabSheet;
     ...        
    // Setters and getters...
  public
    IntfPointer: IHYVisualPlugin;

    // Other properties..
   end;
///
type
  TDockedFormManager = class(TObjectList)
  private
    function GetItems(Index: integer): TDockedForm;
    procedure SetItems(Index: integer; const Value: TDockedForm);

  public
    property Items[Index:integer]: TDockedForm read GetItems write SetItems;
    function FindItemIndexByInstanceID (i_InstanceID: integer): integer;
    function FindItemIndexByInterfacePointer(i_IntfPointer: IHYVisualPlugin): integer;
    function FindItemIndexByTabSheet (i_TabSheet: TcxTabSheet): integer;
  end;

Hello

Could you also provide the exception info?
In case of a .NET-side exception could you attach Visual Studio as a debugger to catch the full exception info including its type and full stacktrace?

Thanks in advance

It’s actual a WPF exception, but the test project attached allows you to reproduce it.
I’ve stepped into your source and the issue with not being able to unload seems to be caused by THYModuleManager.CanUnload raising exception as it finds the PluginDescriptors after ReleaseInstance as run (stepped through ReleaseInstance - all OK).

2020-05-29 14:46:05.7927|ERROR|PluginModule1.Plugin1|System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.NullReferenceException: Object reference not set to an instance of an object.
   at DevExpress.Xpf.Bars.BarContainerControl.CreateItemsSource()
   at DevExpress.Xpf.Bars.BarContainerControl..ctor()
   at System.Xaml.Schema.XamlTypeInvoker.DefaultCtorXamlActivator.InvokeDelegate(Action`1 action, Object argument)
   at System.Xaml.Schema.XamlTypeInvoker.DefaultCtorXamlActivator.CallCtorDelegate(XamlTypeInvoker type)
   at System.Xaml.Schema.XamlTypeInvoker.DefaultCtorXamlActivator.CreateInstance(XamlTypeInvoker type)
   at System.Xaml.Schema.XamlTypeInvoker.CreateInstance(Object[] arguments)
   at MS.Internal.Xaml.Runtime.ClrObjectRuntime.CreateInstanceWithCtor(XamlType xamlType, Object[] args)
   at MS.Internal.Xaml.Runtime.ClrObjectRuntime.CreateInstance(XamlType xamlType, Object[] args)
   at System.Xaml.XamlObjectWriter.Logic_CreateAndAssignToParentStart(ObjectWriterContext ctx)
   at System.Xaml.XamlObjectWriter.WriteStartMember(XamlMember property)
   at System.Xaml.XamlWriter.WriteNode(XamlReader reader)
   at System.Windows.Markup.WpfXamlLoader.TransformNodes(XamlReader xamlReader, XamlObjectWriter xamlWriter, Boolean onlyLoadOneNode, Boolean skipJournaledProperties, Boolean shouldPassLineNumberInfo, IXamlLineInfo xamlLineInfo, IXamlLineInfoConsumer xamlLineInfoConsumer, XamlContextStack`1 stack, IStyleConnector styleConnector)
   at System.Windows.Markup.WpfXamlLoader.Load(XamlReader xamlReader, IXamlObjectWriterFactory writerFactory, Boolean skipJournaledProperties, Object rootObject, XamlObjectWriterSettings settings, Uri baseUri)
   at System.Windows.Markup.WpfXamlLoader.LoadBaml(XamlReader xamlReader, Boolean skipJournaledProperties, Object rootObject, XamlAccessLevel accessLevel, Uri baseUri)
   at System.Windows.Markup.XamlReader.LoadBaml(Stream stream, ParserContext parserContext, Object parent, Boolean closeStream)
   at System.Windows.Application.LoadComponent(Object component, Uri resourceLocator)
   at PluginModule1.Views.ToolbarView.InitializeComponent() in C:\Users\Martin\Source\repos\Proof of Concept\Testbeds\CloseOpenTest\PluginModule1\Views\ToolbarView.xaml:line 1
   at PluginModule1.Views.ToolbarView..ctor() in C:\Users\Martin\Source\repos\Proof of Concept\Testbeds\CloseOpenTest\PluginModule1\Views\ToolbarView.xaml.cs:line 12
   --- End of inner exception stack trace ---
   at System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck)
   at System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark)
   at System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark)
   at System.Activator.CreateInstance(Type type, Boolean nonPublic)
   at System.RuntimeType.CreateInstanceImpl(BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes, StackCrawlMark& stackMark)
   at System.Activator.CreateInstance(Type type, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes)
   at System.Activator.CreateInstance(Type type, Object[] args)
   at System.Xaml.Schema.SafeReflectionInvoker.CreateInstanceCritical(Type type, Object[] arguments)
   at System.Xaml.Schema.SafeReflectionInvoker.CreateInstance(Type type, Object[] arguments)
   at System.Xaml.Schema.XamlTypeInvoker.CreateInstance(Object[] arguments)
   at MS.Internal.Xaml.Runtime.ClrObjectRuntime.CreateInstanceWithCtor(XamlType xamlType, Object[] args)
   at MS.Internal.Xaml.Runtime.ClrObjectRuntime.CreateInstance(XamlType xamlType, Object[] args)
   at System.Xaml.XamlObjectWriter.Logic_CreateAndAssignToParentStart(ObjectWriterContext ctx)
   at System.Xaml.XamlObjectWriter.WriteStartMember(XamlMember property)
   at System.Xaml.XamlWriter.WriteNode(XamlReader reader)
   at System.Windows.Markup.WpfXamlLoader.TransformNodes(XamlReader xamlReader, XamlObjectWriter xamlWriter, Boolean onlyLoadOneNode, Boolean skipJournaledProperties, Boolean shouldPassLineNumberInfo, IXamlLineInfo xamlLineInfo, IXamlLineInfoConsumer xamlLineInfoConsumer, XamlContextStack`1 stack, IStyleConnector styleConnector)
   at System.Windows.Markup.WpfXamlLoader.Load(XamlReader xamlReader, IXamlObjectWriterFactory writerFactory, Boolean skipJournaledProperties, Object rootObject, XamlObjectWriterSettings settings, Uri baseUri)
   at System.Windows.Markup.WpfXamlLoader.LoadBaml(XamlReader xamlReader, Boolean skipJournaledProperties, Object rootObject, XamlAccessLevel accessLevel, Uri baseUri)
   at System.Windows.Markup.XamlReader.LoadBaml(Stream stream, ParserContext parserContext, Object parent, Boolean closeStream)
   at System.Windows.Application.LoadComponent(Object component, Uri resourceLocator)
   at PluginModule1.Views.DxView1.InitializeComponent() in C:\Users\Martin\Source\repos\Proof of Concept\Testbeds\CloseOpenTest\PluginModule1\Views\DxView1.xaml:line 1
   at PluginModule1.Views.DxView1..ctor() in C:\Users\Martin\Source\repos\Proof of Concept\Testbeds\CloseOpenTest\PluginModule1\Views\DxView1.xaml.cs:line 24
   --- End of inner exception stack trace ---
   at System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck)
   at System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark)
   at System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark)
   at System.Activator.CreateInstance(Type type, Boolean nonPublic)
   at System.RuntimeType.CreateInstanceImpl(BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes, StackCrawlMark& stackMark)
   at System.Activator.CreateInstance(Type type, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes)
   at System.Activator.CreateInstance(Type type, Object[] args)
   at System.Xaml.Schema.SafeReflectionInvoker.CreateInstanceCritical(Type type, Object[] arguments)
   at System.Xaml.Schema.SafeReflectionInvoker.CreateInstance(Type type, Object[] arguments)
   at System.Xaml.Schema.XamlTypeInvoker.CreateInstance(Object[] arguments)
   at MS.Internal.Xaml.Runtime.ClrObjectRuntime.CreateInstanceWithCtor(XamlType xamlType, Object[] args)
   at MS.Internal.Xaml.Runtime.ClrObjectRuntime.CreateInstance(XamlType xamlType, Object[] args)
   at System.Xaml.XamlObjectWriter.Logic_CreateAndAssignToParentStart(ObjectWriterContext ctx)
   at System.Xaml.XamlObjectWriter.WriteEndObject()
   at System.Xaml.XamlWriter.WriteNode(XamlReader reader)
   at System.Windows.Markup.WpfXamlLoader.TransformNodes(XamlReader xamlReader, XamlObjectWriter xamlWriter, Boolean onlyLoadOneNode, Boolean skipJournaledProperties, Boolean shouldPassLineNumberInfo, IXamlLineInfo xamlLineInfo, IXamlLineInfoConsumer xamlLineInfoConsumer, XamlContextStack`1 stack, IStyleConnector styleConnector)
   at System.Windows.Markup.WpfXamlLoader.Load(XamlReader xamlReader, IXamlObjectWriterFactory writerFactory, Boolean skipJournaledProperties, Object rootObject, XamlObjectWriterSettings settings, Uri baseUri)
   at System.Windows.Markup.WpfXamlLoader.LoadBaml(XamlReader xamlReader, Boolean skipJournaledProperties, Object rootObject, XamlAccessLevel accessLevel, Uri baseUri)
   at System.Windows.Markup.XamlReader.LoadBaml(Stream stream, ParserContext parserContext, Object parent, Boolean closeStream)
   at System.Windows.Application.LoadComponent(Object component, Uri resourceLocator)
   at PluginModule1.Plugin1.InitializeComponent() in C:\Users\Martin\Source\repos\Proof of Concept\Testbeds\CloseOpenTest\PluginModule1\Plugin1.xaml:line 1
   at PluginModule1.Plugin1..ctor() in C:\Users\Martin\Source\repos\Proof of Concept\Testbeds\CloseOpenTest\PluginModule1\Plugin1.xaml.cs:line 37

Hello

Unfortunately it seems to be some kind of issue with loading WPF-related stuff into a non-default .NET domain.
Your sample works without errors when it is changed to load plugin into the default domain.

I’m getting the opposite in my testing.
I’ve added a new section to the test app which creates plugins into a tab which better represents my main application.

Modified test app

First “New Instance” button click will perform the LoadManagedModule and dock into a tab, subsequent clicks will create a new instance in a new tab.

Select an instance in the ListView and click “Close” to perforn ReleaseInstance. When the last instance has been released the UnloadModule is called.

After Unload, clicking “New Instance” will start the process again and call LoadManagedModule.

If LoadManagedModule is called with InNewAppDomain = true this works fine.
If LoadManagedModule is called with InNewAppDomain = false this second Load fails.