如何确定DLL是COM还是.NET?

8

我有一个更新程序,从服务器拉取的文件在一个目录中混合了VB6 DLL和.NET DLL。

如何确定一个DLL是COM类型的?(这样我就可以从更新程序中调用regsvr32


为什么不做正确的事情,注册那些你知道是COM服务器的,跳过那些不是的呢?你应该拥有这些信息,并在安装程序中编写代码。 - Tim
1
@Tim - 我猜可能存在这样一种情况,即代码的发布者与消费者不是同一组织 - 否则我同意 - 明确控制过程。 - AJ.
@AJ - 这并不意味着不能弄清楚并测试它。我的观点是,如果它是您的安装过程的一部分,那么您应该知道需要注册什么。不这样做是粗心和不专业的。提前进行一个简单的测试即可解决问题。既然可以事先确定,为什么还要添加代码呢? - Tim
@Tim:两个词(改成三个):基于插件的系统。 - Hao
@Hao - 我不知道那是什么意思。如果你正在制作一个插件系统,你应该有一个专门的目录或其他方式来识别它们。这些DLL文件来自哪里? - Tim
显示剩余2条评论
4个回答

6

我猜想一种方法是尝试使用System.Reflection.Assembly.LoadFile()加载文件(更多信息)。如果出现BadImageFormatException,则不是有效的.NET程序集。可能有更好的方法来完成这个任务,但这个方法应该可行。


这似乎是写一个安装程序来完成这个任务而不是仔细跟踪需要注册哪些DLL文件的工作量很大。但无论如何,点赞加一。 - Tim

5
为了正式地做到这一点,您可以检查PE以了解每个dll导出的类型。这里有一篇非常有趣的MSDN文章介绍了结构。如果您理解了这个设置,就可以识别与.Net的链接(从而缺乏指示纯COM dll)。

今天我的投票用完了。我会回来给这个答案点赞的。这是一个很好的技术解答。 - Tim
@ Tim - 谢谢 :) 这不是给心脏虚弱的人,但只要付出一点努力,它可以提供一个相当可靠的解决方案。如果场景比汇编语言更高级,这种方法应该是可靠的(即:没有太多“优化”的PE需要处理)。 - AJ.

3

为什么不对它们全部调用regsvr呢?如果它们注册了,那就好了,如果没有也没关系。

不过最好的方法是编写一个安装程序,它知道哪个是哪个,并为每个正确地执行操作。

编辑

如果你担心“发出错误”,不要担心。

看看这个用法

你可以抑制消息。(/s)


@Hao - 尽管我提供了另一种答案,但我同意Tim的观点。 - AJ.
@AJ:盲目地通过regsvr32注册DLL的问题在于,如果DLL是.NET类型,regsvr32会发出错误。 - Hao
我已经使用 /S。它可以在XP上禁止错误信息,但在Vista上会显示错误信息。 - Hao
1
@Hao - 请确保您以管理员身份运行该命令。如果UAC权限不正确,则/s标志将无法工作,因为操作系统永远不会让您走得那么远。 - AJ.

0

你可以通过以下方法迅速翻转并找出所有的.NET程序集:

private bool IsDotNetAssembly(string path)
{
  var sb = new StringBuilder(256);
  var hr = NativeMethods.GetFileVersion(path, sb, sb.Capacity, out var _);
  return hr == 0;
}

private static class NativeMethods
{
  [DllImport("mscoree.dll", CharSet = CharSet.Unicode)]
  public static extern int GetFileVersion(string path, StringBuilder buffer, int buflen, out int written);
}

使用这种解决方案,您无需加载程序集本身,这具有一些优点(速度快,没有异常)。

您可以直接跳过.NET程序集进行COM注册。


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