Page 1 of 2

Embedded Reference only working once

PostPosted: Tue Jan 03, 2023 7:55 pm
by sh_jackland
I'm creating a plugin which uses the following NuGet
https://www.nuget.org/packages/Microsof ... ons/6.25.1

I've added it as an embedded reference to my plugin and when I restart Jiwa to test it, it works as expected.
The problem is if I restart Jiwa again (and every time afterwards), I get the following error:

Error: Could not load file or assembly `Microsoft.IdentityModel.Abstractions, version=6.22.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35` or one of its dependencies. The system cannot find the file specified. Module .ctor

If I make a change to the plugin such as changing a line of code or removing the package from embedded references and re-adding it, it will work once and stop again.
Deleting the plugin folder inside "C:\ProgramData\Jiwa Financials\Jiwa 7\7.2.1\{user}\{server}\{database}\Plugins\{user}\Runtime\" will also cause it to work once.

Any ideas as to what the cause of this may be?

Re: Embedded Reference only working once

PostPosted: Wed Jan 04, 2023 8:24 am
by SBarnes
Without seeing the plugin it is difficult to comment, can you post the plugin as an attachment?

That being said a couple of things you could try:

  • Remove the embedded reference and drop the DLL in the Jiwa program directory and then add it as an assembly reference and see if you get the same problem
  • Add an Assemble resolver and see if that fixes the issue, see this link viewtopic.php?f=26&t=578&p=2009&hilit=AssemblyResolve#p2011 but add a resolver that will resolve to the current assemblies path namely the currently compiled plugin

Also I notice inside the NuGet package there are number of versions of the library which one are you embedding?

Re: Embedded Reference only working once  Topic is solved

PostPosted: Wed Jan 04, 2023 1:07 pm
by sh_jackland
Thank you for the response,

Your assembly resolver code helped me fix it.

What I noticed with the assembly resolver is that after a change is made to the plugin and Jiwa is restarted, the assembly resolver doesn't run and it works fine, but every time afterwards, the assembly resolver runs. Even though the .dll is still in the ProgramData directory.

What I've done is modified your AssemblyResolve code so it searches for the .dll in the ProgramData directory and it now works.

Code: Select all
static System.Reflection.Assembly AssemblyResolve(object sender, ResolveEventArgs e)
{
    string jiwaApplicationPath = @"C:\ProgramData\Jiwa Financials\Jiwa 7";
    System.Reflection.Assembly resolvedAssembly = null;

    string filename = e.Name.Split(new Char[] { ',' })[0].Replace(@"\\", @"\");
    string[] files = Directory.GetFiles(jiwaApplicationPath, filename + ".dll", SearchOption.AllDirectories);

    if (files.Length > 0)
    {
        resolvedAssembly = System.Reflection.Assembly.LoadFrom(files[0]);
    }

    return resolvedAssembly;
}

Re: Embedded Reference only working once

PostPosted: Wed Jan 04, 2023 2:58 pm
by SBarnes
Glad it helped.

Re: Embedded Reference only working once

PostPosted: Wed Jan 04, 2023 3:05 pm
by Mike.Sheen
sh_jackland wrote:What I've done is modified your AssemblyResolve code so it searches for the .dll in the ProgramData directory and it now works.


That's odd, because the default resolver already does that - but only if the RequestingAssembly is not null. It looks for the requested assembly in the same folder as the RequestingAssembly.Location. And in the case of plugins, the RequestingAssembly.Location is in a sub-folder of the ProgramData\Jiwa Financials folder.

In your case, is the ResolveEventArgs (e) .RequestingAssembly null? If it isn't, what value is it?

Re: Embedded Reference only working once

PostPosted: Wed Jan 04, 2023 3:12 pm
by sh_jackland
Mike.Sheen wrote:In your case, is the ResolveEventArgs (e) .RequestingAssembly null? If it isn't, what value is it?


RequestingAssembly is null when it runs.

Re: Embedded Reference only working once

PostPosted: Wed Jan 04, 2023 3:13 pm
by SBarnes
Which version from NuGet did you embed?

Re: Embedded Reference only working once

PostPosted: Wed Jan 04, 2023 3:15 pm
by Mike.Sheen
sh_jackland wrote:RequestingAssembly is null when it runs.


Ok - thanks for letting me know.

Looks like you've uncovered a bug - or at least some unexpected behaviour. I'll try to repro it and if I can you can look forward to it being fixed in a future release.

Re: Embedded Reference only working once

PostPosted: Wed Jan 04, 2023 3:31 pm
by sh_jackland
Here are the steps I took:

- Created a .Net 4.5 console app in Visual Studio
- Installed NuGet: Microsoft.IdentityModel.Abstractions 6.25.1
- Jiwa plugin Embedded References -> .dll at C:\path\to\solution\packages\Microsoft.IdentityModel.Abstractions.6.25.1\lib\net45\Microsoft.IdentityModel.Abstractions.dll

The code I'm running is based on this https://www.pragmatic-development.io/bl ... edentials/
In that sample, running line 25 is when the AssemblyResolve is ran.

Re: Embedded Reference only working once

PostPosted: Wed Jan 04, 2023 3:57 pm
by Mike.Sheen
I can't repro this issue.

Attached is the plugin I created for testing - it's using an Embedded reference of Microsoft.IdentityModel.Abstractions.dll and when logging into Jiwa, it runs the following code:

Code: Select all
const string clientId = "<clientId>",
          clientSecret = "<clientSecret>",
          tenantId = "<tenantId>",
          environment = "<yourEnvironment>.crm4",
          apiVersion = "9.2";

var scope = new[] { "https://{environment}.dynamics.com/.default" };
var webAPI = "https://{environment}.dynamics.com/api/data/v{apiVersion}/";
var authority = "https://login.microsoftonline.com/{tenantId}";

try
{
   var clientApp = Microsoft.Identity.Client.ConfidentialClientApplicationBuilder.Create(clientId)
       .WithClientSecret(clientSecret)
       .WithAuthority(new Uri(authority))
       .Build();
}
catch (Exception ex)
{
   // if we throw here we'll prevent the user from logging in - and they won't be able to login to disable this plugin... so we
   // just show the error in a messagebox instead
   Plugin.Manager.DisplayMessage(null, ex.Message, System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error);
}


Now, obviously because I don't have valid values for the Uri or secret I do get an error complaining about the invalid Uri - but it is happily resolving the Embedded reference - even on subsequent attempts.

sh_jackland - are you able to try the attached to see what behaviour you get?