0

I'm using multiple DLLs with the same name and I would like to have only one path for searching a DLL when using dllimport.

My code so far:

    'Trying to remove default search paths    
    <System.AttributeUsage(System.AttributeTargets.Assembly Or System.AttributeTargets.Method, AllowMultiple:=False)>
        Public NotInheritable Class DefaultDllImportSearchPathsAttribute
            Inherits Attribute
        End Class

        'Trying to add my own path
        <DllImport("kernel32.dll", SetLastError:=True, CharSet:=CharSet.Auto)>
        Public Shared Function SetDllDirectory(ByVal lpPathName As String) As Long
        End Function

    'Importing my DLL
        <DllImport("A.dll", CallingConvention:=CallingConvention.StdCall)>
        Public Shared Sub B(<MarshalAs(UnmanagedType.BStr)> ByRef X As String)

        End Sub

    Dim path As String = My.Computer.Registry.GetValue("HKEY_CURRENT_USER\Software\A\", "path", Nothing)

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            SetDllDirectory(path)
    End Sub

It keeps loading another DLL and never reaches the stage of searching the DLL in the 'path'. How can I make this work?

References: How can I specify a [DllImport] path at runtime?

Pixy
  • 47
  • 6

1 Answers1

0

If you know the full path to your DLL load it explicitly with a call to LoadLibrary passing that full path. If you do that before call any pinvoke functions from that DLL, then the system uses the DLL that you loaded explicitly.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • The full path of the DLL is taken from the registry and it depends on the installation directory. Unfortunately, dllimport only accepts constants. – Pixy Jul 06 '19 at 14:05
  • Yes. So, load the dll first with a call to LoadLibrary, using the full path. That gets the right dll loaded into the process. Then call the pinvoke which you mark with just the filename of the dll. This is a well known method. – David Heffernan Jul 06 '19 at 14:43
  • I tried ` Public Shared Function LoadLibrary(ByVal lpLibFileName As String) As Long End Function` `Dim path As String = My.Computer.Registry.GetValue("HKEY_CURRENT_USER\Software\A\", "path", Nothing)` `Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load LoadLibrary(path + "A.dll") End Sub` ` Public Shared Sub B( ByRef X As String) End Sub` ` Still loading another dll. – Pixy Jul 06 '19 at 20:54
  • Works fine here. – David Heffernan Jul 06 '19 at 21:03
  • Hmm, strange. I try to find what goes wrong. Maybe I need elevated access level or something. – Pixy Jul 07 '19 at 15:43
  • No. That won't be it. Make a simple console program that calls LoadLibrary with a hard coded absolute path to the dll, and then calls kne of your pinvoke functions. – David Heffernan Jul 07 '19 at 15:50
  • I had another dll with the same name installed in GAC and due to search path priorities the program was trying to load this one instead of the one I wanted. Why priorities cannot be edited? Not cool. – Pixy Sep 03 '19 at 06:05