How to reference C# dll located in different folder to a C# winforms exe in different folder which uses Interface exposed by that dll

Ezhirko picture Ezhirko · Oct 22, 2013 · Viewed 7.1k times · Source

I have a C# windows forms that uses a Utility.dll located in different folder than that of the EXE location. Utility.dll contains a class UtilityClass and an interface ILoadString. When i do not inherit ILoadString interface in my Form1.cs class, i am successfully able to load the Utility.dll through AppDomain.AssemblyResolve Event in Program.cs.

The problem arises when i try to inherit ILoadString interface in Form1.cs. When i try to run the project, i get an FileNotFoundException from visual studio saying "Could not load file or assembly 'Utility, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified." The control does not even come to static void Main() in Program.cs. I think CLR is trying to load Utility.dll in the beginning itself as my Form1.cs is inheriting ILoadString.

Note: In Add reference Utility.dll 's copy local is set to "false". so Exe folder do not contain this dll.

How do i load Utility.dll from other folder in this case? Any help appreciated.

Thanks in advance.

I am pasting my code below.

using System.Reflection;

namespace SampleForm
{
    static class Program
    {
    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main()
    {
        AppDomain currentDomain = AppDomain.CurrentDomain;
        currentDomain.AssemblyResolve += new ResolveEventHandler(MyResolveEventHandler);
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Form1());
    }

    private static Assembly MyResolveEventHandler(object sender, ResolveEventArgs args)
    {
        Assembly MyAssembly, objExecutingAssemblies;
        string strTempAssmbPath = "";
        objExecutingAssemblies = Assembly.GetExecutingAssembly();
        AssemblyName[] arrReferencedAssmbNames = objExecutingAssemblies.GetReferencedAssemblies();
        foreach (AssemblyName strAssmbName in arrReferencedAssmbNames)
        {
            if (strAssmbName.FullName.Substring(0, strAssmbName.FullName.IndexOf(",")) == args.Name.Substring(0, args.Name.IndexOf(",")))
            {
                strTempAssmbPath = "D:\\Ezhirko\\SampleForm\\bin\\Common\\" +
                    args.Name.Substring(0, args.Name.IndexOf(",")) + ".dll";
            }
        }       
        MyAssembly = Assembly.LoadFrom(strTempAssmbPath);
        return MyAssembly;
    }
}

My Windows form here....

using Utility;

namespace SampleForm
{
    public partial class Form1 : Form, ILoadString
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
        string Name = string.Empty;
        UtilityClass obj = new UtilityClass();
        Name = obj.GetName();
        this.lblHello.Text = Name;
        ChangeName();
    }


    public void ChangeName()
    {
        this.lblHello.Text = "InterFace Called !";
    }
}

This is UtilityClass.cs from Utility.dll

namespace Utility
{
    public class UtilityClass
    {
        private string sName = string.Empty;

        public UtilityClass()
        {
            sName = "My Name";
        }

        public string GetName()
        {
            return sName;
        }
    }
}

This is interface ILoadString.cs from Utility.dll

namespace Utility
{
    public interface ILoadString
    {
        void ChangeName();
    }
}

Answer

Avi Turner picture Avi Turner · Oct 22, 2013

Is there a specific reason you have copy local is set to "false"?
It think you would be better off setting it to true.
Another option would be copying it to your bin folder using build events, or loading it dynamically using reflection.
But again, as I said, I think it would be better to simply set copy local to true.

EDIT: (as per Ezhirko's Comment)

You can add loading the assemblies on the static constructor of Program or in SampleForm:

static class Program
{
    static Program()
    {
        //Loads assemblies. 
    }

   //the rest of your code...

}