7

I have a C# project that contains 1 EXE and about 7 DLLs. What I would like to have is a folder beside the EXE called "Library" (or something similar) that contains all the DLLs so that it is a bit more organized and looks better for the end user.

I know this can be done using an AppConfig but the I don't want another file beside the EXE. All I want is the main EXE and the folder.

Is it possible to use AppConfig and embed it or load the DLLs without using a AppConfig that won't change how I currently use my DLLs? I know you can load a DLL at run time but I don't think that is what I am looking for.

Thanks!

EDIT

I know the pros and cons to doing this, so please only answers on how to do this and no advice as to why I should or should not do this.

Landin Martens
  • 3,283
  • 12
  • 43
  • 61
  • 1
    Your idea of "organized" is very incompatible with the CLR's idea. Which **strongly** prefers the DLLs in the same folder as the EXE. Or the GAC. You can invoke DLL Hell by writing an event handler for the AppDomain.CurrentDomain.AssemblyResolve event. Don't do it. – Hans Passant Aug 19 '12 at 20:58
  • 7
    Not to be rude but I did not ask if I should do it I ask how to do it. – Landin Martens Aug 19 '12 at 21:12
  • 3
    The AssemblyResolve event was the rude answer. The rest was advice, you can ignore it as you please. – Hans Passant Aug 19 '12 at 21:17

4 Answers4

2

Use System.Reflection.Assembly.LoadFrom(path).

LoadFrom will allow it to look in the same folder as the targetted dll for any dependencies. If you use Load, then it will not consider dlls that are sitting in the same folder as the dll you Load.

I know this doesn't directly answer your question, but manually calling LoadFrom on the DLLs early in your process startup should do the trick if you want an "xcopy" installable .net app or something.

Adi Lester
  • 24,731
  • 12
  • 95
  • 110
doug65536
  • 6,562
  • 3
  • 43
  • 53
  • The problem with using that is that I can't have any referenced DLLs so every call has to be done using reflection. – Landin Martens Aug 19 '12 at 21:37
  • I see. I assumed it was some sort of plugin model, for example, something abstracted behind interfaces. – doug65536 Aug 19 '12 at 21:42
  • 2
    CLR loads assemblies on-demand, and it doesn't load if the assembly is already loaded into the app-domain. So, if you force-load all your assemblies upfront using reflection, you can still use your strong references. Only you will not have the dlls in the app-folder, and clr will not look for it since they are already loaded. This means manually/automagically moving dlls from root-folder to your fav folder – LadderLogic Aug 20 '12 at 02:12
  • The think that makes this work is you will do the Load call before the on-demand load happens. When you go to access the DLL, it will use the one you Load'ed. As long as it is similar enough to the one you used as a reference, it will work. – doug65536 Dec 12 '12 at 17:40
1

PrettyBin is your solution. It does this beautifully!

avijendr
  • 3,958
  • 2
  • 31
  • 46
0

SetDllDirectory() + carefully coded AssemblyResolve. Works for me in a nontrivial project, with no DLL hell.

https://github.com/TASVideos/BizHawk/blob/d05ddabf5f22debf47369f94868462a75ea0b466/BizHawk.Client.EmuHawk/Program.cs

zeromus
  • 1,648
  • 13
  • 14
0

I created new console application-launcher. In app folder contains my EXE file - MyApp.exe and all DLLs.

static void Main(string[] args)
    {
        var process = new Process
            {
                StartInfo =
                     {
                       FileName = "app\\MyApp.exe",
                     }
            };
        process.Start();
    }

If you want the application to be launched when you drag certain files onto the EXE:

class Program
{
    static void Main(string[] args)
    {
        if (args.Length > 0)
        {
            String FileName = System.IO.Path.GetDirectoryName( System.Reflection.Assembly.GetExecutingAssembly().Location )
                                        + "\\app\\MyApp.exe";
            ProcessStartInfo startInfo = new ProcessStartInfo(FileName);
            startInfo.WindowStyle = ProcessWindowStyle.Normal;
            startInfo.Arguments = args[0].ToString();
            Process.Start(startInfo);
        }

        else { 
            var process = new Process
                {
                    StartInfo =
                              {
                                  FileName = "app\\MyApp.exe",
                              }
                };
            process.Start();
        }
    }
}
gevaraweb
  • 912
  • 7
  • 19