c # - Relativ sti til uhåndteret DLL

Indlæg af Hanne Mølgaard Plasc

Problem




   Mulig duplikat:

  Angiv søgestien for DllImport i .NET





Jeg har en uhåndteret DLL. For clearance er det en C ++ dll, som jeg vil bruge i min c # kode.
Problemet er, at det er en Windows-app og bruger, der kan installere det i enhver mappe efter eget valg. Så jeg kan ikke henvise det til en statisk vej, og jeg kunne ikke finde en måde at give en relativ vej på.
Her er koden jeg prøvede:


 [DllImport("mydll.dll", CharSet = CharSet.Auto, SetLastError = true)]
  static extern bool SetDllDirectory(string lpPathName);

  public void SetDllDirectory(string lpPathName)
        {
            try
            {
                bool r = SetDllDirectory(lpPathName);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public void SetDirectoryPath()
        {
            try
            {
                DirectoryInfo directory = new DirectoryInfo(System.IO.Path.GetDirectoryName(System.Windows.Forms.Application.ExecutablePath));
                if (directory.Exists)
                    SetDllDirectory(directory.ToString() + "\mydll.dll");

            }
            catch (Exception ex)
            {
                throw ex;
            }
        }


Og nedenfor er den fejl, jeg modtager.



  Kan ikke finde et indgangspunkt med navnet 'SetDllDirectory' i DLL 'mydll.dll'.



Dette spørgsmål kunne være en kopi af


'C ++ unmanaged DLL i c #'


'Relativ sti til DLL i Platform Invoke Statement'


Undskyld for det, men jeg fandt ingen løsning i disse referencer.

Bedste reference


Denne fejlmeddelelse:



  Kan ikke finde et indgangspunkt med navnet 'SetDllDirectory' i DLL 'mydll.dll'.



siger intet om ikke at kunne finde DLL. Det siger, at din P/Invoke definition er forkert. Der er ingen funktion med navnet SetDllDirectory i din DLL (mydll.dll). Og hvorfor skulle der være? De eneste funktioner, der eksporteres fra DLL'er, er dem, du udtrykkeligt koder og eksporterer. Da du ikke skrev kode til en SetDllDirectory og angiver, at den skal eksporteres fra mydll.dll, eksisterer den ikke i DLL'en.


Udover det er dette spørgsmål ubesvarligt, medmindre du opdaterer dit spørgsmål med ægte kode. Du skal mindst sende underskriften til den funktion, du forsøger at ringe fra den ustyrede DLL, sammen med den P/Invoke-kode, du har forsøgt på siden C # (administreret).



  Problemet er, at det er en Windows-app og bruger, der kan installere det i enhver mappe efter eget valg. Så jeg kan ikke henvise det til en statisk vej, og jeg kunne ikke finde en måde at give en relativ vej på.



Dette er ikke et reelt problem. Relative stier fungerer fint, og de fungerer på den måde, som dit spørgsmål angiver, at du allerede har forsøgt. Du skal blot inkludere navnet på DLL'en i P/Invoke definitionen. Standard DLL-søgeord tager sig af alt andet. Hvis den administrerede EXE er i samme mappe som den ustyrede DLL, som du vil P/Invoke, vil alt fungere problemfrit.


Det betyder ikke noget, hvor brugeren vælger at installere appen, så længe DLL og EXE er placeret i samme mappe. Og det er dit installationsprogram.


Og så længe du bruger relative stier, skal du absolut ikke bruge funktionen SetDllDirectory fra Win32 API'en (som faktisk er defineret i kernel32.dll. [14]

Andre referencer 1


Hvis du forsøger at stikke ind i et ustyret bibliotek, der ikke er standard, skal du tilføje denne placering til den dll-søgevej, som Windows bruger til at kigge efter DLL-filer.


Hvis dine brugere kan fortælle det program, hvor c/c ++ biblioteksfilen er, kan du indlæse den manuelt, når de vælger den.


public class UnsafeNativeMethods {
    [DllImport("kernel32.dll", SetLastError = true)]
    public static extern bool SetDllDirectory(string lpPathName);

    [DllImport("kernel32.dll", SetLastError = true)]
    public static extern int GetDllDirectory(int bufsize, StringBuilder buf);

    [DllImport("kernel32", CharSet = CharSet.Unicode, SetLastError = true)]
    public static extern IntPtr LoadLibrary(string librayName);

    [DllImport("mylibrary")]
    public static extern void InitMyLibrary();
}


Du kan ringe ovenstående i en form for preload rutine som sådan:


public void LoadDllFile( string dllfolder, string libname ) {
    var currentpath = new StringBuilder(255);
    UnsafeNativeMethods.GetDllDirectory( currentpath.Length, currentpath );

    // use new path
    UnsafeNativeMethods.SetDllDirectory( dllfolder );

    UnsafeNativeMethods.LoadLibrary( libname );

    // restore old path
    UnsafeNativeMethods.SetDllDirectory( currentpath );
}


Du kan så kalde det som sådan:


LoadDllFile( "c:whatever", "mylibrary.dll" );