在Inno Setup中检索.NET程序集的强名称

时间:2017-09-01 09:09:22

标签: .net inno-setup .net-assembly pascalscript strongname

我需要将这些DLL文件安装到GAC。

我使用预处理器为这些DLL生成[Files]节条目。我需要为StrongAssemblyName参数提供一个值。

所以问题

  1. 我可以自动从Pascal脚本中检索DLL的StrongAssemblyName吗?
  2. 如果没有,可以创建一个字典,这样我就可以使用程序集名称作为键在字典中查找,然后使用硬编码的值字符串在自动构建行时使用 Source: path; DestDir
  3. 如果可能,我更喜欢第一种解决方案。

1 个答案:

答案 0 :(得分:2)

我不认为,在Inno Setup Pascal Script中检索强名称是一种本地方式。

但是,您可以使用简单的PowerShell命令来检索强名称。

([Reflection.Assembly]::ReflectionOnlyLoadFrom('My.dll')).FullName

结合这两个问题:

你得到的代码如下:

function GetAssemblyStrongName(FileName: string): string;
var
  TmpFileName: string;
  Args: string;
  StrongName: AnsiString;
  ResultCode: Integer;
begin
  TmpFileName := ExpandConstant('{tmp}') + '\strong_name.txt';
  Args :=
    Format('-ExecutionPolicy Unrestricted -Command "Set-Content -Path "%s" -NoNewline ' +
           '-Value ([Reflection.Assembly]::ReflectionOnlyLoadFrom(''%s'')).FullName"', [
           TmpFileName, FileName]);
  if (not Exec('powershell.exe', Args, '', SW_HIDE, ewWaitUntilTerminated, ResultCode)) or
     (ResultCode <> 0) or
     (not LoadStringFromFile(TmpFileName, StrongName)) then
  begin
    RaiseException(Format('Error retrieving strong name of "%s"', [FileName]));
  end;

  Result := StrongName;
  DeleteFile(TmpFileName);
end;

实际上,您不能使用Pascal Scripting,因为您需要在编译时使用强名称,而Pascal Scripting仅在安装时执行。在某些情况下,您可以使用scripted constant,但StrongAssemblyName parameter不支持。

同样,你必须使用preprocessor

Pascal脚本代码转换为预处理器,如:

#define GetAssemblyStrongName(FileName) \
  Local[0] = AddBackslash(GetEnv("TEMP")) + "strong_name.txt", \
  Local[1] = \
    "-ExecutionPolicy Unrestricted -Command """ + \
    "Set-Content -Path '" + Local[0] + "' -NoNewline -Value " + \
    "([Reflection.Assembly]::ReflectionOnlyLoadFrom('" + FileName + "')).FullName" + \
    """", \
  Exec("powershell.exe", Local[1], SourcePath, , SW_HIDE), \
  Local[2] = FileOpen(Local[0]), \
  Local[3] = FileRead(Local[2]), \
  FileClose(Local[2]), \
  DeleteFileNow(Local[0]), \
  Local[3]

您可以在StrongAssemblyName参数中使用它,例如:

[Files]
Source: "My.dll"; DestDir: "{app}"; \
  StrongAssemblyName: "{#GetAssemblyStrongName('My.dll')}"

将其预处理为:

[Files]
Source: "My.dll"; DestDir: "{app}"; \
  StrongAssemblyName: "My, Version=1.0.0.0, Culture=neutral, PublicKeyToken=2271ec4a3c56d0bf"

尽管如此,generate the [Files] section completely by a preprocessor,您评论中的当前代码现在可以正常工作,因为您使用的语法实际上调用GetAssemblyStrongName预处理器宏而不是GetAssemblyStrongName Pascal脚本功能

请注意,上面的宏使用C风格的字符串,因此必须外面 Pascal样式的pragma指令:

; here

#pragma parseroption -p-

; not here

#pragma parseroption -p+

; or here