Reputation: 60
I have a completely functioning application that I have converted to a Dll.
I need to be able to run that application (now dll) out of an exe . Ive added the dll as a reference to the new exe and have tried to just instantiate a frmMain object from the namespace used in the dll and show it like I would in any other application.
However, I get a bunch of null reference exceptions in several of the references that I had in the exe that I converted to a dll.
I've also tried the solution here Launch Dll using C# program and tried jumping to the Program.cs Main() function at which point I get a "SetCompatibleTextRenderingDefault must be called before the first IWin32Window object is created in the application." error.
Here is the dll's program.cs
namespace VTRS
{
class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new frmMain());
}
//had to add this because exe can't find Main
public void invokeMain()
{
Main();
}
//you have to have a constructor for the exe to instantiate this class
public Program()
{
}
}
}
and here is the new applications code
private void button1_Click(object sender, EventArgs e)
{
try
{
System.Reflection.Assembly dll1 = System.Reflection.Assembly.LoadFile(Application.StartupPath + "\\VTRSTCACodeMaintenance.dll");
if (dll1 != null)
{
object obj = dll1.CreateInstance("VTRS.Program");
if (obj != null)
{
System.Reflection.MethodInfo mi = obj.GetType().GetMethod("invokeMain");
mi.Invoke(obj, new object[0]);
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
Can anyone explain to me why this doesn't work or point me in the right direction? I'm super confused and am not doing this by choice (I'm being told to by the boss)
Upvotes: 0
Views: 757
Reputation: 70652
You do not need reflection, nor do you need to execute the Main()
method of your original .exe file (indeed, you should probably just remove it, if that project is intended to just be a plain DLL).
You don't need reflection because, once you've added the assembly as a reference in your new project, all of the public types and members are accessibly in your new project. Just make sure you've declared frmMain
as public
(this is the default in Visual Studio, so it may already be public
). Then instead of all that reflection rigmarole, all you need to do is what you'd normally do to show a form:
frmMain form = new frmMain();
form.Show();
or even just:
new frmMain().Show();
You don't need to execute the Main()
method, because all it does is work that your new project already does:
[STAThread]
sets the entry point thread (which becomes the main UI thread) to the STA apartment model. But since your new project is also (it seems) a Winforms program, you already have an entry point and a main UI thread that has been correctly configured. It's this thread in which the Click
event for button1
is raised, and so you are executing in that thread when the button1_Click()
method is called.Application.Run(new frmMain())
. This call has three effects: it creates an instance of frmMain()
(which you can do yourself as I noted above), it then passes that instance to the Application.Run()
method so that method can call the Show()
method on the form (again, you can do that yourself), and then the Run()
method sits in a loop dispatching window messages. You also don't need to do that because, again, you are already in a Winforms program, which has already called Application.Run()
, and is already dispatching window messages (which is how the Click
event got raised in the first place).So, stop trying to invoke the Main()
method, just make sure the form class you want to use is public
so it's visible from projects that reference the assembly, and just create and show the frmMain
object the way you would if it were declared in the same project.
Upvotes: 1
Reputation: 528
In Solution Explorer, in your project view right click on References --> Add New Reference --> Browse --> Find VTRSTCACodeMaintenance.dll(it should be in your \bin\debug folder) --> double click it --> click Ok. That is basically.
Upvotes: 0
Reputation: 332
I think it's because of the access modifier of the class program just change it to public.
also if you don't load a changeable dll (dynamic) why you don't just reference it to the project as you would normally do with other dll's and call the main from the program class (you still need program class to be public)
Upvotes: 0