如何从运行时启动的 .dll 中启动 Windows 窗体

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6423524/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 17:07:57  来源:igfitidea点击:

How to launch a Windows Form from within a .dll launched at runtime

c#windowswinformsdllruntime

提问by MoonKnight

I have researched this a fair bit and cannot establish the correct approach. My problem is as follows: I have a winForms applications and from within it I wish to launch a time intesive .dll. I can do this using System.Reflection no problem like this

我对此进行了相当多的研究,但无法建立正确的方法。我的问题如下:我有一个 winForms 应用程序,我希望从中启动一个时间密集的 .dll。我可以使用 System.Reflection 做到这一点,没有这样的问题

    // Execute the method from the requested .dll using reflection (System.Reflection).
    //[System.Runtime.InteropServices.DllImport(strDllPath)]
    DLL = Assembly.LoadFrom(strDllPath);
    classType = DLL.GetType(String.Format("{0}.{0}", ListUfCmdParams[1]));
    classInst = Activator.CreateInstance(classType);
    XmlExpInfo = classType.GetMethod(DllParams[0]);
    XmlExpInfo.Invoke(classInst, paramObj);

    // Return something.
    return String.Format("Method '{0}' from '{1}{2}' successfully executed!", 
    ListUfCmdParams[2], ListUfCmdParams[1], strDotDll);

this works great but the process being called is so time intensive I want to display to the user what is happening. To do this I have included in the .dll file a WinForm which has a progressBar and some other attributes. When I do this I get an exception. This occurs when "Activator.CreateInstance()" attempts to do its work: MissingMethodException "Cannot create an abstract class". I have come across this error before when I using partial classes and I had to remove the "partial" keyword from my classes to enable the .dll to execute correctly (which I just about got away with!). I cannot remove this "partial" keyword from the above winForms class so, the question is "How do I call a winForm from within my .dll (if indeed it is possible)?" so that the .dll can show its progress as it executes from the calling application?

这很好用,但被调用的过程非常耗时,我想向用户显示正在发生的事情。为此,我在 .dll 文件中包含了一个 WinForm,它具有一个进度条和一些其他属性。当我这样做时,我得到了一个例外。当“Activator.CreateInstance()”尝试完成其工作时会发生这种情况:MissingMethodException“无法创建抽象类”。我之前在使用部分类时遇到过这个错误,我不得不从我的类中删除“partial”关键字以使 .dll 能够正确执行(我刚刚逃脱了!)。我无法从上面的 winForms 类中删除这个“部分”关键字,所以问题是“如何从我的 .dll 中调用 winForm(如果确实可能)?” 所以这样 。

Thanks for your time,

谢谢你的时间,

Nick

缺口

Ps. I have read the following threads and they are somewhat ambiguous:

附言。我已经阅读了以下线程,它们有些模棱两可:

A DLL with WinForms that can be launched from A main app

可以从主应用程序启动的带有 WinForms 的 DLL

et al.

等。

采纳答案by MoonKnight

I have just seen this question again and thought I would update as to how I eventually did this.

我刚刚再次看到这个问题,并认为我会更新我最终是如何做到这一点的。

In the end I found the following to be the most effective way of performing the above for what I wanted. First you launch a WinForm which holds your progress information. Second youu envoke your "worker" method from within the "Shown" event.

最后,我发现以下是针对我想要的执行上述操作的最有效方法。首先,您启动一​​个保存您的进度信息的 WinForm。其次,您可以从“Shown”事件中调用您的“worker”方法。

The code for the first part i.e. to call the WinForm using Reflection is provided below:

下面提供了第一部分的代码,即使用反射调用 WinForm:

    // Execute the method from the requested .dll using reflection (System.Reflection).
    Assembly DLL = Assembly.LoadFrom(strDllPath);
    Type classType = DLL.GetType(String.Format("{0}.{0}", strNsCn));
    object classInst = Activator.CreateInstance(classType, paramObj);
    Form dllWinForm = (Form)classInst;  
    dllWinForm.ShowDialog();

I hope this helps someone else.

我希望这对其他人有帮助。

回答by C.Evenhuis

You should not make a callee (the dll) aware of it's caller (the form). Instead you could enrich the class in your dll that performs the time intensive method with a ProgressUpdatedevent:

你不应该让被调用者(dll)知道它的调用者(表单)。相反,您可以丰富 dll 中的类,该类使用ProgressUpdated事件执行时间密集型方法:

public event ProgressUpdatedHandler ProgressUpdated;
public delegate void ProgressUpdatedHandler(object sender, int stepsCompleted, int stepsTotal)

This way the form could simply assign a handler for that event, and the dll could raise the event whenever it can indicate what the progress is.

通过这种方式,表单可以简单地为该事件分配一个处理程序,并且 dll 可以在它可以指示进度时引发该事件。