How can I specify a [DllImport] path at runtime?
Asked Answered
E

12

178

In fact, I got a C++ (working) DLL that I want to import into my C# project to call it's functions.

It does work when I specify the full path to the DLL, like this :

string str = "C:\\Users\\userName\\AppData\\Local\\myLibFolder\\myDLL.dll";
[DllImport(str, CallingConvention = CallingConvention.Cdecl)]
public static extern int DLLFunction(int Number1, int Number2);

The problem is that it's gonna be an installable project, so the user's folder will not be the same (ex : pierre, paul, jack, mum, dad, ...) depending computer/session where it'd be runned on.

So I'd like my code to be a little more generic, like this :

/* 
goes right to the temp folder of the user 
    "C:\\Users\\userName\\AppData\\Local\\temp"
then go to parent folder
    "C:\\Users\\userName\\AppData\\Local"
and finally go to the DLL's folder
    "C:\\Users\\userName\\AppData\\Local\\temp\\myLibFolder"
*/

string str = Path.GetTempPath() + "..\\myLibFolder\\myDLL.dll"; 
[DllImport(str, CallingConvention = CallingConvention.Cdecl)]
public static extern int DLLFunction(int Number1, int Number2);

The big deal is that "DllImport" desire a "const string" parameter for the DLL's directory.

So my question is :: What could be done in this case ?

Enrollment answered 12/1, 2012 at 13:45 Comment(7)
Just deploy the DLL in the same folder as the EXE so you don't have to do anything but specify the DLL name without the path. Other schemes are possible but are all troublesome.Psychopath
The thing is that it's gonna be a MS Office Excel Add In, so I don't thing putting the dll in the exe's directory would be the best solution...Enrollment
Your solution is the wrong one. Don't place files in the Windows or system folders. They chose those names for a reason: because they're for Windows system files. You're not creating one of those because you don't work for Microsoft on the Windows team. Remember what you learned in kindergarten about using things that don't belong to you without permission, and put your files anywhere but there.Melanosis
Your solution is still wrong. Well-behaved applications that don't actually do administrative stuff shouldn't require administrative access. The other issue is that you don't know your application will actually be installed in that folder. I might move it somewhere else, or change the install path during setup (I do that kind of stuff for fun, just to break badly-behaved applications). Hard-coding paths is the epitome of bad behavior, and it's completely unnecessary. If you're using your application's folder, then that's the first path in the default search order for DLLs. All automatic.Melanosis
putting it in program files is NOT constant. 64bit machines have Program File (x86) instead, for example.Heated
@Jsncrdnl, I just put this Directory.SetCurrentDirectory(DLLsFolder), DLLs are loaded on demand, so before instantiating an object, that use the referenced DLL, call 'SetCurrentDirectory'. After loaded (using dllimport), the dlls are unload when the process is finished (or an AppDomain finalize, if any).Mestee
since had seen this syntax in csharp, knew it had a problem with it; a question world be, How To :( complete ignore such implementation and set other application parameters to indicate the method are not using DLLImport );Translator
M
213

Contrary to the suggestions by some of the other answers, using the DllImport attribute is still the correct approach.

I honestly don't understand why you can't do just like everyone else in the world and specify a relative path to your DLL. Yes, the path in which your application will be installed differs on different people's computers, but that's basically a universal rule when it comes to deployment. The DllImport mechanism is designed with this in mind.

In fact, it isn't even DllImport that handles it. It's the native Win32 DLL loading rules that govern things, regardless of whether you're using the handy managed wrappers (the P/Invoke marshaller just calls LoadLibrary). Those rules are enumerated in great detail here, but the important ones are excerpted here:

Before the system searches for a DLL, it checks the following:

  • If a DLL with the same module name is already loaded in memory, the system uses the loaded DLL, no matter which directory it is in. The system does not search for the DLL.
  • If the DLL is on the list of known DLLs for the version of Windows on which the application is running, the system uses its copy of the known DLL (and the known DLL's dependent DLLs, if any). The system does not search for the DLL.

If SafeDllSearchMode is enabled (the default), the search order is as follows:

  1. The directory from which the application loaded.
  2. The system directory. Use the GetSystemDirectory function to get the path of this directory.
  3. The 16-bit system directory. There is no function that obtains the path of this directory, but it is searched.
  4. The Windows directory. Use the GetWindowsDirectory function to get the path of this directory.
  5. The current directory.
  6. The directories that are listed in the PATH environment variable. Note that this does not include the per-application path specified by the App Paths registry key. The App Paths key is not used when computing the DLL search path.

So, unless you're naming your DLL the same thing as a system DLL (which you should obviously not be doing, ever, under any circumstances), the default search order will start looking in the directory from which your application was loaded. If you place the DLL there during the install, it will be found. All of the complicated problems go away if you just use relative paths.

Just write:

[DllImport("MyAppDll.dll")] // relative path; just give the DLL's name
static extern bool MyGreatFunction(int myFirstParam, int mySecondParam);

But if that doesn't work for whatever reason, and you need to force the application to look in a different directory for the DLL, you can modify the default search path using the SetDllDirectory function.
Note that, as per the documentation:

After calling SetDllDirectory, the standard DLL search path is:

  1. The directory from which the application loaded.
  2. The directory specified by the lpPathName parameter.
  3. The system directory. Use the GetSystemDirectory function to get the path of this directory.
  4. The 16-bit system directory. There is no function that obtains the path of this directory, but it is searched.
  5. The Windows directory. Use the GetWindowsDirectory function to get the path of this directory.
  6. The directories that are listed in the PATH environment variable.

So as long as you call this function before you call the function imported from the DLL for the first time, you can modify the default search path used to locate DLLs. The benefit, of course, is that you can pass a dynamic value to this function that is computed at run-time. That isn't possible with the DllImport attribute, so you will still use a relative path (the name of the DLL only) there, and rely on the new search order to find it for you.

You'll have to P/Invoke this function. The declaration looks like this:

[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern bool SetDllDirectory(string lpPathName);
Melanosis answered 14/1, 2012 at 11:24 Comment(23)
Another minor improvement on this may be to drop the extension from the DLL name. Windows will automatically add .dll and other systems will add the appropriate extension under Mono (e.g. .so on Linux). This may help if portability is a concern.Houseboy
+1 for the SetDllDirectory. You can also just change Environment.CurrentDirectory and all relative pathes will be evaluated from that path!Raulrausch
Even before this was posted, the OP clarified that he's making a plugin, so putting the DLLs in Microsoft's program files is sort of a non-starter. Also, altering the process DllDirectory or CWD might not be a good idea, they could cause the process to fail. Now AddDllDirectory on the other hand...Hausfrau
Your example of SetDllDirectory was a life-safer. Found this post by accident while trying to get GhostscriptSharp working on an Azure website. +1 and thanksAgnew
Thanks! I was trying to test if relative worked so I put one function relative and the others still full path to the same dll on a different location. Caused some Violation errorsOctennial
The most obvious reply is if the dll could be renamed (eg by a distributor) then that distributor will need some way of changing the name of the library being loaded.Zoubek
As far as the searching of the native assembly is concerned for making p/invoke calls it searches the application's root directory and all its sub-directories recursively So - The directory from which the application loaded. should be The directory and all its sub-directories from which the application is loaded.. Kindly correct me if I'm wrong.Vicinal
No, the search is not recursive, @RBT. I am quoting these rules from the official documentation. It isn't a mistake.Melanosis
Even if it is not mentioned in the documentation here but I believe it behaves this way. I did a quick test on this and I placed the native C++ assembly in bin\debug\mydir\myNativeAssembly.dll and still p/invoke calls succeeded while using [DllImport] attribute.Vicinal
Then there is something else going on there, @RBT. Perhaps you have a <probing> element in your application's .config file? Or maybe the sub-directory has the same name as the assembly? Or maybe you already loaded the DLL explicitly, so its using its known location to find it? There are a lot of possibilities, but I see no evidence that the search is recursive. Furthermore, even if it is on whatever version of Windows you're testing, that isn't part of the documented contract and I'm not going to add in undocumented implementation details.Melanosis
@Houseboy Your hint is also extremly important when working with Unity3D Engine even though using a DLL. It seems like the Mono framework in Unity may not use an extension in the DllImport statement even when importing a DLL in windows. Removing the .dll in Unity fixed my issue. Thanks.Synecology
@GameScripting: "You can also just change Environment.CurrentDirectory and all relative pathes will be evaluated from that path!" - True. Although that may not be the directory you set. Since this is a process-wide property, any thread can modify it at any time. There is absolutely no way to get current-working-directory-based code right. It's one of those tools you absolutely need to banish from your toolbox.Drachma
@Drachma sometimes you can use simple solutions for simple problems. In my specific case I had a windows service running as system user, so the default working dir is autom. set to C:\Windows\System32. Now when you have a class that useses DllImport to load a dll located in the install-dir for example at C:\Program Files\myapp it will fail. By simply setting the current working dir at service startup, all problems are gone.Raulrausch
Relying on the working directory is a potentially serious security vulnerability, @GameScripting, and especially ill-advised for something running with superuser permissions. Worth writing the code and doing the design work to get it right.Melanosis
How can I know the run-time path of my dll? Say, I have this code in the constructor public Data(Database databaseParam) { Logging.Log(4, "Initializing Data class..."); database = databaseParam; SetDllDirectory(????); // What should I use here to get path of that dll? }Crying
@Crying The whole point of the answer is you do not need to know this information. "All of the complicated problems go away if you just use relative paths." At any rate, the purpose of comments is to request clarification on an existing answer. If you have a new question, then ask a new question.Melanosis
Note that DllImport is more than just a wrapper on LoadLibrary. It also considers the directory of the assembly the extern method is defined in. The DllImport search paths can be additionally limited using DefaultDllImportSearchPath.Vitality
Just to point out another necessary use case for this: applications compiled to target "AnyCPU" can be executed as either 32-bit or 64-bit processes so in order to properly support this, you'd need to package the native assemblies for both architectures, then choose which to use at runtime.Yt
This is exactly what I need thank-you. Due to a plugin structure that we use that picks up managed DLLs in the bin directory, we need all unmanaged DLLs in their own folder. While we were able to DllImport by name the first dll, if it were to reference another DLL, it wouldn't work. Using the SetDllDirectory worked for me.Chiaki
What about the cross-platform solution, on Linux there is no such "kernel32.dll"Cosmonaut
For those coming here in 2022 and beyond, who are creating MSIX app packages, know that the DLL Search Order is different from what is documented here and you cannot use the PATH env variable. As far as I can tell, this is a gap with MSIX and only solution is to use the suggested SetDllDirectory API in code. Some links of interest: Link 1 Link 2Binghi
Actually it doesn't work this way on Linux for whatever reason. Even if you load a Library with the exact name X, Mono will occasionally not recognize it for use with DllImport. I don't know why that is but it's a huge headache. The reason why I'm searching for the solutions here in the first place.Fredericksburg
The relative path solution doesn't work for modern, cross-platform .NET since the DLL itself will have a different name and binary between Windows, macOS, and Linux. Still unsure how to solve this.Savior
C
42

Even better than Ran's suggestion of using GetProcAddress, simply make the call to LoadLibrary before any calls to the DllImport functions (with only a filename without a path) and they'll use the loaded module automatically.

I've used this method to choose at runtime whether to load a 32-bit or 64-bit native DLL without having to modify a bunch of P/Invoke-d functions. Stick the loading code in a static constructor for the type that has the imported functions and it'll all work fine.

Cathrin answered 12/1, 2012 at 14:46 Comment(4)
I'm not sure if this is guaranteed to work. Or if it just happens to on the current version of the framework.Couperin
@Code: Seems guaranteed to me: Dynamic-Link Library Search Order. Specifically, "Factors That Affect Searching", point one.Melanosis
Nice. Well my solution has a small additional advantage, as even the function name doesn't have to be static and known at compile time. If you have 2 functions with the same signature and a different name, you can invoke them using my FunctionLoader code.Hone
This sounds like what I want. I was hoping to use filenames like mylibrary32.dll and mylibrary64.dll, but I guess I can live with them having the same name but in different folders.Glabrous
H
33

If you need a .dll file that is not on the path or on the application's location, then I don't think you can do just that, because DllImport is an attribute, and attributes are only metadata that is set on types, members and other language elements.

An alternative that can help you accomplish what I think you're trying, is to use the native LoadLibrary through P/Invoke, in order to load a .dll from the path you need, and then use GetProcAddress to get a reference to the function you need from that .dll. Then use these to create a delegate that you can invoke.

To make it easier to use, you can then set this delegate to a field in your class, so that using it looks like calling a member method.

EDIT

Here is a code snippet that works, and shows what I meant.

class Program
{
    static void Main(string[] args)
    {
        var a = new MyClass();
        var result = a.ShowMessage();
    }
}

class FunctionLoader
{
    [DllImport("Kernel32.dll")]
    private static extern IntPtr LoadLibrary(string path);

    [DllImport("Kernel32.dll")]
    private static extern IntPtr GetProcAddress(IntPtr hModule, string procName);

    public static Delegate LoadFunction<T>(string dllPath, string functionName)
    {
        var hModule = LoadLibrary(dllPath);
        var functionAddress = GetProcAddress(hModule, functionName);
        return Marshal.GetDelegateForFunctionPointer(functionAddress, typeof (T));
    }
}

public class MyClass
{
    static MyClass()
    {
        // Load functions and set them up as delegates
        // This is just an example - you could load the .dll from any path,
        // and you could even determine the file location at runtime.
        MessageBox = (MessageBoxDelegate) 
            FunctionLoader.LoadFunction<MessageBoxDelegate>(
                @"c:\windows\system32\user32.dll", "MessageBoxA");
    }

    private delegate int MessageBoxDelegate(
        IntPtr hwnd, string title, string message, int buttons); 

    /// <summary>
    /// This is the dynamic P/Invoke alternative
    /// </summary>
    static private MessageBoxDelegate MessageBox;

    /// <summary>
    /// Example for a method that uses the "dynamic P/Invoke"
    /// </summary>
    public int ShowMessage()
    {
        // 3 means "yes/no/cancel" buttons, just to show that it works...
        return MessageBox(IntPtr.Zero, "Hello world", "Loaded dynamically", 3);
    }
}

Note: I did not bother to use FreeLibrary, so this code is not complete. In a real application, you should take care to release the loaded modules to avoid a memory leak.

Hone answered 12/1, 2012 at 13:55 Comment(9)
There is managed counterpart for LoadLibrary (in the Assembly class).Sailboat
If you had some code example, it would be easier for me to understand ! ^^ (Actually, it's a bit misty)Enrollment
@Sailboat Piccioni: If you meant Assembly.LoadFrom, this only loads .NET assemblies, not native libraries. What did you mean?Hone
I was meaning that, but I didn't know about this limitation. Sigh.Sailboat
Well, but don't call MessageBoxA. There's absolutely no reason to call ANSI functions in 2012. Call the Unicode version, MessageBoxW. And don't hard-code paths to system DLLs!!Melanosis
Of course not. That was just a sample to show that you can call a function in a native dll without using P/Invoke which requires a static path.Hone
Wow, this is really cool solution, thanks! Incredibly flexible! Should be the answer.Barong
Nice approach, but how to deal with strings encodings in this case?Heavenly
Strings ? Just add them to the delegate definition with MarshalAs like you would do in a dllimport attribute. It's a long time Jan.. but +1, this is really neat.. I've tested it, added a release method using FreeLibrary().Finegrain
C
17

Among all other good answers, after .NET Core 3.0, you can use NativeLibrary. For example in Linux you don't have such kernel32.dll. NativeLibrary.Load and Native.SetDllImportResolver can be the way to go:

        static MyLib()
        {
            //Available for .NET Core 3+
            NativeLibrary.SetDllImportResolver(typeof(MyLib).Assembly, ImportResolver);
        }

        private static IntPtr ImportResolver(string libraryName, Assembly assembly, DllImportSearchPath? searchPath)
        {
            IntPtr libHandle = IntPtr.Zero;
            if (libraryName == "MyLib")
            {
                if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
                {
                    libHandle = NativeLibrary.Load("xxxx.dll");
                }
                else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
                {
                    libHandle = NativeLibrary.Load("xxxx.so");
                }
            }
            return libHandle;
        }

        [DllImport("MyLib", CallingConvention = CallingConvention.Cdecl)]
        public static extern IntPtr foo(string name);
        

See also:

Cosmonaut answered 6/8, 2021 at 6:29 Comment(0)
V
8

It'll be simple if you know the directory where your C++ libraries will be present at runtime. I can see that this is the case in your problem statement. Your assembly named myDll.dll would be present inside myLibFolder directory inside temporary folder of the current user.

string str = Path.GetTempPath() + "..\\myLibFolder\\myDLL.dll"; 

You can continue using the DllImport statement using a constant string as shown below:

[DllImport("myDLL.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int DLLFunction(int Number1, int Number2);

Before you call the DLLFunction function (present in C++ library) in your C# code add following line of code:

string assemblyProbeDirectory = Path.GetTempPath() + "..\\myLibFolder\\myDLL.dll"; 
Directory.SetCurrentDirectory(assemblyProbeDirectory);

This instructs the .NET CLR to look for the unmanaged C++ libraries at the directory path which you obtained at runtime. Call to Directory.SetCurrentDirectory sets the application's current working directory to the specified directory. If your myDLL.dll is present at path represented by assemblyProbeDirectory path then it will get loaded. Then you can call the desired function through p/invoke.

Vicinal answered 19/1, 2017 at 13:36 Comment(2)
This worked for me. I have a folder "Modules" located in the "bin" directory of my executing application. There I'm placing a managed dll and some unmanaged dll's that the managed dll requires. Using this solution AND setting the probing path in my app.config allows me to dynamically load the required assemblies.Exerciser
For people using Azure Functions: string workingDirectory = Path.GetFullPath(Path.Combine(executionContext.FunctionDirectory, @"..\bin"));Flank
D
1

set the dll path in the config file

<add key="dllPath" value="C:\Users\UserName\YourApp\myLibFolder\myDLL.dll" />

before calling the dll in you app, do the following

string dllPath= ConfigurationManager.AppSettings["dllPath"];    
   string appDirectory = Path.GetDirectoryName(dllPath);
   Directory.SetCurrentDirectory(appDirectory);

then call the dll and you can use like below

 [DllImport("myDLL.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int DLLFunction(int Number1, int Number2);
Danidania answered 16/5, 2019 at 3:42 Comment(0)
H
1

Since .NET Core 3.0 - also works with .NET 5 & .NET 6 - you can use NativeLibrary.Load(string) to dynamically load unmanaged DLLs at runtime, which you can use via P/Invoke.

See this answer here on SO for more details: https://mcmap.net/q/144179/-how-to-select-the-path-for-dllimport-at-run-time-when-the-name-of-the-required-dll-can-change

Hohenstaufen answered 13/11, 2021 at 22:41 Comment(0)
T
0
//[?] Method Sample;
[System.Runtime.InteropServices.DllImport("ramdom_Kernel32.dll")] //[!] Error Sample
public dynamic MethodWithDllImport(){
  
}

partial static Main(){
  try{
    //[?] Exception Cannot Be Handled over the Attribute;
    //    handle where it is called;
    MethodWithDllImport();
  } 
  catch{
   //[?] use overloaded\other name methods
  }
}
Translator answered 18/12, 2021 at 20:47 Comment(0)
S
0

After some reseach and tries-errors, for dlls placed in unmanaged\dlls directory in the project root, it seems to be only possible via extending PATH environment variable on its startup :

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace biometric_sync
{
    internal static class Program
    {
        /// <summary>
        /// Главная точка входа для приложения.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);

            string workingDirectory = Environment.CurrentDirectory;
            // This will get the current PROJECT directory
            // where "Parent.Parent" => requied for assigned Debug|Release.x86|x64 configurations !
            string projectDirectory = Directory.GetParent(workingDirectory).Parent.Parent.FullName;
            var dllDirectory = projectDirectory + @"\\unmanaged\\dlls";
            Environment.SetEnvironmentVariable(
                "PATH",
                Environment.GetEnvironmentVariable(
                    "PATH", EnvironmentVariableTarget.Process
                ) + ";" + dllDirectory,
                EnvironmentVariableTarget.Process
            );

            Application.Run(new Form1());
        }
    }
}

Use Directory.GetParent(workingDirectory).Parent.FullName (less parent references) for anyCpu target.

Then the below code works well :

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.IO;

namespace sbxpc
{
    class SBXPCDLL
    {
        [DllImport("SBXPCDLL64.dll", CallingConvention = CallingConvention.Winapi)]
        static extern byte _ConnectTcpip(Int32 dwMachineNumber, ref IntPtr lpszIPAddress, Int32 dwPortNumber, Int32 dwPassWord);

        public static bool ConnectTcpip(Int32 dwMachineNumber, string lpszIPAddress, Int32 dwPortNumber, Int32 dwPassWord)
        {
            if (lpszIPAddress == null)
                return false;

            IntPtr string_in = Marshal.StringToBSTR(lpszIPAddress);
            try
            {
                byte ret = _ConnectTcpip(dwMachineNumber, ref string_in, dwPortNumber, dwPassWord);
                return ret > 0;
            }
            catch (Exception)
            {
                return false;
            }
            finally
            {
                Marshal.FreeBSTR(string_in);
            }
        }

    }
}
Sabbatarian answered 16/9, 2023 at 9:56 Comment(0)
S
0

It's late, but i have a solution : https://github.com/warny/All-purpose-Utilities/blob/master/Utils.Reflection/Reflection/DllMapper.cs

Use it like this :

public interface IKernel32 : IDisposable
{
    [External("GetTempPathA")]
    uint GetTempPath(uint nBufferLength, [Out] StringBuilder lpBuffer);
}

public class Kernel32 : DllMapper
{
    private delegate uint GetTempPathDelegate(uint nBufferLength, [Out] StringBuilder lpBuffer);

    [External("GetTempPathA")]
    private GetTempPathDelegate __GetTempPath;

    public uint GetTempPath(uint nBufferLength, [Out] StringBuilder lpBuffer) => __GetTempPath(nBufferLength, lpBuffer);
}

[TestClass]
public class DllMapperTests
{
    [DllImport("kernel32.dll")]
    static extern uint GetTempPath(uint nBufferLength, [Out] StringBuilder lpBuffer);

    [TestMethod]
    public void MapFromInterfaceTest()
    {
        using (var kernel32 = DllMapper.Emit<IKernel32>("kernel32.dll", CallingConvention.Winapi))
        {
            StringBuilder tempPath = new StringBuilder(' ', 1024);
            var i = kernel32.GetTempPath(261, tempPath);
            Assert.AreEqual((int)i, tempPath.ToString().Length);
        }
    }

    [TestMethod]
    public void MapFromClassTest()
    {
        using (Kernel32 kernel32 = DllMapper.Create<Kernel32>("kernel32.dll"))
        {
            StringBuilder tempPath = new StringBuilder(' ', 1024);
            var i = kernel32.GetTempPath(261, tempPath);
            Assert.AreEqual((int)i, tempPath.ToString().Length);
        }
    }
}
Sandglass answered 25/1 at 16:2 Comment(0)
P
-2

DllImport will work fine without the complete path specified as long as the dll is located somewhere on the system path. You may be able to temporarily add the user's folder to the path.

Property answered 12/1, 2012 at 13:53 Comment(1)
I tried placing it in the system Environment variables BUT it's still considered as non constant (logical, I think)Enrollment
M
-20

If all fails, simply put the DLL in the windows\system32 folder . The compiler will find it. Specify the DLL to load from with: DllImport("user32.dll"..., set EntryPoint = "my_unmanaged_function" to import your desired unmanaged function to your C# app:

 using System;
using System.Runtime.InteropServices;

class Example
{
   // Use DllImport to import the Win32 MessageBox function.

   [DllImport ("user32.dll", CharSet = CharSet.Auto)]
   public static extern int MessageBox 
      (IntPtr hWnd, String text, String caption, uint type);

   static void Main()
   {
      // Call the MessageBox function using platform invoke.
      MessageBox (new IntPtr(0), "Hello, World!", "Hello Dialog", 0);    
   }
}

Source and even more DllImport examples : http://msdn.microsoft.com/en-us/library/aa288468(v=vs.71).aspx

Mawkish answered 12/1, 2012 at 14:14 Comment(7)
Ok, I agree with your solution of using the win32 folder (simplest way of doing it) but how do you grant access to that folder to the Visual Studio debugger (and also to the compiled application) ? (Except manually running it as admin)Enrollment
If that is used for anything more than a debugging aid, it would fall through any review (security or otherwise) in my book.Urethrectomy
This is a pretty terrible solution. The system folder is for system DLLs. Now you require admin privileges and are relying on bad practices just because you're lazy.Cathrin
+1 for MikeP, -1 for this answer. This is a terrible solution, anyone who does this should be flogged repeatedly while being forced to read The Old New Thing. Just like you learned in kindergarten: the system folder does not belong to you, so you should not use it without permission.Melanosis
Okok, I agree with you, but my problem isn't resolved so... Which location would you recommend me then ?(Knowing that I can't use variables to set it up -Because it's waiting for a constant string-, so that I MUST use a location that's gonna be the same on every computer?) (Or is there any way to use a variables, instead of a constant, to perform it ?)Enrollment
@Kuroicloud666: Use a relative path and place your DLLs in the application directory. I believe Hans already suggested this. It's what everyone else does, and it works perfectly. Read up on the default search order for DLLs. You'll see that the app directory is the first one checked (with the exception of for known system DLLs for security reasons, which we've already established you're not creating), so this is guaranteed to work.Melanosis
I tried putting the DLL within "C:\\program files\\MyAppName\\MyDllName.dll" but I still have the "access denied" error...Enrollment

© 2022 - 2024 — McMap. All rights reserved.