Получить строгое имя сборки.NET в Inno Setup

Мне нужно установить эти некоторые файлы DLL в GAC.

Я использую препроцессор для генерации [Files] записи раздела для этих библиотек DLL. И мне нужно предоставить значение для StrongAssemblyName параметр.

Итак вопрос

  1. Могу ли я автоматически получить StrongAssemblyName DLL из скрипта на Паскале?
  2. Если нет, можно ли создать словарь, чтобы я мог искать в словаре, используя имя сборки в качестве ключа, а затем иметь жестко закодированные строки значений, которые будут использоваться при автоматическом построении строкиSource: path; DestDir

Я бы предпочел первое решение, если это возможно.

1 ответ

Решение

Я не думаю, что есть собственный способ получить строгое имя в 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 выполняется только во время установки. В некоторых случаях вы можете использовать скриптовую константу, но она не поддерживается в StrongAssemblyName параметр.

Итак, еще раз, вы должны использовать препроцессор.

Код Pascal Script преобразуется в препроцессор как:

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

Хотя, когда вы генерируете [Files] раздел полностью препроцессором, ваш текущий код из вашего комментария теперь будет работать, так как синтаксис, который вы использовали, фактически вызывает GetAssemblyStrongName макрос препроцессора, а не GetAssemblyStrongName Функция Pascal Script.

Обратите внимание, что в приведенном выше макросе используются строки в стиле C, поэтому он должен быть вне стиля Pascal pragma директивы:

; here

#pragma parseroption -p-

; not here

#pragma parseroption -p+

; or here
Другие вопросы по тегам