Creating a shortcut with two files names one being variable? - inno-setup

I want to create a shortcut that calls two files, first, it calls Excel.exe, then it calls my add-in.
I tested it doing the following:
Target:
"C:\Program Files\Microsoft Office\OFFICE11\EXCEL.EXE" "C:\MyAddin.xll"
And it works fine. Now I want to implement it in inno-setup.
I have to get the Excel.exe location via some automation in inno-setup, which I store in a global variable.
This is what I've tried:
Name: {commondesktop}\{#MyAppName}; Filename: ExcelExecutablePath;
Parameters: {app}\{#MyAppExeName}; Tasks: desktopicon;
Flags: CreateOnlyIfFileExists; IconFilename: {app}\Icons\TimeCard64.ico;
I've tried other things too, but I'm at a bit of a loss on this one.
Thanks in advance. Let me know if I should be more clear on something!

To find the location of 'excel', you can query the 'App Paths' registry key if it includes 'excel.exe' in a function in code section. Example:
 
[Icons]
Name: "{commondesktop}\My Excel File"; Filename: "{code:GetExcelPath}"; Parameters: """C:\MyAddin.xll"""
..
[Code]
function GetExcelPath(dummy: string): string;
begin
RegQueryStringValue(HKEY_LOCAL_MACHINE, 'SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\excel.exe', '', Result);
if Result = '' then
Result := 'excel.exe';
end;

Related

Default behavior and custom behavior for changing the type combobox in inno setup

In my setup tool I want a specific behavior on the Select Components wizard page. The installer contains several types, one of them is a custom. If the user selects one of the setup types, it is not possible to change the check boxes (similar to components flagged fixed). But if the user selects "custom", the checkboxes are supposed to be enabled.
Enable and disable the checkboxes can easily be done by changing the procedure WizardForm.TypesCombo.OnChange. When doing so unfortunately the default behavior with selecting the components according to the setup types does not work anymore.
The question is, how can I do both on the "change" event of the type combo box?
I tried to store the default implementation into a function pointer and call this in the customized change procedure (see commented lines in the code), but did not succeed. I am getting compiler errors.
Here is my inno setup script:
[Setup]
AppId={{8D76F99A-82A1-4995-A470-BA9B69F83F67}
AppName=MyAppName
AppVersion=1.0.1
Uninstallable=no
DefaultDirName=C:\MyPath\Versions
SetupLogging=yes
[Types]
Name: "full"; Description: "Complete installation (Base System & optional 3rd Party SW)";
Name: "base_only"; Description: "Basic installation without optional";
Name: "custom"; Description: "Custom installation"; Flags: iscustom
[Components]
Name: "Base"; Description: "Base with required 3rd Party SW"; Types: full base_only ;
Name: "Base\Redist"; Description: "Redistributables"; Types: full base_only ;
Name: "Base\NTP"; Description: "NTP"; Types: full base_only ;
Name: "Base\WinSCP"; Description: "WinSCP"; Types: full base_only ;
Name: "ThirdPartyOptional"; Description: "Optional 3rd Party SW"; Types: full ;
Name: "ThirdPartyOptional\7Zip"; Description: "7Zip"; Types: full ;
Name: "ThirdPartyOptional\WinMerge"; Description: "WinMerge"; Types: full ;
Name: "ThirdPartyOptional\Notepad"; Description: "Notepad++"; Types: full ;
Name: "ThirdPartyOptional\Putty"; Description: "Putty"; Types: full ;
[Code]
type
TMyOnChange = procedure(Sender: TObject);
procedure TypeChange (Sender: TObject);
var
i: Integer;
begin
for i := 0 to WizardForm.ComponentsList.Items.count - 1 do
begin
WizardForm.ComponentsList.ItemEnabled[i] := (WizardForm.TypesCombo.Text = 'Custom installation');
end;
//TMyOnChange(Sender); // this throws an compiler error: type mismatch
end;
procedure InitializeWizard;
begin
// try to get default implementation of types combo change
//TMyOnChange := WizardForm.TypesCombo.OnChange; // this throws an compiler error: internal error (20)
// add callback function for type changed
WizardForm.TypesCombo.OnChange := #TypeChange;
// initialize the wpSelectComponents page
TypeChange(nil);
end;

Pascal Scripting: Canceling setup before {app} variable is set

I have some declarations at the [Dirs]-section in my Inno Setup file. I use "Inno Setup Compiler" and a normal text editor (Notepad++) for developing.
When I cancel the setup before choosing the install directory, the {app} variable is empty for sure.
I get this error (which is totally logic):
How can I fix that no error occurs after pressing the "Cancel" button and committing that I want to cancel the setup?
Internal error: An attempt was made to expand the "app" constant
before it was initialized.
Can I globally set the {app} variable or give it a default value?
Here is a code snippet where I use the variable {app}:
[Dirs]
Name: {app}; Permissions: everyone-readexec
Name: {app}\bin; Permissions: everyone-readexec
[Run]
Filename: "{app}\run.exe; Flags: runhidden
[INI]
Filename: {app}\bin\myIni.ini; Section: Settings;
[InstallDelete]
Name: {app}\*; Type: filesandordirs; Tasks:
Thanks for help,
regards,
C.
Either you should skip the code, which attempts to expand the {app} constant before it's initialized, or as a workaround you can use the WizardDirValue, which actually returns value to the {app} when it's being expanded. Even reference mentions that (emphasized by me):
Returns the current contents of the edit control on the Select
Destination Location page of the wizard.
Unlike ExpandConstant('{app}'), this function will not fail if called after the wizard is shown but prior to the user selecting a
directory. Rather, it will return the default directory name.
In the most recent source code you can see how the {app} constant is expanded on this line.
Thanks for helping, the problem got solved!
Before the user reaches the 'Select Destination Location' the {app} variable is not set.
My DeInitialize-Procedure looked like this:
procedure DeinitializeSetup();
var
SettingsPath: String;
begin
SettingsPath := ExpandConstant('{app}')
DelTree(SettingsPath + '\bin', True, True, True);
end;
What I did is I created a Boolean variable at the beginning:
[Code]
var appIsSet: Boolean;
I set it to false at initializing:
function InitializeSetup(): Boolean;
begin
// interesting code
appIsSet := False;
end;
... and set it to 'true' after the user has reached 'wpSelectDir' in nextButtonClick (see code snippet below:)
begin
if CurPageID = wpSelectDir then
begin
appIsSet := True;
The last step is to check in the Deinitialize-Procedure if the boolean variable is set. If so, he can access on it, if not - do nothing:
procedure DeinitializeSetup();
var
SettingsPath: String;
begin
if appIsSet then begin
SettingsPath := ExpandConstant('{app}')
DelTree(SettingsPath + '\bin', True, True, True);
end;
end;

Inno Setup: RegValueExists does not return true, trying to check Registry Key

I want to show Components based on the existence of a registry key:
[Components]
Name: "MyProgram"; Description: "MyProgram"; Check: RegistryCheck
This is the corresponding function:
function RegistryCheck: Boolean;
begin
Result := RegValueExists(HKEY_LOCAL_MACHINE, 'SOFTWARE\Bricsys', 'RegisteredOwner')
end;
I don't know what's the mistake, the installed program which has to be checked is x64, running IS on a x64 machine.
Key:
Rootkey: HKEY_LOCAL_MACHINE
Name: RegisteredOwner
Type: REG_SZ
Data: User
If you are trying to install on a 64bit OS you may be looking in the wrong RootKey.
Try using the following instead...
RegValueExists(HKLM64, 'SOFTWARE\Bricsys', 'RegisteredOwner')

Inno Setup, APP start When windows start

For Inno Setup,
I would like to create a checkbox Task for MyAPP Auto Start when Windows Start.
My code like below :
And, How to write the codes below - DO_Set_AutoStart_WhenWindowsStart()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[Tasks]
Name: "StartMenuEntry" ; Description: "Start my app when Windows starts" ; GroupDescription: "Windows Startup"; MinVersion: 4,4;
[code]
//Do Additional Task - Auto Start when Windows Start
function NextButtonClick(CurPageID: Integer): Boolean;
var
Index: Integer;
begin
Result := True;
if CurPageID = wpSelectTasks then
begin
Index := WizardForm.TasksList.Items.IndexOf('Start my app when Windows starts');
if Index <> -1 then
begin
if WizardForm.TasksList.Checked[Index] then
MsgBox('First task has been checked.', mbInformation, MB_OK)
DO_Set_AutoStart_WhenWindowsStart();
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
else
MsgBox('First task has NOT been checked.', mbInformation, MB_OK);
end;
end;
end;
You don't need to make use of the [code] section to add an automatic starting app.
There are different ways to accomplish this, for example
[icons]
Name: "{userstartup}\My Program"; Filename: "{app}\MyProg.exe"; Tasks:StartMenuEntry;
Name: "{commonstartup}\My Program"; Filename: "{app}\MyProg.exe"; Tasks:StartMenuEntry;
The difference between {userstartup} and {commonstartup}, if not obvious, is that {userstartup} affects the startup menu entry for the current user and {commonstartup} affects all the users of the target machine.
Edit
You may also use the registry to start an application. I'm adding this because the OP mentioned in comments the described method doesn't work on windows 8 (because the lack of start menu, which I forgot). I have no windows 8 at hand to test, so it's up to you to test if this works on windows 8 or not.
The Run keys in the registry exists since WinXP, so you can configure windows to auto-run a program from the installer adding something like this:
[Registry]
;current user only
Root: HKCU; Subkey: "Software\Microsoft\Windows\CurrentVersion\Run"; ValueType: string; ValueName: "MyProgram"; ValueData: "{app}\MyProg.exe"; Tasks:AutoRunRegistry;
;any user
Root: HKLM; Subkey: "Software\Microsoft\Windows\CurrentVersion\Run"; ValueType: string; ValueName: "MyProgram"; ValueData: "{app}\MyProg.exe"; Tasks:AutoRunRegistry;
Don't miss I'm also changing the Tasks parameter in the example to AutoRunRegistry.

Add installation type, maintain the predefined ones

I'd like to add an own installation type into an Inno setup project, while keeping the original ones (Full, Compact and Custom). The problem is, when I create the [Types] section, these installation types are lost and I have to redefine them.
If this is not possible, okay then, let's redefine them. But I'd like to use the original language constants from the .isl files. I haven't found any option, how to use [Message]-like declarations as constants in [CustomMessage] way (e. g. {cm:LaunchProgram}) in the Types' Description parameter. Is there any option, how to do this?
Here is how you can do it, using [CustomMessages]
[CustomMessages]
FullInstall=Full installation
CompactInstall=Compact installation
CustomInstall=Custom installation
[Types]
Name: "full"; Description: "{cm:FullInstall}"
Name: "compact"; Description: "{cm:CompactInstall}"
Name: "custom"; Description: "{cm:CustomInstall}"; Flags: iscustom
Here is how you can do it using [Messages] values.
[Types]
Name: "full"; Description: "{code:FullInstall}"
Name: "compact"; Description: "{code:CompactInstall}"
Name: "custom"; Description: "{code:CustomInstall}"; Flags: iscustom
[Code]
function FullInstall(Param : String) : String;
begin
result := SetupMessage(msgFullInstallation);
end;
function CustomInstall(Param : String) : String;
begin
result := SetupMessage(msgCustomInstallation);
end;
function CompactInstall(Param : String) : String;
begin
result := SetupMessage(msgCompactInstallation);
end;

Resources