在批处理文件中区分 COM dll 和 .NET 程序集

Distinguish COM dll from .NET assembly in batch files

我的一个文件夹里有一堆dll,要么是COM dlls,要么是.NET assemblies。现在,我正在使用下面这样的东西来注册二进制文件:

@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

这里的问题是,虽然对于 COM dll,它工作正常,但对于 .NET 程序集它失败了。作为解决方法,我可以将 regsvr32 替换为 regasm 并再次 运行 。这将在第二个 运行 中注册 .NET 程序集。我想知道,批处理文件是否有办法区分这两种情况。我知道,COM dll 必须有 PECOFF header 而 .NET 程序集不会(?)。查看 MSDN,我看到 ImageHlp API 可能对此有所帮助。有没有更简单的方法来实现同样的目标?

我相当确定您无法使用原始批处理脚本来检测此问题。 (或者,如果你能想出办法,那将是非常丑陋的。)但你可以通过许多其他方式来做到这一点。

这是一个选项:使用 corflags.exe,它随 Windows SDK 一起提供。要在您的系统上查找副本,请尝试 attrib /s C:\corflags.exe。要使用它,请尝试这样的操作:

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

或者,您可以编写自己的程序来查找 DLL 中是否存在 DllRegisterServer 入口点,而 .NET DLL 没有。只需使用任何语言的几行代码即可完成此检查。这是 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;
}

当然,这是 regsvr32.exe 已经做的事情的一半,所以你可以做类似的事情:

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