【问题标题】:Check if a DLL is present in the system检查系统中是否存在 DLL
【发布时间】:2011-01-18 13:15:56
【问题描述】:

快速提问。我想知道执行我的应用程序的系统中是否存在 DLL。

这在 C# 中可行吗? (以一种适用于所有 Windows 操作系统的方式?)

对于 DLL,我指的是非 .NET 经典 dll(Win32 dll)

(基本上我想进行检查,因为我正在使用用户系统上可能存在或不存在的 DLL,但我不希望应用程序在不存在时崩溃而没有警告:P)

【问题讨论】:

  • 目标是在文件不存在的情况下不出错,还是查找存在的内容。
  • 目标是知道 dll 是否不存在并向用户显示“您缺少 dll xxx.dll。去更新您的系统”。

标签: c# windows winapi dll pinvoke


【解决方案1】:

调用LoadLibrary API 函数:

[DllImport("kernel32", SetLastError=true)]
static extern IntPtr LoadLibrary(string lpFileName);

static bool CheckLibrary(string fileName) {
    return LoadLibrary(fileName) == IntPtr.Zero;
}

【讨论】:

  • 这不只是检查库,它会加载并保持加载。你必须手动 FreeLibrary。
  • 好吧,无论如何我的应用程序总是会加载该库(因为应用程序 100% 使用它:D),所以我认为不需要免费库。
  • 恕我直言,FreeLibrary is 需要 - 否则您会泄露对该库的引用。这现在可能无关紧要,但在未来,有人会认为 CheckLibrary 没有副作用,它会烧死你。
  • Larry 是对的,更不用说它会给您的应用程序验证程序检查带来干扰。您正在使用 AppVerifier 来检查错误,对吗?对吧??
  • "系统在所有加载的模块上维护每个进程的引用计数。调用 LoadLibrary 增加引用计数。调用 FreeLibrary 或 FreeLibraryAndExitThread 函数减少引用计数。系统在其引用计数时卸载模块达到零或进程终止时(无论引用计数如何)。”来自 MSDN 的引用,但无论如何,免费图书馆不花钱。我会添加它:P
【解决方案2】:

在 .NET 中使用平台调用调用时,可以使用 Marshal.PrelinkAll(Type) 方法:

设置任务提供早期初始化并执行 调用目标方法时自动执行。首次任务 包括以下内容:

验证平台调用元数据的格式是否正确。

验证所有托管类型都是平台的有效参数 调用函数。

定位非托管 DLL 并将其加载到进程中。

定位进程中的入口点。

如您所见,除了 dll 是否存在之外,它还会执行其他检查,例如定位入口点(例如,SomeMethod()SomeMethod2() 是否确实存在于进程中,如下面的代码所示)。

using System.Runtime.InteropServices;

public class MY_PINVOKES
{
    [DllImport("some.dll")]
    private static void SomeMethod();

    [DllImport("some.dll")]
    private static void SomeMethod2();
}

然后使用try/catch 策略进行检查:

try
{
    // MY_PINVOKES class where P/Invokes are
    Marshal.PrelinkAll( typeof( MY_PINVOKES) );
}
catch
{
    // Handle error, DLL or Method may not exist
}

【讨论】:

  • 这应该是选择的答案。
【解决方案3】:

其实它不会抛出FileNotFoundException

另外,对于 LoadLibrary

,需要在多个位置检查路径

.net 中有一个标准异常是从 TypeLoadException 派生的,即 DllNotFoundException

最好的方法是在 try..catch 中包装方法/PInvoke 调用并处理 DllNotFoundException,因为 .net 将检查应用程序路径以及设置为 PATH OS 环境变量的一部分的任何其他路径。

[DllImport("some.dll")]
private static void SomeMethod();

public static void SomeMethodWrapper() {
try {
      SomeMethod();
    } catch (DllNotFoundException) {
    // Handle your logic here
  }
}

【讨论】:

    【解决方案4】:

    【讨论】:

    • 详细阐述这个主题?
    【解决方案5】:

    我假设这是一个 PInvoke 调用?

    如果是这样,确定它是否存在的最简单方法是进行调用并捕获在文件不存在时导致的异常。

    [DllImport("some.dll")]
    private static void SomeMethod();
    
    public static void SomeMethodWrapper() {
      try {
        SomeMethod();
      } catch (DllNotFoundException) {
        // Do Nothing 
      }
    }
    

    【讨论】:

    • 不是简单的单次调用,第一次调用可能不会一直都是一样的。我需要检查更多“更高级别”
    猜你喜欢
    • 1970-01-01
    • 2020-05-13
    • 2011-04-19
    • 2013-01-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-16
    • 1970-01-01
    相关资源
    最近更新 更多