Skip to content

Commit d3b815c

Browse files
committed
Windows installer script added
1 parent a2c9100 commit d3b815c

File tree

4 files changed

+300
-1
lines changed

4 files changed

+300
-1
lines changed

.gitignore

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,8 @@ cabal.project.local~
2323

2424
examples/plots/
2525
examples/*.html
26-
stack.yaml.lock
26+
stack.yaml.lock
27+
28+
# Installer-related
29+
installer/setup*
30+
installer/*.exe

build-setup.ps1

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Build windows installer
2+
3+
Write-Host "Cleaning .stack-work directory"
4+
stack clean --full
5+
6+
Write-Host "Building executable"
7+
stack install pandoc-plot --local-bin-path ".\installer"
8+
9+
# Extract version from cabal file
10+
# This is so we can dynamically name the installer using the exe version
11+
$regex = "^version:\s+\d+.\d+.\d+.\d+"
12+
$versionString = Select-String -Path ".\pandoc-plot.cabal" -Pattern $regex -AllMatches
13+
$version = ($versionString.Matches.Value -split "\s+")[1]
14+
Write-Host "Version: " $version
15+
16+
Write-Host "Building setup using Inno Setup Compiler"
17+
if ($ENV:PROCESSOR_ARCHITECTURE -eq "AMD64"){
18+
$iscc = get-item "C:\Program Files (x86)\Inno Setup 5\ISCC.exe"
19+
}
20+
else {
21+
$iscc = get-item "C:\Program Files\Inno Setup 5\ISCC.exe"
22+
}
23+
& $iscc /dAppVersion=$version ".\installer\pandoc-plot-setup.iss"

installer/modpath.iss

Lines changed: 219 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,219 @@
1+
// ----------------------------------------------------------------------------
2+
//
3+
// Inno Setup Ver: 5.4.2
4+
// Script Version: 1.4.2
5+
// Author: Jared Breland <[email protected]>
6+
// Homepage: http://www.legroom.net/software
7+
// License: GNU Lesser General Public License (LGPL), version 3
8+
// http://www.gnu.org/licenses/lgpl.html
9+
//
10+
// Script Function:
11+
// Allow modification of environmental path directly from Inno Setup installers
12+
//
13+
// Instructions:
14+
// Copy modpath.iss to the same directory as your setup script
15+
//
16+
// Add this statement to your [Setup] section
17+
// ChangesEnvironment=true
18+
//
19+
// Add this statement to your [Tasks] section
20+
// You can change the Description or Flags
21+
// You can change the Name, but it must match the ModPathName setting below
22+
// Name: modifypath; Description: &Add application directory to your environmental path; Flags: unchecked
23+
//
24+
// Add the following to the end of your [Code] section
25+
// ModPathName defines the name of the task defined above
26+
// ModPathType defines whether the 'user' or 'system' path will be modified;
27+
// this will default to user if anything other than system is set
28+
// setArrayLength must specify the total number of dirs to be added
29+
// Result[0] contains first directory, Result[1] contains second, etc.
30+
// const
31+
// ModPathName = 'modifypath';
32+
// ModPathType = 'user';
33+
//
34+
// function ModPathDir(): TArrayOfString;
35+
// begin
36+
// setArrayLength(Result, 1);
37+
// Result[0] := ExpandConstant('{app}');
38+
// end;
39+
// #include "modpath.iss"
40+
// ----------------------------------------------------------------------------
41+
42+
procedure ModPath();
43+
var
44+
oldpath: String;
45+
newpath: String;
46+
updatepath: Boolean;
47+
pathArr: TArrayOfString;
48+
aExecFile: String;
49+
aExecArr: TArrayOfString;
50+
i, d: Integer;
51+
pathdir: TArrayOfString;
52+
regroot: Integer;
53+
regpath: String;
54+
55+
begin
56+
// Get constants from main script and adjust behavior accordingly
57+
// ModPathType MUST be 'system' or 'user'; force 'user' if invalid
58+
if ModPathType = 'system' then begin
59+
regroot := HKEY_LOCAL_MACHINE;
60+
regpath := 'SYSTEM\CurrentControlSet\Control\Session Manager\Environment';
61+
end else begin
62+
regroot := HKEY_CURRENT_USER;
63+
regpath := 'Environment';
64+
end;
65+
66+
// Get array of new directories and act on each individually
67+
pathdir := ModPathDir();
68+
for d := 0 to GetArrayLength(pathdir)-1 do begin
69+
updatepath := true;
70+
71+
// Modify WinNT path
72+
if UsingWinNT() = true then begin
73+
74+
// Get current path, split into an array
75+
RegQueryStringValue(regroot, regpath, 'Path', oldpath);
76+
oldpath := oldpath + ';';
77+
i := 0;
78+
79+
while (Pos(';', oldpath) > 0) do begin
80+
SetArrayLength(pathArr, i+1);
81+
pathArr[i] := Copy(oldpath, 0, Pos(';', oldpath)-1);
82+
oldpath := Copy(oldpath, Pos(';', oldpath)+1, Length(oldpath));
83+
i := i + 1;
84+
85+
// Check if current directory matches app dir
86+
if pathdir[d] = pathArr[i-1] then begin
87+
// if uninstalling, remove dir from path
88+
if IsUninstaller() = true then begin
89+
continue;
90+
// if installing, flag that dir already exists in path
91+
end else begin
92+
updatepath := false;
93+
end;
94+
end;
95+
96+
// Add current directory to new path
97+
if i = 1 then begin
98+
newpath := pathArr[i-1];
99+
end else begin
100+
newpath := newpath + ';' + pathArr[i-1];
101+
end;
102+
end;
103+
104+
// Append app dir to path if not already included
105+
if (IsUninstaller() = false) AND (updatepath = true) then
106+
newpath := newpath + ';' + pathdir[d];
107+
108+
// Write new path
109+
RegWriteStringValue(regroot, regpath, 'Path', newpath);
110+
111+
// Modify Win9x path
112+
end else begin
113+
114+
// Convert to shortened dirname
115+
pathdir[d] := GetShortName(pathdir[d]);
116+
117+
// If autoexec.bat exists, check if app dir already exists in path
118+
aExecFile := 'C:\AUTOEXEC.BAT';
119+
if FileExists(aExecFile) then begin
120+
LoadStringsFromFile(aExecFile, aExecArr);
121+
for i := 0 to GetArrayLength(aExecArr)-1 do begin
122+
if IsUninstaller() = false then begin
123+
// If app dir already exists while installing, skip add
124+
if (Pos(pathdir[d], aExecArr[i]) > 0) then
125+
updatepath := false;
126+
break;
127+
end else begin
128+
// If app dir exists and = what we originally set, then delete at uninstall
129+
if aExecArr[i] = 'SET PATH=%PATH%;' + pathdir[d] then
130+
aExecArr[i] := '';
131+
end;
132+
end;
133+
end;
134+
135+
// If app dir not found, or autoexec.bat didn't exist, then (create and) append to current path
136+
if (IsUninstaller() = false) AND (updatepath = true) then begin
137+
SaveStringToFile(aExecFile, #13#10 + 'SET PATH=%PATH%;' + pathdir[d], True);
138+
139+
// If uninstalling, write the full autoexec out
140+
end else begin
141+
SaveStringsToFile(aExecFile, aExecArr, False);
142+
end;
143+
end;
144+
end;
145+
end;
146+
147+
// Split a string into an array using passed delimeter
148+
procedure MPExplode(var Dest: TArrayOfString; Text: String; Separator: String);
149+
var
150+
i: Integer;
151+
begin
152+
i := 0;
153+
repeat
154+
SetArrayLength(Dest, i+1);
155+
if Pos(Separator,Text) > 0 then begin
156+
Dest[i] := Copy(Text, 1, Pos(Separator, Text)-1);
157+
Text := Copy(Text, Pos(Separator,Text) + Length(Separator), Length(Text));
158+
i := i + 1;
159+
end else begin
160+
Dest[i] := Text;
161+
Text := '';
162+
end;
163+
until Length(Text)=0;
164+
end;
165+
166+
167+
procedure CurStepChanged(CurStep: TSetupStep);
168+
var
169+
taskname: String;
170+
begin
171+
taskname := ModPathName;
172+
if CurStep = ssPostInstall then
173+
if IsTaskSelected(taskname) then
174+
ModPath();
175+
end;
176+
177+
procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep);
178+
var
179+
aSelectedTasks: TArrayOfString;
180+
i: Integer;
181+
taskname: String;
182+
regpath: String;
183+
regstring: String;
184+
appid: String;
185+
begin
186+
// only run during actual uninstall
187+
if CurUninstallStep = usUninstall then begin
188+
// get list of selected tasks saved in registry at install time
189+
appid := '{#emit SetupSetting("AppId")}';
190+
if appid = '' then appid := '{#emit SetupSetting("AppName")}';
191+
regpath := ExpandConstant('Software\Microsoft\Windows\CurrentVersion\Uninstall\'+appid+'_is1');
192+
RegQueryStringValue(HKLM, regpath, 'Inno Setup: Selected Tasks', regstring);
193+
if regstring = '' then RegQueryStringValue(HKCU, regpath, 'Inno Setup: Selected Tasks', regstring);
194+
195+
// check each task; if matches modpath taskname, trigger patch removal
196+
if regstring <> '' then begin
197+
taskname := ModPathName;
198+
MPExplode(aSelectedTasks, regstring, ',');
199+
if GetArrayLength(aSelectedTasks) > 0 then begin
200+
for i := 0 to GetArrayLength(aSelectedTasks)-1 do begin
201+
if comparetext(aSelectedTasks[i], taskname) = 0 then
202+
ModPath();
203+
end;
204+
end;
205+
end;
206+
end;
207+
end;
208+
209+
function NeedRestart(): Boolean;
210+
var
211+
taskname: String;
212+
begin
213+
taskname := ModPathName;
214+
if IsTaskSelected(taskname) and not UsingWinNT() then begin
215+
Result := True;
216+
end else begin
217+
Result := False;
218+
end;
219+
end;

installer/pandoc-plot-setup.iss

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
; Script generated by the Inno Setup Script Wizard.
2+
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!
3+
4+
#define AppName "pandoc-plot"
5+
#define AppEXEName "pandoc-plot.exe"
6+
#define AppPublisher "Laurent P. René de Cotret"
7+
#define AppURL "https://github.com/LaurentRDC/pandoc-plot"
8+
9+
[Setup]
10+
; NOTE: The value of AppId uniquely identifies this application.
11+
; Do not use the same AppId value in installers for other applications.
12+
; (To generate a new GUID, click Tools | Generate GUID inside the IDE.)
13+
AppId={{4AD298C3-6FD5-49B2-9E4A-8FEB19C63640}
14+
AppName={#AppName}
15+
AppVersion={#AppVersion}
16+
AppVerName={#AppName} {#AppVersion}
17+
AppPublisher={#AppPublisher}
18+
AppPublisherURL={#AppURL}
19+
AppSupportURL={#AppURL}
20+
AppUpdatesURL={#AppURL}
21+
DefaultDirName={pf}\{#AppName}
22+
DisableProgramGroupPage=yes
23+
ChangesEnvironment=true
24+
LicenseFile=..\LICENSE
25+
OutputDir=.\setup-{#AppVersion}
26+
OutputBaseFilename={#AppName}-wininst-{#AppVersion}
27+
Compression=lzma2/ultra64
28+
SolidCompression=yes
29+
30+
[Languages]
31+
Name: "english"; MessagesFile: "compiler:Default.isl"
32+
33+
[Files]
34+
Source: ".\pandoc-plot.exe"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
35+
; NOTE: Don't use "Flags: ignoreversion" on any shared system files
36+
37+
[Tasks]
38+
Name: "modifypath"; Description: "Add pandoc-pyplot executable to path"; Flags: checkedonce
39+
40+
[Run]
41+
Filename: "{app}\{#AppEXEName}"; Description: "{cm:LaunchProgram,{#StringChange(AppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent
42+
43+
[Code]
44+
const
45+
ModPathName = 'modifypath';
46+
ModPathType = 'user';
47+
48+
function ModPathDir(): TArrayOfString;
49+
begin
50+
setArrayLength(Result, 1)
51+
Result[0] := ExpandConstant('{app}');
52+
end;
53+
#include "modpath.iss"

0 commit comments

Comments
 (0)