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

Retrieve strong name of .NET assembly in Inno Setup

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

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

所以问题

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

如果可能的话,我更喜欢第一个解决方案。

我不认为,在 Inno Setup Pascal 脚本中有一种本地方法来检索强名称。

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

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

结合这两个问题:

  • How can I see the strong name of my assembly?
  • How to get an output of an Exec'ed program in Inno Setup?

您会得到如下代码:

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 脚本,因为您需要在编译时使用强名称,而 Pascal 脚本仅在安装时执行。在某些情况下,您可以使用 scripted constant, but it's not supported in the 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"

虽然,正如您 ,您评论中的当前代码现在可以工作,因为您使用的语法实际上调用 GetAssemblyStrongName 预处理器宏而不是 GetAssemblyStrongName Pascal 脚本函数。

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

; here

#pragma parseroption -p-

; not here

#pragma parseroption -p+

; or here