Hunter Dishner
Hunter Dishner

Reputation: 60

Running an exe converted to a dll from another exe

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

Answers (3)

Peter Duniho
Peter Duniho

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:

  • The [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.
  • Likewise, the calls to set the visual styles and text rendering. You don't need to call these again, because your new project called them when it started.
  • Finally, the call to 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

αNerd
αNerd

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

Abdo
Abdo

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

Related Questions