Distinguish COM dll from .NET assembly in batch files

279 Views Asked by At

I have a bunch of dlls in a folder, which are either COM dlls, or .NET assemblies. Now, I'm using something like this below to register the binaries:

@echo off

set argCount=0
for %%x in (%*) do (
   set /A argCount+=1
)
if not %argCount% == 1 (
    echo Usage:
    echo   %0 ^<filename^>
    echo Example:
    echo   %0 path\to\the\file.ext
    goto end
)

for /F "tokens=*" %%A in (%1) do (
    echo Registering %%A ...
    regsvr32 "%%A"
)

:end

The issue here is that although for COM dlls, it works fine, but for .NET assemblies it fails. As a workaround, I could replace the regsvr32 with regasm and run it again. This would, in the second run register the .NET assemblies. I was wondering, if there was a way the batch file might be able to distinguish between the two cases here. I understand, COM dlls must have the PE or COFF header while .NET assemblies would not (?). Looking at MSDN, I see ImageHlp API which might have something for this. Is there an easier way to achieve the same?

1

There are 1 best solutions below

3
On BEST ANSWER

I'm fairly certain there is nothing you can do with raw batch script to detect this. (Or if you can figure out a way, it's going to be incredibly ugly.) But you can do this a number of other ways.

Here's one option: Use corflags.exe, which ships with the Windows SDK. To find a copy on your system, try something like attrib /s C:\corflags.exe. To use it, try something like this:

corflags.exe your.dll
if %ERRORLEVEL% equ 0 goto :IS_DOT_NET
goto :IS_NOT_DOT_NET

Alternatively, you could write your own program that looks for the existence of a DllRegisterServer entry point in the DLL, which .NET DLLs do not have. It would only take a handful of lines of code in any language to do this check. Here's the C++:

// returns:
//   1 if the dll can be used with regsvr32
//   0 if the dll cannot be used with regsvr32
//  -1 if the dll cannot be loaded
int main(int argc, LPCSTR* argv)
{
    if (argc != 2)
        return -1;
    HMODULE hModule = LoadLibraryA(argv[1]);
    if (!hModule)
        return -1;
    FARPROC dllRegisterServer = GetProcAddress(hModule, "DllRegisterServer");
    FreeLibrary(hModule);
    if (dllRegisterServer)
        return 1;
    return 0;
}

Of course, this is half of what regsvr32.exe already does, so you could just do something like:

regsvr32.exe /s your.dll
if %errorlevel% neq 0 regasm.exe your.dll