FoxPro and .NET Interop
LoadAssembly issues
Gravatar is a globally recognized avatar based on your email address. LoadAssembly issues
  Matthew Olson
  All
  Jul 23, 2024 @ 03:35am

I've had issues with this before but now I'm at a loss as to what I'm missing this time. I'm working to connect to Stripe from my application using a DLL I've created for that purpose.

Here is the problematic code in VFP:

LOCAL loBridge as wwDotnetBridge,loStripe
SET PROCEDURE TO wwdotnetbridge ADDITIVE
loBridge = GetwwDotnetBridge()
IF loBridge.LoadAssembly(pcSysHome + "Stripe.dll")
loStripe = loBridge.CreateInstance("Stripe.Program")
MESSAGEBOX(loBridge.cErrorMsg)
pcClient_Secret=loStripe.CreateStripe(lcSecret,lnAmount)

The cErrorMsg in the message box is: "Type not loaded. Please load call LoadAssembly first." I then get an error on the next line: "LOSTRIPE is not an object." If I look at cErrorMsg after the LoadAssembly, it is blank.

I've read this help topic a bunch: https://west-wind.com/wsdlgenerator/docs/_3680rtwph.htm. So, to confirm, here is the structure in my DLL:

Does anyone see what I'm doing wrong?

I appreciate any help.

Thanks, Matthew

Gravatar is a globally recognized avatar based on your email address. re: LoadAssembly issues
  Rick Strahl
  Matthew Olson
  Jul 23, 2024 @ 11:59am

Make sure that all the dependencies for the Stripe DLL are accessible in the FoxPro code. To find out you can create a new .NET project, add the Stripe NuGet package and then compile the project. Whatever is in the Bin folder should also be in the folder from which you're loading the Stripe DLL.

+++ Rick ---

Gravatar is a globally recognized avatar based on your email address. re: LoadAssembly issues
  Rick Strahl
  Matthew Olson
  Jul 23, 2024 @ 12:18pm

Make sure that all the dependencies for the Stripe DLL are accessible in the FoxPro code. To find out you can create a new .NET project, add the Stripe NuGet package and then compile the project. Whatever is in the Bin folder should also be in the folder from which you're loading the Stripe DLL.

+++ Rick ---

Gravatar is a globally recognized avatar based on your email address. re: LoadAssembly issues
  Matthew Olson
  Rick Strahl
  Jul 24, 2024 @ 09:05am

That makes some sense. However, I'm not seeing anything in that bin folder other than my dll. I have to go to the nuget folder to get these. And it looks like I need more than just the dependencies, but the dependencies to my dependencies. Am I not seeing the dlls in the bin folder because I'm using the community edition of Visual Studio? Is there another way to collect the dependencies (and any sub-dependencies)? I know I'm looking for an easy button here, but there are hundreds of sub-dependencies on some of these.

Thanks, Matthew

Gravatar is a globally recognized avatar based on your email address. re: LoadAssembly issues
  Rick Strahl
  Matthew Olson
  Jul 24, 2024 @ 09:53am

NuGet packages only contain their own compiled files.

The only way you'll see all the dependencies is if you build a top level .NET project (not a library). That's because each library only builds its own assemblies and pulls dependencies during compilation. So until you build a top level application (ie. a Console or WPF/WinForms or Test project) you won't really see all dependencies.

Easiest is to create .NET 4.72 console project (you need the .NET SDK for this)

  • Create a new folder and name it as you want your EXE file to be (ie. ConsoleTest)
  • Do: dotnet new console
  • Edit the .csproj file to change the TargetFramework to net472
  • Remove <ImplicitUsings> and <Nullable> elements
  • Run: dotnet add package stripe (or whatever)
  • Change: program.cs to adjust for older C# syntax used for net472 (see below)
  • Run: dotnet build

Note: the reason for the project cleanup is that the SDK no longer supports building for older versions of .NET. Older SDKs allowed for netstandard2.0, but even that is no longer supported. Visual Studio supports it though so you could create a project there, but you still will want to change the target to net472 or net481 to ensure you get the installed Windows framework dependencies.

You should end up with something like this:

<!-- .csproj -->
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net472</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="stripe" Version="1.12.0" />
  </ItemGroup>

</Project>

and

using System;

namespace ConsoleStart 
{

    public class Program 
    {
        public static void Main(string[] args) {
            Console.WriteLine("Hello World!");
        }
    }

}

These then are your actual dependencies:

+++ Rick ---

Gravatar is a globally recognized avatar based on your email address. re: LoadAssembly issues
  Matthew Olson
  Rick Strahl
  Jul 24, 2024 @ 10:35am

Thank you. I was wrong about there being a 100 dependencies. There ended up being 60. Still, more than enough.

After all of that, I'm still getting the same errors. Any ideas on that?

Thanks, Matthew

Gravatar is a globally recognized avatar based on your email address. re: LoadAssembly issues
  Rick Strahl
  Matthew Olson
  Jul 24, 2024 @ 11:21am

What library are you using exactly? If you're using Stripe you should only have those two dependencies...

Whatever other library you're using change or add it to that project to see what dependencies you really have.

+++ Rick ---

Gravatar is a globally recognized avatar based on your email address. re: LoadAssembly issues
  Matthew Olson
  Rick Strahl
  Jul 24, 2024 @ 11:38am

Ah. A very good question. Every time that I turned around, it seemed like I needed to load another dependency. There are only 5 dependencies, but the sub-dependencies went nuts. Here is a look at the packages with the stripe.net expanded to see sub-dependencies and the sub-subs, drilling down as far as I could go for that one:

Interestingly, I updated the Newtonsoft.Json one and it added it as a regular dependency. Otherwise, it is listed as a sub-dependency, so probably not needed as a regular dependency. When it did that though, I was at the end of my rope so just let it be.

Here's the full list of dependencies created: C:\StripeExe\Stripe\bin\Debug\net472\Microsoft.AspNetCore.Antiforgery.dll C:\StripeExe\Stripe\bin\Debug\net472\Microsoft.AspNetCore.Authentication.Abstractions.dll C:\StripeExe\Stripe\bin\Debug\net472\Microsoft.AspNetCore.Authentication.Core.dll C:\StripeExe\Stripe\bin\Debug\net472\Microsoft.AspNetCore.Authorization.dll C:\StripeExe\Stripe\bin\Debug\net472\Microsoft.AspNetCore.Authorization.Policy.dll C:\StripeExe\Stripe\bin\Debug\net472\Microsoft.AspNetCore.Cryptography.Internal.dll C:\StripeExe\Stripe\bin\Debug\net472\Microsoft.AspNetCore.DataProtection.Abstractions.dll C:\StripeExe\Stripe\bin\Debug\net472\Microsoft.AspNetCore.DataProtection.dll C:\StripeExe\Stripe\bin\Debug\net472\Microsoft.AspNetCore.Diagnostics.Abstractions.dll C:\StripeExe\Stripe\bin\Debug\net472\Microsoft.AspNetCore.Hosting.Abstractions.dll C:\StripeExe\Stripe\bin\Debug\net472\Microsoft.AspNetCore.Hosting.Server.Abstractions.dll C:\StripeExe\Stripe\bin\Debug\net472\Microsoft.AspNetCore.Html.Abstractions.dll C:\StripeExe\Stripe\bin\Debug\net472\Microsoft.AspNetCore.Http.Abstractions.dll C:\StripeExe\Stripe\bin\Debug\net472\Microsoft.AspNetCore.Http.dll C:\StripeExe\Stripe\bin\Debug\net472\Microsoft.AspNetCore.Http.Extensions.dll C:\StripeExe\Stripe\bin\Debug\net472\Microsoft.AspNetCore.Http.Features.dll C:\StripeExe\Stripe\bin\Debug\net472\Microsoft.AspNetCore.JsonPatch.dll C:\StripeExe\Stripe\bin\Debug\net472\Microsoft.AspNetCore.Mvc.Abstractions.dll C:\StripeExe\Stripe\bin\Debug\net472\Microsoft.AspNetCore.Mvc.Core.dll C:\StripeExe\Stripe\bin\Debug\net472\Microsoft.AspNetCore.Mvc.DataAnnotations.dll C:\StripeExe\Stripe\bin\Debug\net472\Microsoft.AspNetCore.Mvc.Formatters.Json.dll C:\StripeExe\Stripe\bin\Debug\net472\Microsoft.AspNetCore.Mvc.ViewFeatures.dll C:\StripeExe\Stripe\bin\Debug\net472\Microsoft.AspNetCore.ResponseCaching.Abstractions.dll C:\StripeExe\Stripe\bin\Debug\net472\Microsoft.AspNetCore.Routing.Abstractions.dll C:\StripeExe\Stripe\bin\Debug\net472\Microsoft.AspNetCore.Routing.dll C:\StripeExe\Stripe\bin\Debug\net472\Microsoft.AspNetCore.WebUtilities.dll C:\StripeExe\Stripe\bin\Debug\net472\Microsoft.Bcl.AsyncInterfaces.dll C:\StripeExe\Stripe\bin\Debug\net472\Microsoft.DotNet.PlatformAbstractions.dll C:\StripeExe\Stripe\bin\Debug\net472\Microsoft.Extensions.Configuration.Abstractions.dll C:\StripeExe\Stripe\bin\Debug\net472\Microsoft.Extensions.DependencyInjection.Abstractions.dll C:\StripeExe\Stripe\bin\Debug\net472\Microsoft.Extensions.DependencyInjection.dll C:\StripeExe\Stripe\bin\Debug\net472\Microsoft.Extensions.DependencyModel.dll C:\StripeExe\Stripe\bin\Debug\net472\Microsoft.Extensions.FileProviders.Abstractions.dll C:\StripeExe\Stripe\bin\Debug\net472\Microsoft.Extensions.Hosting.Abstractions.dll C:\StripeExe\Stripe\bin\Debug\net472\Microsoft.Extensions.Localization.Abstractions.dll C:\StripeExe\Stripe\bin\Debug\net472\Microsoft.Extensions.Localization.dll C:\StripeExe\Stripe\bin\Debug\net472\Microsoft.Extensions.Logging.Abstractions.dll C:\StripeExe\Stripe\bin\Debug\net472\Microsoft.Extensions.ObjectPool.dll C:\StripeExe\Stripe\bin\Debug\net472\Microsoft.Extensions.Options.dll C:\StripeExe\Stripe\bin\Debug\net472\Microsoft.Extensions.Primitives.dll C:\StripeExe\Stripe\bin\Debug\net472\Microsoft.Extensions.WebEncoders.dll C:\StripeExe\Stripe\bin\Debug\net472\Microsoft.Net.Http.Headers.dll C:\StripeExe\Stripe\bin\Debug\net472\Microsoft.Win32.Registry.dll C:\StripeExe\Stripe\bin\Debug\net472\Newtonsoft.Json.Bson.dll C:\StripeExe\Stripe\bin\Debug\net472\Newtonsoft.Json.dll C:\StripeExe\Stripe\bin\Debug\net472\Stripe.net.dll C:\StripeExe\Stripe\bin\Debug\net472\System.Buffers.dll C:\StripeExe\Stripe\bin\Debug\net472\System.ComponentModel.Annotations.dll C:\StripeExe\Stripe\bin\Debug\net472\System.Diagnostics.DiagnosticSource.dll C:\StripeExe\Stripe\bin\Debug\net472\System.Memory.dll C:\StripeExe\Stripe\bin\Debug\net472\System.Numerics.Vectors.dll C:\StripeExe\Stripe\bin\Debug\net472\System.Runtime.CompilerServices.Unsafe.dll C:\StripeExe\Stripe\bin\Debug\net472\System.Security.AccessControl.dll C:\StripeExe\Stripe\bin\Debug\net472\System.Security.Cryptography.Xml.dll C:\StripeExe\Stripe\bin\Debug\net472\System.Security.Permissions.dll C:\StripeExe\Stripe\bin\Debug\net472\System.Security.Principal.Windows.dll C:\StripeExe\Stripe\bin\Debug\net472\System.Text.Encodings.Web.dll C:\StripeExe\Stripe\bin\Debug\net472\System.Text.Json.dll C:\StripeExe\Stripe\bin\Debug\net472\System.Threading.Tasks.Extensions.dll C:\StripeExe\Stripe\bin\Debug\net472\System.ValueTuple.dll

Does this help?

Thanks, Matthew

Gravatar is a globally recognized avatar based on your email address. re: LoadAssembly issues
  Rick Strahl
  Matthew Olson
  Jul 24, 2024 @ 12:00pm

What you're looking at is the .NET Core version so that might be different and that's not what you want (you can use that, but if there's a .NET Framework version that will be better with less dependencies). The subdependencies you are seeing are from the base libraries, so those you don't need to worry about.

This is why I say: Build a local project with just that dependency and build it - that will show you exactly what's required for the specific runtime target.

.NET Framework has different dependencies than .NET Core and for FoxPro usage, you'll preferably want to use the .NET Framework version of any library, unless that's not available.

I was looking at the wrong NuGet package before, but using what you have there is stripe.net and these are the dependencies:

  <ItemGroup>
    <PackageReference Include="Stripe.net" Version="45.4.0" />
  </ItemGroup>

which gets you this when built:

It looks like that's a really old version of the Newtonsoft library, so you'll likely need assembly redirects to make that work, but that should give you different errors (if any at runtime).

+++ Rick ---

© 1996-2024