2

I'm migrating a .NET application to .NET Core, and one of the tasks that the app needs to do, is to enumerate assemblies the .NET Global Assembly Cache (yes, I know my .NET Core app itself doesn't use the GAC, but one of the purposes of my app is to create an inventory of what is in the full .NET Framework GAC)

Any method that I try to P/Invoke in the Fusion.dll gives me the same error:

Unhandled Exception: System.DllNotFoundException: Unable to load DLL 'Fusion.dll' or one of its dependencies: The specified module could not be found. (Exception from HRESULT: 0x8007007E)

Code example:

class Program
{
    static void Main(string[] args)
    {
        GacUtility.CreateAssemblyCache(out var x, 0);
    }
}

public class GacUtility
{
    [DllImport("Fusion.dll")]
    public static extern int CreateAssemblyCache(out object asmCache, int reserved);
}

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp2.2</TargetFramework>
  </PropertyGroup>

</Project>

NB: I know that correct signature of CreateAssemblyCache expects an IAssemblyName and I have that right in my code, which gives me the same error. I'm using object above to simplify a reproduceable example.

Lindsey1986
  • 381
  • 1
  • 3
  • 15
  • 1
    When using P/Invoke, make sure your that the function you are calling is exported correctly, project and the dll have the same architecture or the dll dependencies are available with it (you can use a dependency walker for this). – Sohaib Jundi Jul 16 '19 at 02:40
  • I might be wrong but the concept of GAC is not possible with .NET Core in the same sense as it is in the .NET Framework. If you want to inventory the dlls in the .NET GAC you would be better off enumerating the contents of the proper folders. After all the GAC is just a collection of DLLS inside some very specific folders. – Jonathan Alfaro Jul 16 '19 at 04:59
  • @SohaibJundi I'm positive the function is exported correctly, project and dll have the same architecture because it's works fine when I call it from a .NET Framework app both 32-bit and 64-bit. – Lindsey1986 Jul 16 '19 at 06:55
  • @Darkonekt That doesn't make sense to me because I'm just doing a P/Invoke to an external DLL. It should not matter that I'm doing it from .NET Core. In theory, P/Invoke can call any kind of Win32 DLL, no? – Lindsey1986 Jul 16 '19 at 06:56
  • 1
    It does matter because the GAC is searched differently. If you want to load a dll and call it. You will need to provider a FULL PATH and make sure the architecture of the DLL is the same as the consuming application. – Jonathan Alfaro Jul 17 '19 at 06:24
  • Thanks @Darkonekt I see what you mean – Lindsey1986 Jul 17 '19 at 13:02

1 Answers1

1

Changing platform to x64, and specifying full path to the dllImport, and the signiture to IntPtr instead of object worked for me,

class Program
{
    static void Main(string[] args)
    {
        GacUtility.CreateAssemblyCache(out IntPtr x, 0);
    }
}

public class GacUtility
{
    [DllImport(@"C:\Windows\Microsoft.NET\Framework64\v4.0.30319\fusion.dll")]
    public static extern int CreateAssemblyCache(out IntPtr asmCache, int reserved);
}

yet, for x86 it strangely did not

Sohaib Jundi
  • 1,576
  • 2
  • 7
  • 15
  • 1
    That's certainly interesting. Thanks for sharing. Maybe it's a bug in .NET Core? Putting the full path or targeting `x64` is not really an option for me, so I'm looking for a workaround – Lindsey1986 Jul 16 '19 at 12:49