Inno设置如何确定文件是否是.NET程序集 [英] Inno setup How to determine whether a file is a .NET assembly

查看:172
本文介绍了Inno设置如何确定文件是否是.NET程序集的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想让我的inno设置循环通过dll(.net和com dll)在特定的文件夹,并注册每个dll。有没有办法识别每个dll类型(.net / com),并使用regasm / regsvr取决于dll的类型。



我有一个代码循环.net dlls在一个文件夹并注册每个。该代码可以在这里找到。在这种情况下,所有的DLL都是.net类型。

解决方案

以下功能(最初是基于 这篇文章 )可能有帮助您确定由 FileName 参数指定的文件是否为.NET程序集。如其名称所示,如果文件是.NET程序集,则应返回True,否则返回False。此功能适用于32位和64位库。



请注意,修改后的此代码仅适用于Unicode Inno安装程序。它不适用于ANSI版本的Inno Setup。对于ANSI版本,使用下面的帮助函数:

  [代码] 
函数BufferToWord(const Buffer:string):字;
begin
结果:= Ord(缓冲区[1]);
结束

函数BufferToLongWord(const Buffer:string):LongWord;
begin
结果:=(Ord(缓冲区[2])shl 16)+ Ord(缓冲区[1]);
结束

函数ReadFromStream(Stream:TStream; Size:Integer):LongWord;
var
缓冲区:string;
begin
SetLength(Buffer,Size div 2);
Stream.ReadBuffer(Buffer,Size);
case大小
2:结果:= BufferToWord(Buffer);
4:Result:= BufferToLongWord(Buffer);
else
RaiseException('要读取的意外字节大小');
结束
结束

函数IsDotNetAssembly(const FileName:string):Boolean;
var
FileStream:TFileStream;
PEOffset:LongWord;
MagicNumber:Word;
ComDescriptor:LongWord;
DataDirOffset:LongWord;
begin
//初始化结果
结果:= False;
//打开要读取的文件
FileStream:= TFileStream.Create(FileName,fmOpenRead或fmShareDenyNone);
try
//寻求PE头的起始偏移量并读取
的值$ FileStream.Position:= $ 3C;
PEOffset:= ReadFromStream(FileStream,SizeOf(PEOffset));
//由于Magic号码
//寻求可选的标题,这将告诉我们图像是32位还是64位;读它
FileStream.Position:= PEOffset + $ 18;
MagicNumber:= ReadFromStream(FileStream,SizeOf(MagicNumber));
//根据图像位置我们设置偏移数据
//目录
case MagicNumber
$ 010B:DataDirOffset:= $ 60; // 32位图像
$ 020B:DataDirOffset:= $ 70; // 64-bit image
else
RaiseException('Invalid image format。');
结束
//位置到RVA 15的数据目录数组
FileStream.Position:= PEOffset + $ 18 + DataDirOffset + $ 70;
//读取COM描述符的值
ComDescriptor:= ReadFromStream(FileStream,SizeOf(ComDescriptor));
//如果此值不为零,则该文件是CLR程序集
Result:= ComDescriptor<> 0;
finally
FileStream.free;
结束
结束

要在ANSI版本的Inno Setup中使用上述代码,请使用上述代码替换上述帮助函数。重要的是要做到这一点,因为Inno安装程序中的流只能使用字符串作为缓冲区,并且字符串的Unicode字节和ANSI版本的Inno Setup中的字符串的字节数不同。



函数BufferToWord(const Buffer:AnsiString):Word;

 
begin
结果:=(Ord(Buffer [2])shl 8)+ Ord(Buffer [1]);
结束

函数BufferToLongWord(const Buffer:AnsiString):LongWord;
begin
结果:=(Ord(缓冲区[4])shl 24)+(Ord(缓冲区[3])shl 16)+
(Ord(缓冲区[2])) )+ Ord(缓冲区[1]);
结束

函数ReadFromStream(Stream:TStream; Size:Integer):LongWord;
var
缓冲区:AnsiString;
begin
SetLength(Buffer,Size);
Stream.ReadBuffer(Buffer,Size);
case大小
2:结果:= BufferToWord(Buffer);
4:Result:= BufferToLongWord(Buffer);
else
RaiseException('要读取的意外字节大小');
结束
结束

上述函数的用法很简单:


$ b $如果IsDotNetAssembly('C:\Wherever\WhateverBinary.dll')然后
MsgBox('二进制文件是一个.NET程序集!',mbInformation,b $ pre> MB_OK)
else
MsgBox('二进制文件不是.NET程序集!',mbInformation,MB_OK);


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.

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.

解决方案

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.

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;

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

这篇关于Inno设置如何确定文件是否是.NET程序集的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆