【问题标题】:How to detect if a dll is a COM dll如何检测 dll 是否为 COM dll
【发布时间】:2015-02-03 17:24:53
【问题描述】:

我想确定是否需要将 dll 注册为部署工具的一部分。所以它可能是任何类型的 com dll、.net 或其他。它可能会或可能不会被注册。所以这个问题和How to determine if DLL is COM or .NET?有点不同。

我的函数签名是:

public bool? IsComDll(string Path)
{

}

我想直接检查 dll,而不是注册它来查找,因为那样会留下副作用。

如果它恰好是 .Net dll,我不介意使用 Assembly 函数,但我不会提前知道,而且我还需要处理非 .Net dll。

编辑:

这是我到目前为止的代码。除了在可能是也可能不是 COM 的非 .net dll 上,它可以工作,其中LoadLibrary 返回一个零指针,这可能是由于其他原因,如依赖问题。一些 COM dll 的工作正常并返回 true,例如 C:\Windows\System32\vbscript.dll。所以我想你可以说它至少有 75% 的时间有效。

public T GetAttribute<T>(string AssemblyPath)
{
    return GetAttribute<T>(Assembly.LoadFile(AssemblyPath));
}

public T GetAttribute<T>(Assembly Assembly)
{
    return Assembly.GetCustomAttributes(typeof(T), false).FirstOrDefault;
}

public bool? IsComDll(string Path)
{

    if (IsDotNetDll(Path)) {
        ComVisibleAttribute ComVisibleAttribute = GetAttribute<ComVisibleAttribute>(Path);
        return ComVisibleAttribute != null && ComVisibleAttribute.Value;
    }

    if (Path.Contains(" ")) {
        Path = string.Format("\"{0}\"", Path);
    }

    IntPtr hModuleDLL = LoadLibrary(Path);

    if (hModuleDLL == IntPtr.Zero) {
        //we can't tell
        //TODO: Find out how!
    }

    // Obtain the required exported API.
    IntPtr pExportedFunction = IntPtr.Zero;

    pExportedFunction = GetProcAddress(hModuleDLL, "DllRegisterServer");

    return pExportedFunction != IntPtr.Zero;

}

public bool IsDotNetDll(string Path)
{
    try {
        Assembly.LoadFile(Path);
        return true;
    } catch (BadImageFormatException bifx) {
        return false;
    } catch (Exception ex) {
        throw;
    }
}

【问题讨论】:

  • @stuartd,引用的问题无法解析为代码。我认为我的问题可以,因此可以改进。
  • 如果 DLL 导出一个名为 DllRegisterServer 的函数,那么它期望“被注册为部署工具的一部分”的可能性很高。另一个(少得多)流行的选择是DllInstallRegsvr32 实用程序支持两者。
  • @IgorTandetnik,有人说DllGetClassObject 将永远存在。你觉得他们说的不对吗?谢谢。
  • 是的,COM DLL 总是会导出DllGetClassObject - 但我看不出这个事实如何帮助您实现“将它注册为部署工具的一部分”的目标。假设您检查了一个 DLL 并发现它实际上导出了 DllGetClassObject - 现在怎么办?

标签: .net com


【解决方案1】:

有一些工具可以在开发时提供帮助。这些方法是手动的,但通常只构建一次安装程序,因此这种方法可以获得所需的信息。

  1. 我经常运行 OLEView(我的系统上的C:\Program Files (x86)\Microsoft Visual Studio\Common\Tools\OLEVIEW.EXE - 可能随 VB6/Visual Studio 6 提供)并尝试打开有问题的 DLL。如果它是一个 COM DLL,OLEView 会很好地显示其 IDL 等的转储。否则它会给出一些错误。

    这有点“又快又脏”,但对我来说效果很好。

    2020 年更新)有一个名为 OLEViewDotNet 的 OLEView 替代项目具有改进的功能。讨论here

  2. Dependency Walker (C:\Program Files (x86)\Microsoft Visual Studio\Common\Tools\DEPENDS.EXE) 可用于检查 DLL 是否包含特征 COM 函数导出。例如,这里是加载 mscomct2.ocx 的示例:

正如另一个答案中所述,DLLRegisterServerDLLUnregisterServer 函数是 COM DLL 的典型/必需功能,因此它们的存在几乎肯定意味着它就是这样。

【讨论】:

    【解决方案2】:

    支持自注册的 DLL(通常是 COM DLL,但并非必须如此)会导出名为 DllRegisterServer 的函数,或者不太常见的是 DllInstall

    您可以在 regsvr32 实用程序的帮助下手动注册此类 DLL。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-03-13
      • 1970-01-01
      • 2010-11-28
      • 2023-03-28
      • 2015-02-22
      • 2012-06-04
      • 2011-07-27
      • 2018-10-03
      相关资源
      最近更新 更多