问题
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
- Can I automatically retrieve the
StrongAssemblyName
of a DLL from a Pascal Script? - 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