【问题标题】:Running an exe converted to a dll from another exe运行从另一个exe转换为dll的exe
【发布时间】:2016-09-21 18:28:52
【问题描述】:

我有一个功能齐全的应用程序,已转换为 Dll。

我需要能够从 exe 中运行该应用程序(现在是 dll)。我已将 dll 添加为对新 exe 的引用,并尝试从 dll 中使用的命名空间中实例化一个 frmMain 对象,并像在任何其他应用程序中一样显示它。

但是,在我转换为 dll 的 exe 中的几个引用中,我得到了一堆空引用异常。

我也试过这里的解决方案Launch Dll using C# program 并尝试跳转到 Program.cs Main() 函数,此时我得到一个“必须在应用程序中创建第一个 IWin32Window 对象之前调用 SetCompatibleTextRenderingDefault”。错误。

这里是dll的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()
        {

        }
    }
}

这是新的应用程序代码

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);
            }
        }

谁能向我解释为什么这不起作用或指出我正确的方向?我超级困惑,不是自愿这样做的(老板告诉我的)

【问题讨论】:

  • 为什么要使用反射来访问 DLL?为什么不直接访问它呢?我认为您提到的所有问题都源于您正在上游使用您的 DLL 的事实。只需引用它并从中实例化您需要的任何类。当然,您必须调整访问修饰符。
  • 我真的不确定。你能给我一个例子吗?我很抱歉,但这是我第一次真正使用实际显示表单等的 dll,而我不仅仅是调用 dll 中的方法并获得结果。
  • 道歉,但我不应该给你举个例子。要么你知道怎么做,要么你不知道,在这种情况下,我建议你买一本关于 C# 和 .NET 的书或教程,并学习如何编码。无论哪种方式,这都是本网站的主题。

标签: c# .net windows dll


【解决方案1】:

您不需要反射,也不需要执行原始 .exe 文件的 Main() 方法(实际上,如果该项目只是一个普通的 DLL,您可能应该删除它)。

您不需要反射,因为一旦您将程序集作为引用添加到新项目中,所有公共类型和成员都可以在新项目中访问。只需确保已将 frmMain 声明为 public(这是 Visual Studio 中的默认设置,因此它可能已经是 public)。然后,您需要做的就是显示表单通常会做的事情,而不是所有的反射繁琐:

frmMain form = new frmMain();

form.Show();

甚至只是:

new frmMain().Show();

您不需要执行Main() 方法,因为它所做的只是您的新项目已经完成的工作:

  • [STAThread] 将入口点线程(成为主 UI 线程)设置为 STA 单元模型。但是由于您的新项目也是(看起来)一个 Winforms 程序,您已经有了一个入口点和一个已正确配置的主 UI 线程。正是这个线程引发了button1Click 事件,因此当调用button1_Click() 方法时,您正在该线程中执行。
  • 同样,设置视觉样式和文本渲染的调用。您无需再次调用它们,因为您的新项目在启动时调用了它们。
  • 最后,调用Application.Run(new frmMain())。这个调用有三个效果:它创建一个frmMain() 的实例(你可以按照我上面提到的那样自己做),然后将该实例传递给Application.Run() 方法,以便该方法可以在表单上调用Show() 方法(同样,您可以自己做),然后Run() 方法位于循环调度窗口消息中。你也不需要这样做,因为你已经在一个 Winforms 程序中,它已经调用了Application.Run(),并且已经在发送窗口消息(这就是Click 事件首先被引发的方式)。

所以,停止尝试调用 Main() 方法,只需确保您要使用的表单类是 public,以便它在引用程序集的项目中可见,然后创建并显示 frmMain 对象如果它在同一个项目中声明,你会怎么做。

【讨论】:

    【解决方案2】:

    我认为这是因为类程序的访问修饰符只需将其更改为 public。
    另外,如果您不加载可更改的 dll(动态),为什么不像通常使用其他 dll 那样将其引用到项目并从程序类调用 main(您仍然需要程序类是公共的)

    【讨论】:

    • 因为我有 dll 作为参考,所以只需执行 VTRS.Program.frmMain Form1 = new VTRS.Program.frmMain();然后做Form1.Show();就那么简单 ?在将程序类更改为公开之后。
    • 出于某种原因,我只是预计它会比这更复杂。我已经从 dll 中调用了一百万零一个方法,只是假设启动应用程序并不容易。
    • no frmMain 不是类程序的属性,但您可以这样做:VTRS.frmMain form1=new ... 并且您可以调用程序类中的任何方法,例如 VTRS.Program.invokeMain();
    • 呃。在那里上课。我的错 。一会儿我试试。
    • 一个 dll 只是一堆类,而 EXE 也是一堆类,区别在于 EXE 包含一个结构,所以 CLR 可以自动启动它,该结构只是一个名为Main(string[] args) 的静态方法
    【解决方案3】:

    在解决方案资源管理器中,在您的项目视图中右键单击引用 --> 添加新引用 --> 浏览 --> 查找 VTRSTCACodeMaintenance.dll(它应该在您的 \bin\debug 文件夹中)-> 双击它--> 点击确定。 基本上就是这样。

    【讨论】:

    • 我有那个。不过还是谢谢
    猜你喜欢
    • 2015-09-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-12
    • 1970-01-01
    • 2012-05-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多