如何将程序集加载到内存并执行

6

我正在做的事情是:

byte[] bytes = File.ReadAllBytes(@Application.StartupPath+"/UpdateMainProgaramApp.exe");
Assembly assembly = Assembly.Load(bytes);
// load the assemly

//Assembly assembly = Assembly.LoadFrom(AssemblyName);

// Walk through each type in the assembly looking for our class
MethodInfo method = assembly.EntryPoint;
if (method != null)
{
    // create an istance of the Startup form Main method
    object o = assembly.CreateInstance(method.Name);
    // invoke the application starting point
    try
    {
        method.Invoke(o, null);
    }
    catch (TargetInvocationException e)
    {
        Console.WriteLine(e.ToString());
    }
}

问题在于它抛出了TargetInvocationException异常——它发现这个方法是主方法,但由于这一行而抛出了此异常:
object o = assembly.CreateInstance(method.Name);

o仍然为空。所以我深入研究了一下堆栈跟踪,实际的错误是:

InnerException = {"在程序中创建第一个 IWin32Window 对象之前应调用 SetCompatibleTextRenderingDefault"}(这是我的翻译,因为它给我提供了一半希伯来语和一半英语的堆栈跟踪,因为我的 Windows 是希伯来语。)

我做错了什么?

3个回答

4

入口方法是静态的,因此应该使用空值作为“实例”参数来调用它。尝试使用以下内容替换您的Assembly.Load行后面的所有内容:

assembly.EntryPoint.Invoke(null, new object[0]);

如果入口方法不是公共的,您应该使用允许您指定BindingFlags的Invoke重载。

1

如果你查看任何WinForm应用程序的Program.cs文件,你会发现总是有这两行代码

Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);

你需要在你的汇编代码中调用它们。至少这是你的异常信息所说的。


@Eugen,我该怎么办?我正在调用main方法,这应该会激活这些行,不是吗? - Eli Braginskiy
你有汇编源代码的访问权限吗?如果是,那么在方法内创建一个名为“Init”的方法,并将这两行代码放入其中,在调用Main方法之前调用Init方法。如果没有源代码,那么我需要想一想 :) - Eugen
顺便问一下,你没有提及你的应用程序是什么?如果在从该程序集调用Main方法之前在应用程序中调用这些行,也会有所帮助。 - Eugen
@Eugen我有源代码,我创建了这个init。现在我正在尝试以下内容:codeobject oo = assembly.CreateInstance("Init");code但是对象"oo"仍然为空-为什么? - Eli Braginskiy
2
你不能在一个方法上调用CreateInstance。你需要调用该方法。请参考此文章获取示例 http://www.daniweb.com/software-development/csharp/threads/98148 - Eugen
在这一行中:code_Type = assembly.GetType("UpdateMainProgaramApp");code,我应该写命名空间(UpdateMainProgramApp)还是因为这是我的类:codepublic partial class Form1 : Formcode,我应该写“Form1”?因为我尝试了两种方式,但_Type仍然为空... - Eli Braginskiy

0

把它叫做它自己的process,怎么样?


我需要将它加载到内存中,因为我之后需要删除其中的一个dll...所以那并没有帮助。 - Eli Braginskiy
但是调用另一个进程也会导致其加载到内存中。我认为如果一个已经被加载并且包含该进程的 DLL 仍然在运行,你是无法删除它的。参见:在不关闭应用程序的情况下删除 DLL - surfen
@surfen 确切地说 - 你所看到的 - 第一个答案是在说明:如果将应用程序加载到内存中,则该程序集与之无关 - 因此可以将其删除。 - Eli Braginskiy
哦,我明白了...不错的技巧 :) 但是你正在加载exe,所以如果exe引用另一个dll,那么dll程序集将会被关联并阻止,对吧? - surfen
我不确定,但我在努力找出来 :) - Eli Braginskiy
@Blue 引用的程序集也将被加载到内存中并锁定。如果您想在程序集加载到内存时能够删除它,您需要将程序集复制到其他位置,以便您可以从另一个位置加载它(保持原始程序集未锁定)。 - Justin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接