I'm trying to load VclStylesInno.dll for uninstall form of Inno Setup.
Next code is declared in the middle of [Code] section:
procedure uLoadVCLStyle(VClStyleFile: String);
external 'LoadVCLStyleW#{app}/VclStylesInno.dll stdcall';
but I faced an error
An attempt was made to expand the "app" constant before it was initialized
What is the best way to load DLL for uninstall process?
I assume you are getting the error, when starting the installer, not the uninstaller.
When the installer is starting, the {app} is obviously unknown yet.
But as you need the import for the uninstaller only, which knows the {app}, you can add the uninstallonly option:
procedure uLoadVCLStyle(VClStyleFile: String);
external 'LoadVCLStyleW#{app}\VclStylesInno.dll stdcall uninstallonly';
Though it does not really help, as the uninstaller will want to remove the DLL, failing, as it has the DLL locked itself.
The solution is simple, just follow the official instructions for uninstalling the VCL Styles for Inno Setup.
You basically need to install the DLL somewhere else than in the {app} and leave the DLL behind when uninstalling. That's actually an ugly solution, which imho does not justify a styled uninstaller. But it's your choice. Or you might try using UnloadDLL to unlock the file, so it can be deleted.
As you suggested, you may copy the DLL to Windows temporary folder, load it from there and hope for Windows to eventually delete the DLL during temporary directory cleanup.
This should do (note the delayload option):
[Files]
Source: VclStylesInno.dll; DestDir: {app}
Source: skin.vsf; DestDir: {app}
[Code]
procedure LoadVCLStyle_UnInstall(VClStyleFile: String);
external 'LoadVCLStyleW#{%TEMP}\VclStylesInno.dll stdcall uninstallonly delayload';
function InitializeUninstall: Boolean;
begin
if FileCopy(ExpandConstant('{app}\VclStylesInno.dll'),
ExpandConstant('{%TEMP}\VclStylesInno.dll'), False) and
FileCopy(ExpandConstant('{app}\skin.vsf'),
ExpandConstant('{%TEMP}\skin.vsf'), False) then
begin
LoadVCLStyle_UnInstall(ExpandConstant('{%TEMP}\skin.vsf'));
end;
end;
While I didn't test it, it might be better to use {tmp} instead of {%TEMP} (the files might get deleted by the uninstaller parent process right after the uninstallation finishes – and you won't interfere with other processes that might want to store VclStylesInno.dll to %TEMP%).
For another solution (better but more complicated to implement), see
How keep uninstall files inside uninstaller?
Related
I am attempting to use FileOpen in Inno Setup code, however the Inno Setup compiler keeps throwing me the following error.
Unknown Identifier 'FileOpen'
Here is a sample code:
function IsFileLocked(pathFile : string) : Boolean;
var
hFile : integer;
begin
Result := true;
hFile := FileOpen(pathFile);
if (0 <> hFile) then
begin
Result := false;
{ Since ISPP 1.2, Inno Setup automatically frees resources, so FileClose() is obsolete. }
{ http://www.jrsoftware.org/ispphelp/index.php?topic=fileclose }
end;
end;
Unlike the FileClose method, FileOpen is not obsolete.
FileOpen
I did a Google search, but nothing turned up. I know that Inno Setup uses Pascal Script, not Pascal, but the FileOpen function is part of the Inno Setup Preprocessor: Functions.
Note: I upgraded to the latest version of the compiler (5.6.1a) this morning and the latest version of Inno Script Studio (2.3.0), same problem.
I do see the section Other Information > ISPPBuiltins.iss. I tried adding the line:
[Code]
#include <ISPPBuiltins.iss>
Adding the #include statement, generates the error
ISPPBuiltins.iss Line 1: Column 1:'BEGIN' expected.
Adding in ISPPBuiltins.iss to the project as a method to solve the FileOpen problem is meaningless, as opening the file in a text editor shows that 'FileOpen` does not exist in there. I do not see any embedded file. It would appear that the compiler does not like "; BEGIN..." in the file, but I digress. So much for that thought.
Thoughts on how to resolve my Unknown Identifier problem with FileOpen?
FileOpen is a preprocessor function. You cannot use it in Pascal Script code, which has its own function library.
For quick and dirty solution, use LoadStringFromFile.
For a more clean and efficient solution, import CreateFile WinAPI function.
I tried to read sample code for how to load DLL at Inno Setup, but I'm confused.
I have one DLL (ChkArchInfo.dll) and the contents is simple:
extern "C" __declspec(dllexport) bool __stdcall IsARM()
{
SYSTEM_INFO si;
GetNativeSystemInfo(&si);
if(PROCESSOR_ARCHITECTURE_ARM == si.wProcessorArchitecture)
return true;
return false;
}
I know I need to use [Files] section to load the DLL file.
But how to declare this function at .iss to let me use it?
BTW, If there any functions in Inno Setup to get ARM architectute? (ProcessorArchitecture doesn't include ARM architectute)
Please help me to do....
Thank you!!!
BR,
Alan
Read the Inno Setup documentation on Using DLLs and .NET assemblies.
You primarily have to declare an external function prototype. And add the DLL to the [Files] section, if you want to embed the DLL into the installer.
[Files]
Source: "MyDll.dll"; Flags: dontcopy
[Code]
function IsARM: Boolean;
external 'IsARM#files:MyDll.dll stdcall';
Though it would be better to call the GetNativeSystemInfo from Pascal Script directly. But that's a different question.
I have an Inno Setup script with a code section for some basic stuff. But I also have another Inno Setup script file (.iss) that deals with Windows services specifically. I would like to call these functions/procedures directly from my main script. So how do I #include the services.iss file into my main script so that I can call its functions from the Code section?
I've seen some examples on the net indicating how to split the file section using this method, which is great, but I want to be able to split the code section using common code scripts between installations. I could find mention of it here and there, but nowhere does it tell you how to do it.
As you have mentioned yourself, use the #include pre-processor directive.
If you have a common code file like common.pas:
procedure CommonProcedure;
begin
// ...
end;
You can include it into the main .iss script like:
[Code]
#include "common.pas"
function InitializeSetup(): Boolean;
begin
// Calling procedure included from the common.pas
CommonProcedure;
Result := True;
end;
The extension does not really matter. I've used .pas, as the file it's purely a Pascal (Script) code. But if you prefer .iss, it's your choice. Though then, syntactically it would be more appropriate to include section name into the file:
[Code]
procedure CommonProcedure;
begin
// ...
end;
And include the file out-side of the [Code] section:
#include "common.pas"
[Code]
function InitializeSetup(): Boolean;
begin
// Calling procedure included from the common.pas
CommonProcedure;
Result := True;
end;
This approach even gives you greater flexibility, e.g. in case you need some support files for your code:
[Files]
Source: "InnoCallback.dll"; Flags: dontcopy
[Code]
procedure CommonProcedure;
begin
// ...
end;
(Though it's just a matter of coding style. Technically, it does not really matter, as the sections can be mixed in any way. So you can have [Code] section, followed by [Files] section, followed by another [Code] section).
I want to dynamically derive the source folder (and destination folder) for 32/64 bit installations. So how can I specify that in the [Files] section of Inno setup.
The following gives a compilation error:->
[Files]
Source: {#MySourcePath}\{code:GetSourceLibFolder}\*.jar; DestDir: {code:GetAppDir}\lib\;
I have the GetSourceLibFolder() and GetAppDir() function defined in the code section.
The functions are very simple and just return a variable:
function GetSourceLibFolder(Param: String): String;
begin
Result:= SourceLibFolder;
end;
function GetSourceBinFolder(Param: String): String;
begin
Result:= SourceBinFolder;
end;
Thanks !
The source path needs to be used at compile time (unless you have the external flag) which means you must use ISPP and a #define. The [Code] section is only for run/install time code so will work for the target path.
If you provide the code for your GetSourceLibFolder function, someone can convert it to ISPP.
Compiled a Inno Setup script (IS v5.4.2), but when ran resulting Setup.exe, an error dialog appeared with content:
Internal error: ExtractTemporaryFile: The file "isxdl.dll" was not found.
I could not find this .DLL anywhere on my system. While there's probably a good technical reason for it, I found it confusing that the Inno Setup compiler did not complain that the ISXDL.DLL was not available.
=============================
*Found Answer Myself *
I found the issue myself after a bit of searching and experimentation. Evidently I had at one point installed "ISTool", which contains the ISXDL.DLL file, and used "ISTool" to construct and/or compile the .ISS script in question. This placed some references like the following in the setup.
procedure isxdl_AddFile(URL, Filename: AnsiString);
external 'isxdl_AddFile#files:isxdl.dll stdcall';
function isxdl_DownloadFiles(hWnd: Integer): Integer;
external 'isxdl_DownloadFiles#files:isxdl.dll stdcall';
function isxdl_SetOption(Option, Value: AnsiString): Integer;
external 'isxdl_SetOption#files:isxdl.dll stdcall';
For whatever reason, I uninstalled ISTool (possibly motivated by fact that ISTool is not listed, as of May 20, 2011, on the Inno Setup 3rd Party Tools page), but this left the related code still in my script, which compiled okay using Inno Setup.
I found the issue myself after a bit of searching and experimentation. Evidently I had at one point (i.e., a year or more ago) installed "ISTool", which contains the ISXDL.DLL file, and used "ISTool" to construct and/or compile the .ISS script in question. This placed some references like the following in the .ISS setup script.
procedure isxdl_AddFile(URL, Filename: AnsiString);
external 'isxdl_AddFile#files:isxdl.dll stdcall';
function isxdl_DownloadFiles(hWnd: Integer): Integer;
external 'isxdl_DownloadFiles#files:isxdl.dll stdcall';
function isxdl_SetOption(Option, Value: AnsiString): Integer;
external 'isxdl_SetOption#files:isxdl.dll stdcall';
For whatever reason, I uninstalled ISTool (possibly motivated by fact that ISTool is not listed, as of May 20, 2011, on the Inno Setup 3rd Party Tools page), but this left the related code still in my script, which subsequently compiled okay using "Inno Setup".
To correct this, I just deleted the code containing the references to "_isxdl".
You need to have ISXDL.DLL listed in your [Files] section to use the listed functions.
The source code to ISXDL.DLL can be found on the the Project Page.