Retrieve strong name of .NET assembly in Inno Setup

谁都会走 提交于 2019-12-07 18:43:49

问题


I need to install these some DLL files to the GAC.

I use preprocessor to generate [Files] section entries for these DLLs. And I need to provide a value for the StrongAssemblyName parameter.

So question

  1. Can I automatically retrieve the StrongAssemblyName of a DLL from a Pascal Script?
  2. If not, can one create a dictionary so I could look up in the dictionary using the assembly name as key, and then have hardcoded value strings that would get used when automatically building up the line Source: path; DestDir

I would prefer the first solution, if possible.


回答1:


I do not think, there's a native way to retrieve a strong name in Inno Setup Pascal Script.

But, you can use a simple PowerShell command to retrieve the strong name.

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

Combining these two questions:

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

you get a code like:

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;

Though actually, you cannot use Pascal Scripting, as you need the strong name on compile-time, and the Pascal Scripting is executed on install-time only. In some cases, you can use a scripted constant, but it's not supported in the StrongAssemblyName parameter.

So again, you have to use a preprocessor.

The Pascal Script code translates to the preprocessor like:

#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]

You can use it in the StrongAssemblyName parameter like:

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

Which gets preprocessed to something like:

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

Though, as you generate the [Files] section completely by a preprocessor, your current code from your comment will now work, as the syntax, that you have used, actually calls GetAssemblyStrongName preprocessor macro and not GetAssemblyStrongName Pascal Script function.

Note that the macro above uses C-style strings, so it has to be outside the Pascal-style pragma directives:

; here

#pragma parseroption -p-

; not here

#pragma parseroption -p+

; or here


来源:https://stackoverflow.com/questions/45996803/retrieve-strong-name-of-net-assembly-in-inno-setup

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!