toddmo
toddmo

Reputation: 22396

How to detect if a dll is a COM dll

I want to identify if a dll needs to be registered as part of a deployment tool. So it might be any kind of com dll, .net or otherwise. It may or may not be registered. So this question is a little different than How to determine if DLL is COM or .NET?.

My function signature would be:

public bool? IsComDll(string Path)
{

}

I want to inspect the dll directly, not register it to find out, because that would leave a side effect.

I don't mind using Assembly functions if it happens to be a .Net dll, but I won't know in advance and I need to handle non .Net dlls as well.

Edit:

Here is the code I have so far. It's working except on non .net dlls that may or may not be COM, where LoadLibrary is returning a zero pointer which may be because of other reasons like a dependency problem. Some COM dll's work ok and return true, like C:\Windows\System32\vbscript.dll. So I guess you could say it works at least 75% of the time.

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;
    }
}

Upvotes: 3

Views: 4782

Answers (2)

StayOnTarget
StayOnTarget

Reputation: 12988

There are a few tools which can assist with this at development-time. These approaches are manual but generally an installer is only built once so this kind of approach can get the information needed.

  1. I often run OLEView (C:\Program Files (x86)\Microsoft Visual Studio\Common\Tools\OLEVIEW.EXE on my system - might have come with VB6 / Visual Studio 6) and try to open the DLL in question. If it is a COM DLL, the OLEView will nicely display a dump of its IDL etc. Otherwise it gives some error.

    This is kind of "quick & dirty" but has worked well for me.

    (2020 Update) There is a replacement project for OLEView called OLEViewDotNet which boasts improved features. Discussed here.

  2. Dependency Walker (C:\Program Files (x86)\Microsoft Visual Studio\Common\Tools\DEPENDS.EXE) can be used to inspect the DLL to see if it contains characteristic COM function exports. For instance, here's an example of loading mscomct2.ocx:

enter image description here

As noted in another answer the functions DLLRegisterServer and DLLUnregisterServer are typical / required for COM DLLs and so their existence almost certainly means that's what it is.

Upvotes: 4

Igor Tandetnik
Igor Tandetnik

Reputation: 52461

A DLL that supports self-registration (usually a COM DLL, but doesn't strictly have to be) would export a function named DllRegisterServer or, less commonly, DllInstall.

You can manually register such DLLs with the help of regsvr32 utility.

Upvotes: 2

Related Questions