哪种方法更好:Process.Start或直接调用DLL?

时间:2013-01-24 11:20:05

标签: c# dll native exe process.start

在我们的团队中,我们面临着这样的选择:我们需要调用外部第三方代码并从C#代码处理其输出。

第三方代码有两种形式:dll和单exe文件集(可能单独调用这些dll)。可能的方法可能是:使用Process.Start语句来运行可执行文件并捕获其输出。另一个是直接致电dll

我试图了解我们应该使用哪种方法。

一方面调用可执行文件很简单,但另一方面 - 它感觉不健壮。

一方面调用dll看起来更正确的方式来完成这项工作,但另一方面 - 为我们在本机{{1}中的所有函数提供C#绑定可能真的很复杂。代码。

但是我需要对这个主题进行更实质性的分析才能做出最终决定。以前是否有人面对同样的问题,也许你可以分享你的发现。

这将非常有用!

编辑:我在谈论这种特殊情况下的视频转换。我需要从用户那里获取视频流并将其转换为一种视频格式。可以调用C来完成这项工作,在出现问题之前一切正常,我需要重新开始编码或采取任何行动。我无法估计需要多长时间,如果我需要并行转换多个视频ffmpeg将不会那么灵活,因为我计划它......

至少我现在看到了。当我深入研究时,可能会出现更多问题。

6 个答案:

答案 0 :(得分:4)

有几个注意事项:

  1. 你有dll的来源吗?
  2. 你打算打电话给那些dll多少钱?
  3. dll的API和您的用法有多复杂?
  4. 取决于答案。

    在以下情况下创建绑定:

    • 你会经常打电话给dll。直接通话要快得多。
    • 你有来源并检查它们有多好。否则,您可能会遇到内存泄漏,调用约定等问题。
    • dll的API不是太复杂,所以你不需要向它们发送C ++对象等。或者在exe中完成很多工作。

    使用可执行文件:

    • 如果您只是偶尔需要运行它们。创建另一个流程的开销并不重要。
    • 如果您不确定代码的质量。它将为您的代码提供更安全和可靠的功能,而不是加载一些执行不当的dll。如果出现问题,您可以尝试多次运行.exe。但它是一个dll崩溃了你的应用程序,你什么都做不了。
    • 如果API非常复杂,并且exe具有很多功能,那么您将不得不重新实现。

答案 1 :(得分:0)

我想这将取决于您的代码在库的api支持方面所期望的粒度。

如果可执行文件能够很好地封装工作流,那么您可以从调用可执行文件的简单性中受益。

此外,既然你提到这是本机C代码,添加DLL引用意味着必须处理非托管代码,除非我没有选择,否则我个人不会这样做。

答案 2 :(得分:0)

如果dll写得很好且没有内存泄漏,那么最好使用dll,因为它不需要新的进程创建开销。

答案 3 :(得分:0)

我说这一切都取决于您的要求,时间范围,exe文件输出的稳定程度以及解析的容易程度。两种方式都是可行的。

例如,Mercurial认为它的控制台输出是与它交互的主要方式 - 即使可以直接使用它的Python代码。

另一方面,从C#调用C函数相当容易,因此这也是一个选项。但是,如果你需要映射数百个C函数,你必须问问自己是否有时间这样做。

答案 4 :(得分:0)

EXE 有一个主要条目被调用,所以你不能直接调用这些函数。 当您调用exe时,将创建一个新进程 在该进程的主线程的上下文中调用入口线程。

DLL 通过直接调用函数为您提供更大的灵活性 每个功能都有一个入口点 系统将DLL加载到现有线程的上下文中

因此调用DLL对于计算资源来说要好得多,并提供更多的灵活性。考虑到您可以从托管代码和非托管代码调用DLL,并且可以从C#调用托管和非托管dll

如果DLL有一个接口,你可以直接添加一个参考,如果没有,你仍然可以像下面那样调用它

 [DllImport(@"TestLib.dll")]
    public static extern void InitParam([MarshalAs(UnmanagedType.LPWStr)] string inputFile,
        [MarshalAs(UnmanagedType.LPWStr)] string outputFile,
        [MarshalAs(UnmanagedType.LPWStr)] string templateFile,
        [MarshalAs(UnmanagedType.LPWStr)] string userName,
        [MarshalAs(UnmanagedType.LPWStr)] string manifestFilePath,
        [MarshalAs(UnmanagedType.LPWStr)] string usersRightList);

简单来说,您可以导入DLL并使用编组

将参数映射到.net类型

答案 5 :(得分:0)

答案取决于外部应用程序使用它的方式。:

  • 调用exe,如果它多次调用多个dll函数,并且其业务流程又大又复杂 - 您不希望在C#代码中重新实现所有exe逻辑。
  • 直接调用dll,如果exe只调用dll中的两个函数,则调用顺序和参数是众所周知的或根本不存在。

我一般情况下,我更喜欢直接调用dll,因为这消除了产生新进程和处理其输出的大量开销和可能出现的问题。并且不要害怕本机代码,如果您的dll函数很简单,那么使用PInvoke就可以轻松调用这些函数。