I have some vlx files to add to my AutoCAD folder. I would like to make install package with Inno Setup which will install my vlx files at post install.I got the registry key of AutoCAD 2014.
HKEY_LOCAL_MACHINE\Software\Autodesk\AutoCAD\R19.1\ACAD-D001:409
Please show me inno setup script for the above case.
I found this article which states:
Below is a Inno Setup/Pascal code example of how to loop through AutoCAD versions and create the relevant LspLoad registry entries for an imaginary application called "MyCADApp". It is purely to demonstrate the mechanism. It is stripped down to just do 64bit ACAD on 64bit Windows to demonstrate the principle.
Once you've got a handle on the pascal scripting, it should be relatively straight forward to modify/expand it to add tests for 32bit CAD on 64bit Windows and 32bit CAD on 32bit Windows and of course do similar for Bricscad. All the additional functions you may require eg "IsWin64" can be found in the "Support Function Reference" in the Inno Setup Help files.
procedure AddACADRegKey (Release: String); {eg 'R19.0 for ACAD 2013'}
var
RunTimeNum: String; {eg '19'}
AllProductID: TArrayOfString;
ProductID: String; {eg 'ACAD-9001:409'}
KeyPathShort: String;{eg 'SOFTWARE\Autodesk\AutoCAD\'}
KeyPathLong: String; {eg 'SOFTWARE\Autodesk\AutoCAD\R18.1\ACAD-9001:409\Applications\MyCADApp'}
KeyStringShort: String; {eg c:\Program Files\MyCADApp\LspLoad.'}
KeyStringLong: String; {eg 'c:\Program Files\MyCADApp\LspLoad.19.x64.arx'}
I: Integer;
begin
RunTimeNum := Copy (Release, 2, 2);
KeyStringShort := ExpandConstant('{pf}\MyCADApp\LspLoad.');
KeyPathShort := 'SOFTWARE\Autodesk\AutoCAD\';
if RegGetSubkeyNames(HKLM64, KeyPathShort + Release, AllProductID)
then begin
for I := 1 to GetArrayLength(AllProductID) do begin
ProductID := AllProductID[I-1];
KeyPathLong := KeyPathShort + Release + '\' + ProductID + '\Applications\MyCADApp';
KeyStringLong := KeyStringShort + RunTimeNum + '.x64.arx';
RegWriteDWordValue (HKLM64, KeyPathLong,'LOADCTRLS', 2);
RegWriteStringValue (HKLM64, KeyPathLong,'LOADER',KeyStringLong);
end;
end;
end;
An example of its useage - to test for ACAD 2012 and ACAD 2013 and add the registry entries triggered by an end installation event you would add the following code:
procedure CurStepChanged(CurStep: TSetupStep);
begin
if CurStep=ssPostInstall
then begin
AddAcadRegKey ('R18.2');{ACAD 2012}
AddAcadRegKey ('R19.0');{ACAD 2013}
end;
end;
You will find additional information in that discussion thread.
Here is one example I am examining in the registry:
Now, the code I showed you creates those keys:
RegWriteDWordValue (HKLM64, KeyPathLong,'LOADCTRLS', 2);
RegWriteStringValue (HKLM64, KeyPathLong,'LOADER',KeyStringLong);
Have you actually tried it? Why don't you manually add your VLX to the startup suite and then look at the changes made to the registry? Then you know what you need to do.
There is also information here which I found with one search in Google:
Load a .NET assembly
After you have determined the build type of your .NET assembly, you must determine how it will be loaded into AutoCAD. A .NET assembly file can be loaded manually or with demand loading.
Manually - Use the NETLOAD command at the Command prompt or within an AutoLISP file.
Demand load - Define a key specific to the application you want to load when AutoCAD starts up. The key must be placed under the Application key for the specific release of AutoCAD that you want your application to be loaded in.
The key for the application can contain the following keys:
DESCRIPTION
Description of the .NET assembly and is optional.
LOADCTRLS
Controls how and when the .NET assembly is loaded.
1 - Load application upon detection of proxy object
2 - Load the application at startup
4 - Load the application at start of a command
8 - Load the application at the request of a user or another application
16 - Do not load the application
32 - Load the application transparently
LOADER
Specifies which .NET assembly file to load.
MANAGED
Specifies the file that should be loaded is a .NET assembly or ObjectARX file. Set to 1 for .NET assembly files.
You should use the autoloader bundle format. Then you don't have to mess with registry keys, and your Inno Setup script is just installing to the Autodesk\ApplicationPlugins folder under the user data folder, Program Data, or Program Files.
Related
We use Inno Setup for our installer. Recently a user reported the following error during installation:
An error occurred while trying to copy a file: the source file is corrupted
This was due to a setup file that was indeed corrupted somehow.
Ideally the setup EXE would have performed some kind of check upon initialization to see if the entire EXE was valid or not. But apparently it only did this on a file-by-file basis. Is it possible to get InnoSetup to do that?
I looked in Inno Setup documentation for keywords like 'check', 'hash', etc. but didn't see anything - perhaps I missed it.
Quite similar question (from about 10 years ago - though specifically asking about MD5): How to implement MD5 check into Inno Setup installer to get 'like NSIS integrity check'? . That question seemed to state that such a check should already be happening. So perhaps the issue is not whether or not the setup EXE is validated but when this information is used / shown to the user. Also the accepted answer seemed quite manual, ideally I'd like Inno to do this itself.
Similar question with a different error message: "Source file corrupted: SHA-1 hash mismatch" error from Inno Setup
Add a checksum to the installer and verify it when the installer is starting. A standard (and recommended) way to do that is to sign the installer using code signing certificate. It's a must anyway these days.
Easy way to verify the signature is using PowerShell Get-AuthenticodeSignature. You need PowerShell 5.1 for that. It is bundled with Windows 10 Build 14393 (August 2016) and newer. The following code uses that (and skips the check on older versions of Windows).
function InitializeSetup(): Boolean;
var
WindowsVersion: TWindowsVersion;
S: string;
ResultCode: Integer;
begin
Result := True;
GetWindowsVersionEx(WindowsVersion);
Log(Format('Windows build %d', [WindowsVersion.Build]));
// TODO: Better would be to check PowerShell version
if WindowsVersion.Build < 14393 then
begin
Log('Old version of Windows, skipping certificate check');
end
else
begin
S := ExpandConstant('{srcexe}');
if (Pos('''', S) > 0) or (Pos('"', S) > 0) then
RaiseException('Possible code injection');
S := 'if ((Get-AuthenticodeSignature ''' + S + ''').Status -ne ''Valid'') ' +
'{ exit 1 }';
if ExecAsOriginalUser(
'powershell', '-ExecutionPolicy Bypass -command "' + S + '"',
'', SW_HIDE, ewWaitUntilTerminated, ResultCode) and
(ResultCode = 0) then
begin
Log('Installer signature is valid');
end
else
begin
S := 'Installer signature is not valid. Are you sure you want to continue?';
Result := (MsgBox(S, mbError, MB_YESNO) = IDYES);
end;
end;
end;
If you need to support older versions of Windows, you will have to use more complicated methods, like:
Bundling signtool with the installer (not sure about license here);
Using X509Certificate class.
See How to check if a file has a digital signature.
I am trying to create a distributable .exe file with Inno Setup tools and Inno Download Plugin. The resulting file is ~3GB in size, split in 6 parts (1 for the executable, 5 bins containing all the files).
Would it be possible to keep the 5 bins uploaded on some server and download them during installation with the remaining executable file?
My code is here :
procedure InitializeWizard();
var
ResultCode: integer;
TempAddress: String;
FinalSavePath: String;
UserName, UserCompany: String;
begin
idpSetOption('DetailedMode', '1');
idpSetOption('AllowContinue', '1');
idpSetLogin('aaa', 'aaa');
idpAddFile('https://...', target_path);
idpAddFile('https://...', target_path);
idpAddFile('https://...', target_path);
idpAddFile('https://...', target_path);
idpDownloadAfter(wpWelcome);
end;
With idpDownloadAfter(wpWelcome) the installer starts downloading right after accepting to run the executable, if .bin files are already present. If not, the installer just keeps asking for the .bin to be present.
Inno Setup 6.1 has a built-in support for file downloads, which does not need any support files. So the solution below is obsolete now. See Inno Setup: Install file from Internet.
Inno Download Plugin uses idp.dll, which itself is stored in the mysetup-*.bin files. That's why you get prompted for the .bin files, even before anything starts. You need the idp.dll so that the download itself can start.
With some hacking you can have the idp.dll be stored in the [Code], hence directly in the mysetup.exe.
See Inno Setup: Reading a file from installer during uninstallation.
You will need to modify the idp.iss as follows:
Remove the [Files] section with its reference to idp.dll.
In all the external functions declarations:
change #files:idp.dll cdecl to #{tmp}\idp.dll cdecl delayload.
To the front of your .iss script, copy the long code block from my answer to the previously mentioned question.
And now you can do:
procedure InitializeWizard();
begin
SaveBinaryStringToFile(
ExpandConstant('{tmp}\idp.dll'), {#FileToBinaryString("unicode\idp.dll")});
idpAddFile(
'https://www.example.com/mysetup-1.bin', ExpandConstant('{src}\mysetup-1.bin'));
idpDownloadAfter( {whatever} );
end;
Make sure you update the path to the idp.dll to the correct location on your development machine in the call to FileToBinaryString.
The code is for Unicode version of Inno Setup (the only version as of Inno Setup 6).
We are having the following requirement that needs to be done in Inno Setup. We need to support installation of files based on the password and also automatic update of the next versions either via internet update or DVD
Requirement is:
We have several common files for one application
on top of that, we need to install FeatureA or FeatureB or FeatureC depending upon a password per feature. Like this we are having 20 different features.
The user will install only one feature at a time. But they are allowed to add additional features based on a password.
Above scenario is for running setup from the DVD image. In case of int updates, all the features installed by the customer should automatically be updated without password prompt from the user. It should be done silently.
Example:
PC where our software was not installed earlier. Customer using SWVER001 DVD. Install with Feature1PWD => Basic SW + common files + Feature1 files will be installed
Again install using SWVER001 DVD. This time user gives Feature2PWD ==> Feature2 files will be installed. Basic SW + Commonfiles + Feature1 files will be retained and untouched. Main Sw will see both the Feature 1 and Feature 2
User installs SWVER002 using internet update. Here Setup should see both the Basic SW + Common files + Feature1 files + Feature2 files. It should update all the 4 together at once without any input from the user. Silent update would be very good
I am thinking of the following approach
1. Create one main installer with basic/common installation files
2. Then create sub installer per feature
3. Main setup will then call the sub installer based on the passowrd.
4. Main setup will then store the previous features selected in registry/ini file
In case of int update, get the previous feature selected from registry/ini and then do the silent installation automatically without any user input
Any other better suggestions available for configuring above things in the Inno Setup?
It's way easier to create a component per feature and automatically select the component according to entered password.
Something like:
[Components]
Name: "FeatureA"; Description: "Feature A"
Name: "FeatureB"; Description: "Feature B"
Name: "FeatureC"; Description: "Feature C"
[Code]
function TestComponentPassword(
Password: string; Component: string; ComponentPassword: string): Boolean;
var
I: Integer;
begin
Result := (Password = ComponentPassword);
if Result then
begin
for I := 0 to WizardForm.ComponentsList.Items.Count - 1 do
begin
WizardForm.ComponentsList.Checked[I] :=
(WizardForm.ComponentsList.Items[I] = Component);
end;
end;
end;
function CheckPassword(Password: String): Boolean;
begin
Result :=
TestComponentPassword(Password, 'Feature A', 'aaa') or
TestComponentPassword(Password, 'Feature B', 'bbb') or
TestComponentPassword(Password, 'Feature C', 'ccc');
end;
In Inno Setup 6, you can use WizardSelectComponents instead of looking up the component by its name.
For update, create a separate installer for each component/feature. Use the same AppId for all installers, so that they share the uninstall log.
After creating my setup.exe I have to pack it for various software deployment tools. Therefore I can't call the setup.exe with parameters, instead I have placed my own parameters in a setup.ini file next to the setup.exe
[Code]
var
MyIniFile: String;
function InitializeSetup(): Boolean;
var
LoadFromIniFile: String;
begin
Result := true;
MyIniFile := ExpandConstant('{srcexe}'); //writes the full path of the setup.exe in "MyIniFile"
MyIniFile := Copy(MyIniFile, 1, Length(MyIniFile) - Length(ExtractFileExt(MyIniFile))) + '.ini'; //changes the ".exe" into ".ini"
if FileExists(MyIniFile) then LoadFromIniFile := MyIniFile; //checks wether there is a ini-file
if LoadFromIniFile <> '' then begin
MyLogFile := GetIniString('Setup', 'Log', MyLogFile , LoadFromIniFile);
ProductName := GetIniString('Setup', 'ProductName', ProductName, LoadFromIniFile);
end;
end;
Now I want to also place the so called "Setup Command Line Parameters" (listed on the Inno Setup Help site) in my ini-file. I think that there is a way for the /Dir="x:\dirname parameter, which I did not figure out yet. But I also want to have the /SILENT parameter in there, do you think there is a way to do this? If yes, how would you do this? If not, can you please give me a hint why not?
So customize your installer for different products, I'd recommend you to use a pre-processor and automatically build the installer for each product (with different "defines"), instead of using an external INI file.
For example to be able to change application name and resulting executable when building the installer, use a script like:
[Setup]
AppName={#AppName}
OutputBaseFilename={#BaseFilename}
Now you can create two different installers automatically using command-line:
ISCC.exe Example1.iss /dAppName=App1 /dBaseFilename=SetupApp1
ISCC.exe Example1.iss /dAppName=App2 /dBaseFilename=SetupApp2
Regarding the implicit silent installation:
There's no API other than the command-line /SILENT switch to trigger silent installation.
But you can create a near-silent installation by disabling most installer pages:
[Setup]
DisableWelcomePage=true
DisableDirPage=true
DisableProgramGroupPage=true
DisableReadyPage=true
DisableFinishedPage=true
Actually the above example disables all default pages. But Inno Setup compiler will ignore the DisableReadyPage=true, if all other previous pages are disabled.
You may want to choose a different page to show instead. For example a Welcome page (by omitting DisableWelcomePage=true, but keeping the DisableReadyPage=true).
If you do not mind about using external files (as you already use an external INI file), you can of course wrap the installer to a batch file and call the installer with the /SILENT switch.
Is there some way to set the DefaultDirName by code depending on some decission a user did on installtion?
Let me comment:
I have some code which is build for two different systems (using different interops/ocx's and such stuff). My input files are stored in two directories input\A and input\B.
I want to have only one setup-file for both systems.
In the setup file i use CreateInputOptionPage with 2 options to determin which files to install (using Check on each file). This works okay.
But i do also have some ShellExec on finish of setup, which at the moment uses {app} to e.g. register some .Net classes and ShellExec to unregister the .Net classes on InitializeUninstall (also uses {app})
The setup must install the software on two different locations (depending on the selection of the user (eg. c:\software_a or c:\software_b). Can't change this.
So is there some way to specify the DefaultDirName before the files get copied to the system, so i can use the same ShellExec on install and uninstall? I could of course add the same ShellExec for both systems on installtation and use an if to check which files to register (depending on the user selection) but on uninstall i would not have this information (user selection), so i can not unregister the .Net classes.
thanks
In your CreateInputOptionPage code section, you might be able to set a value then use that value in the code snippet below. I haven't tested it but it might work.
[Setup]
DefaultDirName={code:getpath}
[Code]
function GetPath( Default: string ): string;
begin
if (CreateInputOptionPageValue1) then
Result := ExpandConstant({sd}) + '\path1';
else
Result := ExpandConstant({sd}) + '\path2';
end;
If you need to change the install folder after the DefaultDirName has been initialized, this was working for me quite well:
procedure CurPageChanged(CurPageID: Integer);
begin
{ updates the install path depending on the install type or the entered suffix }
if CurPageID = wpSelectDir then begin
WizardForm.DirEdit.Text := ExpandConstant('{pf}') + '\MyAppName' + GetAppSuffix('');
end;
end;
Cheers
Chris