能否在没有exe加载的情况下执行.NET dll?

24

我想知道是否有办法在不创建.EXE文件的情况下,在新进程中执行静态.DLL方法?

据我所知,对于本地Win32/64 DLL来说,这是不可能的。那.NET DLL程序集呢?

更新:我忘了提到我主要感兴趣的是以编程方式实现这一点(具体来说是从C#代码实现)。

谢谢!

结论:尽管没有人“敢”明确说明,答案似乎都倾向于“否定”。需要通过其中一种传统方式(EXE、PowerShell等)启动进程,然后让该进程加载DLL并执行其中的代码。我想我错误地期望管理的DLL能够做更多的事情。

再次感谢所有发表意见的人!


你是指从命令行或运行对话框中,还是从另一个应用程序中? - Justin
5
rundll32需要一个本地的dll文件,至少是用于它打算执行的部分。 - Lasse V. Karlsen
2
创建自己的托管rundll32,使用Activator.CreateInstance和/或反射非常简单。或者只需一个快速的控制台应用程序,这并不需要火箭背包。 - Hans Passant
@Hans:你说得对。当然,这真的很简单——不过,我的问题的关键是它是否也绝对必要。我想现在我知道了。 :) - aoven
我也曾经想过同样的问题,后来我意识到可以将EXE作为库而不是DLL使用。在我的情况下,我正在使用托管的EXE作为无需注册的COM库。您可以添加一个静态的Main()方法来实现可执行功能,因此它既可以作为库又可以作为可执行文件。 - transistor1
1
可以通过在命令行中调用 rundll(32).exe your_dll_name,your_entry_point 或者按照下面的 C# 代码所述启动进程来运行本地的 x86 或 x64 dll。 - Darien Pardinas
5个回答

18

打开PowerShell提示符。

  [Reflection.Assembly]::LoadFile("Name of your dll")
  [Your.NameSpace.And.TypeName]::YourMethod()

我看到您想从C#获取这个。

使用程序集限定名称创建类型:

 var t = Type.GetType("NameSpace.Type,Name Of Dll");
 var m = t.GetMethod("NameOfMethod");
 m.Invoke(null, new object[] { params });

这应该能帮助您入门。

我不太清楚您所说的“在新进程中”的确切含义,但将其包装成一个.exe/.ps1文件并通过命令行选项启动不应该太难。

因此,您不必为要调用的每个DLL创建新的.exe。

但是,如果您想启动一个新进程,您应该启动一个新进程,这通常是通过启动一个新的.EXE来完成的。


1
我曾说过:“在一个新的进程中”。 :) - aoven
PowerShell可能会解决问题。只有一个问题:它是否包含在每个Visual Studio 2010安装中,还是需要单独安装? - aoven
不知道 Visual Studio 是否会随附 Powershell 安装。它是 Windows 7 和 Windows 2008 的一部分。 - GvS
2
这个应该不难将其打包成一个.exe/.ps1文件,并可以通过命令行选项启动。 我知道那个选项。我特别问的是是否还有其他方法?你的回答似乎是否定的。如果在接下来的几个小时里没有其他人提供解决方案,我会接受你的回答。 - aoven
如果你提供启动PowerShell的代码(最好是隐藏的新进程),并且实际执行此操作,那么PowerShell可能会非常酷。 - BrainSlugs83

14

选项1: .NET InstallUtil(普通.NET安装的一部分)

添加对System.Configuration.Install的引用,然后将类似以下代码放入程序集中:

[System.ComponentModel.RunInstaller(true)]
public class Sample : System.Configuration.Install.Installer
{
    public override void Uninstall(System.Collections.IDictionary savedState)
    {
        base.Uninstall(savedState);

        this.Context.LogMessage("This can be in a .dll.");
        // Do your thing...
    }
}

然后滥用.NET InstallUtil:

%windir%\Microsoft.NET\Framework\v2.0.50727\installutil /logtoconsole=false /logfile= /u [your assembly .dll here]

如果没有所有命令行参数禁用日志记录,可能会有点混乱。

选项2:使用本地rundll32反向P/Invoke静态类方法

2016年编辑:现在是一个Nuget包:UnmanagedExports源代码)!

未知的MSIL指令(msdn论坛,2007)链接到IL程序员参考手册(10/3/2000,第74页)的beta 1版本,其中说明:

如果指定了fromunmanaged,则 运行时将自动生成一个thunk,该thunk将转换不受托管的 方法调用为托管调用,调用该方法,并将结果返回给 不受管辖的环境。

Expert .NET 2.0 IL assemblerInside Microsoft. NET IL Assembler中有更多细节。(最佳搜索关键字:ilasm vtentry)。

相关阅读:

Unmanaged Exports: Cannot compile assembly(stackoverflow,2010年)

Unmanaged Exports / RGiesecke.DllExport.dll (stackoverflow, 2010) - Unmanaged Exports和RGiesecke.DllExport.dll

Create a C# DLL That Can Be Imported in a Delphi App Using stdcall (stackoverflow, 2009) - 创建C# DLL并使用stdcall在Delphi应用程序中导入

C# Project Template for Unmanaged Exports (Robert Giesecke, 2010) - msbuild, vs2010集成的Unmanaged Exports的C#项目模板

IKVM.Reflection Update: export static managed methods as unmanaged DLL exports (mono, 2011) - 将静态托管方法导出为非托管DLL出口的IKVM.Reflection更新

Simple Method of DLL Export without C++/CLI (codeproject, 2009) - 不使用C++/CLI的简单DLL导出方法,不支持64位

How to Automate Exporting .NET Function to Unmanaged Programs (codeproject, 2006) - 支持64位的.NET函数自动导出到非托管程序的方法

Has anything been added to .Net 4.0 to support "Reverse P/Invoke" scenarios? (msdn forum, 2010) - .Net 4.0是否新增支持“反向P/Invoke”场景的功能? 包含代码清单

非托管代码可以包装托管方法(codeproject,2004)

潜在的缺点:

通过反向 P/Invoke(非托管到托管代码的回调)存在陷阱(msdn blog,2006)

反向 P/Invoke 和异常(msdn blog,2008)


4
对于创新的方法,我点个赞。我会记住这个方法,以备将来之需! :) - aoven
InstallUtil是.NET的一部分,因此您可以在运行程序集的任何地方使用它;PowerShell则不是那么保证(例如,Windows XP)。还应清楚哪个版本的框架将运行。 :) - user423430
MSBuild内联任务:在XML文件中的C#代码片段,编译并在内存中执行。绕过应用程序白名单。 http://subt0x10.blogspot.com/2016/09/bypassing-application-whitelisting.html - user423430

1

查看随 Windows 一起安装的 rundll32.exe 程序。如果您了解有关 dll 的某些信息,有时可以使用此程序在该 dll 中运行代码。


4
这是.NET,不是本地dll。 - Dan Abramov

0

您可以使用 rundll32.exe dll_name,method_name 来启动进程并运行 DLL 函数。在 C# 中,您可以像这样实现:

myProcess = new Process {StartInfo = {FileName = "rundll32.exe", Arguments = "my_dll_name.dll,my_function_name"}};
myProcess.Start();

请确保 DLL 文件在您的 PATH 中。如果您想运行某种单元测试,请确保在 TearDown / CleanUp 方法中杀死进程:myProcess.Kill(),否则 DLL 可能仍然被加载,您将无法在开发过程中覆盖它。您还应该查看this article,了解一个命令行应用程序,它将杀死所有持有您的 DLL 的进程,并将其添加到 Pre-Build 事件中:freelib.exe my_dll_name.dll


0

一个 .NET 程序集可以在 PowerShell 中加载。(嗯,PowerShell 是一个 EXE,但不专门用于运行任何特定程序集的代码)


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