在 Inno Setup 中检索 .NET 程序集的强名称
Retrieve strong name of .NET assembly in Inno Setup
我需要将这些DLL 文件安装到GAC。
我使用预处理器为这些 DLL 生成 [Files]
节条目。我需要为 StrongAssemblyName
参数提供一个值。
所以问题
- 我可以从 Pascal 脚本中自动检索 DLL 的
StrongAssemblyName
吗?
- 如果没有,可以创建一个字典,这样我就可以使用程序集名称作为键在字典中查找,然后在自动构建行时使用硬编码值字符串
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
我需要将这些DLL 文件安装到GAC。
我使用预处理器为这些 DLL 生成 [Files]
节条目。我需要为 StrongAssemblyName
参数提供一个值。
所以问题
- 我可以从 Pascal 脚本中自动检索 DLL 的
StrongAssemblyName
吗? - 如果没有,可以创建一个字典,这样我就可以使用程序集名称作为键在字典中查找,然后在自动构建行时使用硬编码值字符串
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