UnloadModule not working on .net plugin (D7 host)

Delphi 7 host, c# .net framework 4.7.2 plugin
Tried with both c# winforms and wpf. Same issue

Delphi 7 Host with existing Delphi 7 plugins works as expected and ModuleManager.UnloadModule works correctly.

Delphi 7 Host code is as follows

*// Get instance from ObjectList*
*// After this call the VisualPluginIntf is populated correctly*
VisualPluginIntf := i_PluginManager.Items[ItemIndex].IntfPointer;

*// Call Release.  No exception raised and after the call the VisualPluginIntf is nil as it is when called*
*// For a D7 plugin*
ModuleManager.ReleaseInstance(VisualPluginIntf);

*// Unload module.  Currently uses name, but we've also tried with index*
ModuleManager.UnloadModule(i_PluginFileName);

At this point when unloading a .net plugin we receive exception

EHYException with message 'Plugin module WinformsPlugin.dll could not be unloaded, because the following plugin instances were not released
Plugin "WinformsPlugin.Mainform" reference count : 1

Interestingly inspecting ModuleManager.fModules.Count before/after the call to ReleaseInstance shows the same number of modules - so Release must be failing even though we’re seeing the VisualPluginIntf of nil after the call.

Hi,

can you show, how to you load .NET module into delphi, pls?
by other way, you can create a simple testcase that reproduces this issue.
you can attach it here or drop email to support@ if you want to keep it privately.

Hi, thanks for the reply.

We have tried both LoadModule and LoadManagedModule.

procedure TFrmPulseLauncherHostBase.LoadPlugin(i_PluginFileName: string;
  i_Language: string);
var
  module : THYModule;
begin
  with ModuleManager do begin
    // First check if the requested plugin has already been loaded.
    module := FindModule(i_PluginFileName);

    // If not loaded then load it..
    if (module=NIL) then begin
      if (i_Language <> 'DOTNET') then
        LoadModule(i_PluginFileName)
      else
        LoadManagedModule(i_PluginFileName, true);
    end;
  end;
end;

Hi,

I can’t reproduce this case with TicTacToePluginModule.dll (winforms plugin) from Hydra for NET\Mixed Mode sample

steps:

  • open Managed Projects (All).sln
  • build TicTacToePluginModule
  • update “Hydra for NET\Mixed Mode\Delphi for Win32\UnmanagedHost” and drop button to main form:
procedure TMainForm.Button1Click(Sender: TObject);
var
  i: integer;
begin
  if pos('TicTac', lb_Plugins.Items[lb_Plugins.ItemIndex]) > -1 then begin
    HYModuleManager1.ReleaseInstance(fCurrentPlugin);
    HYModuleManager1.UnloadModule(lb_Plugins.ItemIndex);

    lb_Plugins.Items.Clear;
    for i := 0 to HYModuleManager1.PluginDescriptorCount-1 do begin
      lb_Plugins.Items.Add(HYModuleManager1.PluginDescriptors[i].Name);
    end;
  end;
end;
  • launch UnmanagedHost
  • dbl click on TicTacToe
  • press button1
  • close form
  • no errors will be shown

Thanks for the pointers.
After some tweaking of my Delphi Host code I have this working correctly,

The following changes were made.

Creating the plugin instance
from

var
  intfinstance : IInterface;
...
// Create an instance of the plugin
ModuleManager.CreateInstance(i_FormName,intfinstance);     

// Store the interface so we can talk to the plugin
DockedForm.IntfPointer := intfinstance as IHYVisualPlugin; 

To

var
    intfinstance : IHYPlugin;
...
// Create an instance of the plugin
intfinstance := ModuleManager.CreateInstance(i_FormName) as IHYPlugin;   

// Store the interface so we can talk to the plugin
DockedForm.IntfPointer := intfinstance as IHYVisualPlugin;  

Releasing the plugin with the saved intfinstance works correctly

VisualPluginIntf := i_PluginManager.Items[ItemIndex].IntfPointer;
ModuleManager.ReleaseInstance(VisualPluginIntf);

And when Unloading the plugin I’m using the ‘formname’ rather than the ‘filename’.

ModuleManager.UnloadModule(i_PluginFileName);

to

ModuleManager.UnloadModule(i_PluginFormName);

Many thanks. The proof of concept project is looking positive !