如何检查DLL文件是否已注册?

33
如何通过编程找出C#编写的DLL文件是否已注册?
我已经尝试过这段代码,但它没有起作用。
如果我注册一个DLL文件并使用此代码进行检查,则会返回结果。如果我取消注册并运行相同的代码,则仍然返回true。我将完整路径的DLL文件作为参数。
我们在Visual C++中开发了一个简单的DLL文件。之后我们注册了它。现在我们想确认它是否已注册。
Bob,你能否自己替换一下代码,对我来说还是很困难?
如果我注册一个DLL文件,注册表中是否有条目?我应该查找这些条目并判断DLL文件是否已注册?

在.NET DLL的上下文中,您所说的“注册”是什么意思?这更多是COM DLL的概念,不适用于.NET DLL。您能否澄清一下? - David M
7个回答

22

你需要找到一个DLL中定义的COM对象的GUID,然后查看这个注册表项:

HKEY_CLASSES_ROOT\CLSID\{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}\InprocServer32

将x替换为GUID。

它应该有一个默认值,包含DLL的完整路径。


@Neil Barnwell - 如果是针对一个没有源代码或文档的DLL,最简单的方法是使用regsvr32注册该DLL,然后搜索注册表以获取DLL的完整路径,您将找到一个或多个由该DLL公开的对象的InprocServer32键。 - Daniel Earwicker
6
请不要忘记检查HKEY_CLASSES_ROOT\Wow6432Node\CLSID\。 - DanM7
我知道这个问题很久以前就被问过了。然而,如果你开发的 DLL 是用 Visual C++ 编写的,并且它使用了 ATL,那么它很可能会被注册在 Computer\HKEY_CLASSES_ROOT\TypeLib\ 中。希望这能像对我一样对一些后来者有所帮助。 - Mo Aboulmagd
[OP的评论:] 答案可以工作,需要做一些修改。我查看了 typelib 而不是 clsid。 无论如何,我进行了一点修改。现在它可以工作了。 - shA.t

5
如果您说的是在GAC中注册,这是我的考虑:要在GAC中注册一个程序集,必须使用强名称进行签名(在其名称中具有公钥令牌)。
因此,您可以尝试使用Assembly.Load(string)进行加载,如果出现FileNotFoundException - 则表示该程序集未在GAC中注册。
如果没有错误,但Assembly.GetName().GetPublicKeyToken()的结果为null或为空 - 这意味着您在应用程序目录中找到了程序集,而不在GAC中。

3
您可以使用以下内容:
My.Computer.Registry.ClassesRoot.GetSubKeyNames.Contains("gEncrypt.clsEncrypt")

“gEncrypt.clsEncrypt”是ComName.ClassName。


3

如果你知道COM dll的CLSID,你可以检查HKEY_CLASSES_ROOT\CLSID\{CLSID-of-your-COM-component}或者HKEY_CLASSES_ROOT\Wow6432Node\CLSID\{CLSID-of-your-COM-component}(Wow6432Node => 在64位机器上注册的32位COM)是否有该CLSID对应的键。

以下是一个例子:

private bool IsAlreadyRegistered()
{
    using (var classesRootKey = Microsoft.Win32.RegistryKey.OpenBaseKey(
           Microsoft.Win32.RegistryHive.ClassesRoot, Microsoft.Win32.RegistryView.Default))
    {
        const string clsid = "{12345678-9012-3456-7890-123456789012}";

        var clsIdKey = classesRootKey.OpenSubKey(@"Wow6432Node\CLSID\" + clsid) ??
                        classesRootKey.OpenSubKey(@"CLSID\" + clsid);

        if (clsIdKey != null)
        {
            clsIdKey.Dispose();
            return true;
        }

        return false;
    }
}

2
  1. 声明一个指向接口的指针
  2. 在CLSID和IID上调用CoCreateInstance
  3. 如果返回值不是S_OK,则表示该类未注册

2
class TestDll
{
    //Import your tested DLL here
    [DllImport("kernel32")]
    public extern static int LoadLibrary(string lpLibFileName);
}

try
{
    TestDll test = new TestDll();
}
catch(DllNotFoundException ex)
{
    return false;
}

1
[DllImport("kernel32")]    
public extern static bool FreeLibrary(int hLibModule);

[DllImport("kernel32")]    
public extern static int LoadLibrary(string lpLibFileName);



public bool IsDllRegistered(string DllName)    
{

      int libId = LoadLibrary(DllName);    
      if (libId>0) FreeLibrary(libId);    
      return (libId>0);    
}

由于C ++自动将int> 0转换为bool = true,因此您不能使用> 0。 因此,如果(libID)..返回libID; - abatishchev
1
这只是通过文件名来发现DLL是否可以被加载,与是否已注册无关。 - Daniel Earwicker
1
@abatishchev,不对,这是错误的。在这里,LoadLibrary返回一个整数。 - BobbyShaftoe
如果DLL加载成功,那是因为在路径中找到了该DLL。如果你将DLL放入当前目录或C:\Windows\System32或任何其他可以找到它的地方,那么LoadLibrary就会起作用。此时,DllGetClassObject也将起作用,但这并没有告诉我们什么。 - AshesToAshes

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