I'm trying to load dll libraries during runtime using the following code so that I don't have to provide the user with lot of dll files along with the main executable file. I have inlude all the dll files as an embedded resource and also in the reference part I have include them and have set the CopyLocal property to false. But the problems here are:
1. All the dll are getting copied to Bin\Debug folder
2. I'm getting FileNotFoundException.
I did lot of searches to get these things resolved and finally I'm here. I got a similar code here but still couldn't do anything. What should I do to prevent this exception...??
Is there a better way to do the same thing for a Windows Form Application(Not WPF)...??
using System;
using System.Linq;
using System.Windows.Forms;
using System.Diagnostics;
using System.Reflection;
using System.Collections.Generic;
using System.IO;
namespace MyNameSpace
{
static class Program
{
static int cnt;
static IDictionary<string, Assembly> assemblyDictionary;
[STAThread]
static void Main()
{
AppDomain.CurrentDomain.AssemblyResolve += OnResolveAssembly;
if (cnt != 1)
{
cnt = 1;
Assembly executingAssembly = Assembly.GetExecutingAssembly();
string[] resources = executingAssembly.GetManifestResourceNames();
foreach (string resource in resources)
{
if (resource.EndsWith(".dll"))
{
using (Stream stream = executingAssembly.GetManifestResourceStream(resource))
{
if (stream == null)
continue;
byte[] assemblyRawBytes = new byte[stream.Length];
stream.Read(assemblyRawBytes, 0, assemblyRawBytes.Length);
try
{
assemblyDictionary.Add(resource, Assembly.Load(assemblyRawBytes));
}
catch (Exception ex)
{
MessageBox.Show("Failed to load: " + resource + " Exception: " + ex.Message);
}
}
}
}
Program.Main();
}
if (cnt == 1)
{
cnt = 2;
System.Threading.Thread.CurrentThread.Priority = System.Threading.ThreadPriority.Highest;
Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(Application_ThreadException);
Application.ApplicationExit += new EventHandler(Application_ApplicationExit);
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MainForm());
}
}
private static Assembly OnResolveAssembly(object sender, ResolveEventArgs args)
{
AssemblyName assemblyName = new AssemblyName(args.Name);
string path = assemblyName.Name + ".dll";
if (assemblyDictionary.ContainsKey(path))
{
return assemblyDictionary[path];
}
return null;
}
}
}
If I'm using something unnecessarily in my code then you can show me the right way... I'm a student working on Windows Form Application v4.0 project for my papers to be submitted.
If it is still the case that you must do this, then use this OnResolveAssembly method. There is no need to preload them into an array if you don't want to. This will load them the first time they are actually needed.
Then just:
mark it as a Resource in the file properties.
-Jesse
PS: This comes from http://www.paulrohde.com/merging-a-wpf-application-into-a-single-exe/
Try the following:
AppDomain.Current.BaseDirectory
then continue to the next resourceAppDomain.Current.BaseDirectory
. Do this in a try-catch and if it fails, notify the user. For this step to complete successfully you will need write access on the installation folder (usually a subfolder of "Program Files"). This will be solved by running the program as an administrator the first time only ao that the files are written on the file system.string
or andAssemblyName
as a parameter.