1

我希望我的 inno 设置循环遍历特定文件夹中的 dll(.net 和 com dll)并注册每个 dll。有没有办法识别每种 dll 类型(.net/com)并根据 dll 的类型使用 regasm/regsvr。

我有一个代码循环遍历文件夹中的 .net dll 并注册每个。代码可以在这里找到。在这种情况下,所有的 dll 都是 .net 类型的。如何使用同一文件夹中的两个 dll 实现相同的目的。

4

1 回答 1

1

以下函数(最初基于来自 的同名方法this article)可能会帮助您确定参数指定的文件FileName是否为 .NET 程序集。正如它的名字所宣称的,如果文件是一个 .NET 程序集,它应该返回 True,否则返回 False。此函数应适用于 32 位和 64 位库。

请注意,此代码在其修改中仅适用于 Unicode Inno 设置。它不适用于 ANSI 版本的 Inno Setup。对于 ANSI 版本,请使用下面发布的辅助函数:

[Code]
function BufferToWord(const Buffer: string): Word;
begin
  Result := Ord(Buffer[1]);
end;

function BufferToLongWord(const Buffer: string): LongWord;
begin
  Result := (Ord(Buffer[2]) shl 16) + Ord(Buffer[1]);
end;

function ReadFromStream(Stream: TStream; Size: Integer): LongWord;
var
  Buffer: string;
begin
  SetLength(Buffer, Size div 2);
  Stream.ReadBuffer(Buffer, Size);
  case Size of
    2: Result := BufferToWord(Buffer);
    4: Result := BufferToLongWord(Buffer);
  else
    RaiseException('Unexpected byte size to be read.');
  end;
end;

function IsDotNetAssembly(const FileName: string): Boolean;
var
  FileStream: TFileStream;
  PEOffset: LongWord;
  MagicNumber: Word;
  ComDescriptor: LongWord;
  DataDirOffset: LongWord;
begin
  // initialize result
  Result := False;
  // open the file to be read
  FileStream := TFileStream.Create(FileName, fmOpenRead or fmShareDenyNone);
  try
    // seek to the PE header start offset and read the value of
    FileStream.Position := $3C;
    PEOffset := ReadFromStream(FileStream, SizeOf(PEOffset));
    // seek to the optional header because of the Magic number,
    // which will tell us if the image is 32 or 64-bit; read it
    FileStream.Position := PEOffset + $18;
    MagicNumber := ReadFromStream(FileStream, SizeOf(MagicNumber));
    // according to image bitness we set the offset to the data
    // directory
    case MagicNumber of
      $010B: DataDirOffset := $60; // 32-bit image
      $020B: DataDirOffset := $70; // 64-bit image
    else
      RaiseException('Invalid image format.');
    end;
    // position to RVA 15 of the data directory array
    FileStream.Position := PEOffset + $18 + DataDirOffset + $70;
    // read the value of the COM descriptor
    ComDescriptor := ReadFromStream(FileStream, SizeOf(ComDescriptor));
    // if this value is non zero, the file is a CLR assembly
    Result := ComDescriptor <> 0;
  finally
    FileStream.free;
  end;
end;

要在 Inno Setup 的 ANSI 版本中使用上述代码,请将上述帮助函数替换为这些。这样做很重要,因为 Inno Setup 中的流只能使用字符串作为缓冲区,并且在 Unicode 和 ANSI 版本的 Inno Setup 中,字符串的每个字符的字节大小不同:

function BufferToWord(const Buffer: AnsiString): Word;
begin
  Result := (Ord(Buffer[2]) shl 8) + Ord(Buffer[1]);
end;

function BufferToLongWord(const Buffer: AnsiString): LongWord;
begin
  Result := (Ord(Buffer[4]) shl 24) + (Ord(Buffer[3]) shl 16) +
    (Ord(Buffer[2]) shl 8) + Ord(Buffer[1]);
end;

function ReadFromStream(Stream: TStream; Size: Integer): LongWord;
var
  Buffer: AnsiString;
begin
  SetLength(Buffer, Size);
  Stream.ReadBuffer(Buffer, Size);
  case Size of
    2: Result := BufferToWord(Buffer);
    4: Result := BufferToLongWord(Buffer);
  else
    RaiseException('Unexpected byte size to be read.');
  end;
end;

上述函数的用法很简单:

if IsDotNetAssembly('C:\Wherever\WhateverBinary.dll') then
  MsgBox('The binary file is a .NET assembly!', mbInformation, MB_OK)
else
  MsgBox('The binary file is not a .NET assembly!', mbInformation, MB_OK);
于 2013-11-12T20:13:20.900 回答