Inno Setup的如何确定文件是否是一个.NET程序集是一个、文件、程序、Inno

2023-09-07 08:50:41 作者:玩乐

我想通过动态链接库(.NET和COM DLL)的我的Inno Setup的循环在特定的文件夹,并注册每个DLL。有没有一种方法,以确定每个DLL类型(.NET / COM),并使用regasm / regsvr根据DLL的类型。

I want my inno setup to loop through dlls (both .net and com dlls) in particular folder and register each dll. Is there a way to identify each dll type (.net/com) and use regasm/regsvr depending on the type of the dll.

我有一个code的循环遍历文件夹中的.NET的DLL和注册各一台。在code可以发现here.在这种情况下,所有的DLL是.NET类型。如何实现相同的两个动态链接库present在同一个文件夹中。

I have a code which loops through .net dlls in a folder and register each one. The code can be found here. In this case, all the dlls were .net type. How to achieve the same with both dlls present in the same folder.

推荐答案

下面的函数(S)(最初基于来自的 这篇文章 )可以帮助您确定是否由文件名参数是一个.NET程序集与否。正如它的名字宣称,它应该返回true,如果该文件是一个.NET程序集,否则为false。此功能应该用于32位工作,以及为64位库。

The following function(s) (originally based on a same named method from this article) might help you to determine if a file specified by the FileName parameter is a .NET assembly or not. As its name proclaims, it should return True if the file is a .NET assembly, False if not. This function should work for 32-bit as well as for 64-bit libraries.

请注意,此code在其修改将只在统一$ C C Inno Setup的$。它不打算与创新安装的ANSI版本中使用。对于ANSI版本使用下面贴的辅助功能:

Please note that this code in its modification will work only in Unicode Inno Setup. It's not intended to be used with ANSI versions of Inno Setup. For ANSI versions use the helper functions posted below:

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

要使用上述code在创新安装的ANSI版本这些替换上面的辅助功能。要做到这一点是很重要的,因为在创新安装流只能使用字符串作为一个缓冲区,只是字符串具有在统一code和创新安装的ANSI版本每个字符的字节大小不同的:

To use the above code in the ANSI version of Inno Setup replace the above helper functions with these. It is important to do that, because streams in Inno Setup can use only string as a buffer and just strings has different size in bytes per char in Unicode and ANSI version of 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;

以上函数的用法是那么简单:

The usage of the above function is then straightforward:

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);
 
精彩推荐
图片推荐