Pascal CloseFile not found - pascal

I have been making a program in Delphi and what I am trying to do is set up me game with a 'save file'. I have been doing this in Delphi and not when I bring the code home I am just using a pascal compiler and I cannot seem to run my program as I get the following errors
Free Pascal Compiler version 2.6.2-8 [2014/01/22] for x86_64
Copyright (c) 1993-2012 by Florian Klaempfl and others
Target OS: Linux for x86-64
Compiling control.p
control.p(44,12) Error: Identifier not found "CloseFile"
control.p(116,14) Error: Identifier not found "closeFile"
control.p(127,13) Error: Identifier not found "assignFile"
control.p(143,4) Fatal: There were 3 errors compiling module, stopping
Fatal: Compilation aborted
Error: /usr/bin/ppcx64 returned an error exitcode (normal if you did not specify a source file to be compiled)
Sorry if this is a stupid question but I am new to files and I really want this to work. Below is all of my current code just in case you need it, sorry if its confusing its a draft and thanks for helping.
program Task3;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils;
Type
gameRec = record
name: string[30];
skill: integer;
str: integer;
modif: integer;
sskill: string[3];
sstr: string[3];
smodif: string[3];
sf: integer;
ssf : string[1];
end;
var
gameFile : file of gameRec;
p1, p2 : gameRec;
procedure showStats;
begin
FileMode := fmOpenRead;
Reset(gameFile);
read(gameFile, p1);
read(gameFile, p2);
writeln;
writeln(p1.name, '''s stats');
writeln('Skill: ', p1.skill);
writeln('Strenght: ', p1.str);
writeln('Modifier: ', p1.modif);
writeln;
writeln(p2.name, '''s stats');
writeln('Skill: ', p2.skill);
writeln('Strenght: ', p2.str);
writeln('Modifier: ', p2.modif);
writeln;
CloseFile(gameFile);
end;
procedure resetsf;
var
ran12, ran4, namelen: integer;
namepass: boolean;
name: string;
begin
writeln('No save file detected, generating new stats');
namelen := 0;
namepass := false;
repeat
write('What is player 1''s name: ');
readln(name);
namelen := length(name);
if (namelen > 2) and (namelen < 30) then
begin
p1.name := name;
namepass := true;
end
else
writeln('You name must be between 3 and 30 characters');
until namepass = true;
namepass := false;
repeat
write('What is player 2''s name: ');
readln(name);
namelen := length(name);
if (namelen > 2) and (namelen < 30) then
begin
p2.name := name;
namepass := true;
end
else
writeln('You name must be between 3 and 30 characters');
until namepass = true;
ran12 := random(12) + 1;
ran4 := random(4) + 1;
p1.skill := 10 + (ran12 div ran4);
ran12 := random(12) + 1;
ran4 := random(4) + 1;
p1.str := 10 + (ran12 div ran4);
ran12 := random(12) + 1;
ran4 := random(4) + 1;
p2.skill := 10 + (ran12 div ran4);
ran12 := random(12) + 1;
ran4 := random(4) + 1;
p2.str := 10 + (ran12 div ran4);
reWrite(gameFile);
p1.sskill := inttostr(p1.skill); //debug
p1.sstr := inttostr(p1.str);
p1.smodif := inttostr(p1.modif);
//write(gameFile,p1);
p2.sskill := inttostr(p2.skill);
p2.sstr := inttostr(p2.str);
p2.smodif := inttostr(p2.modif); //debug
write(gameFile,p2);
p1.sf := 1;
p1.ssf := inttostr(p1.sf);
write(gameFile,p1); //debug
closeFile(gameFile);
FileMode := fmOpenRead;
Reset(gameFile);
read(gameFile, p1);
read(gameFile, p2);
end;
begin
assignFile(gameFile, 'N:\gamerec.dat');
randomize;
writeln('Game :)');
writeln('By Sam Collins');
writeln;
FileMode := fmOpenRead;
Reset(gameFile);
read(gameFile, p1);
writeln(p1.sf);
if p1.sf = 0 then
resetsf
else
writeln('Save file detected using old stats');
showStats;
readln;
end.

If you want delphi compatibility, put the compiler in Delphi mode, either by compiling with -Sd or adding {$mode Delphi} to the source (somewhere at the top, e.g. near the $apptype).
Then closefile() and assignfile() will be accepted. The default dialect is turbo pascal. Lazarus puts FPC in objfpc (which is also delphi alike) by default.
Closefile is in an unit (objpas) with system unit enhancements that is only in scope in Delphi or objfpc modi.
Using namespaces (SYSTEM.sysutils instead of sysutils) might be dangerous too. Better simplify to sysutils. Namespaces is an Delphi extension that only got significant use with Delphi XE2.
I tested, and removing the {$R *.res}, the removal of system. before sysutils and -Sd makes the code compile

If I understood the question correctly, you want to port a piece of code from Delphi to Free Pascal and you have problems with file operations.
In Free (and Turbo) Pascal, file handling is much more easier than in Delphi: in Pascal we have Assign instead of AssignFile and Close instead of CloseFile . The syntax for these two procedures can be found in the help system.

Related

Pascal Segmentation Fault parsing Text File

I am working on a Question/Answer UI application in Pascal / Lazarus. My problem is that upon invoking below code through a button click, the program crashes with a Segmentation Fault error.
// more declarations... (UI Form, Buttons, ...)
type
TQuestion = class(TObject)
title: string;
answers: array of string;
correct: integer;
end;
var
questions: array of TQuestion;
procedure TForm1.BStartClick(Sender: TObject);
var
i: integer;
j: integer;
line: string;
arrayLength: integer;
question: TQuestion;
stringList: TStringList;
begin
stringList := TStringList.create;
stringList.LoadFromFile('questions.txt');
for i := 0 to stringList.Count - 1 do ;
begin
line := stringList[i];
if (length(line) >= 2) then
if (line[2] = ' ') and ((line[1] = '-') or (line[1] = '+')) then
begin
arrayLength := length(question.answers);
SetLength(question.answers, arrayLength + 1);
question.answers[arrayLength] :=
Copy(line, 2, Length(line) - 1);
if zeile[1] = '+' then
question.correct := arrayLength;
end
else
begin
question := TQuestion.Create;
question.title := line;
arrayLength := length(questions);
setLength(questions, arrayLength + 1);
questions[arrayLength] := question;
end;
end;
BStart.Visible := False;
end;
Well, my Pascal knowledge goes to 10 to 15 years ago. However, I can see that you have an extra semicolon at the end of this line:
for i := 0 to stringList.Count - 1 do ;

Freepascal finding eof after reset of a non-empty file

Got me stumped: on Windows, Free Pascal
{... writes text lines to PdfTmp, then ...}
close(PdfTmp);
reset(PdfTmp);
while not eof(PdfTmp) do begin
readln(PdfTmp,InpLine);
writeln(ProdFile,InpLine);
end;
close(PdfTmp);
I've verified that the PdfTmp file is written with the text, but the eof() function returns true on the first call, thus the while block is never executed.
I tried all kinds of tricks with surrounding code to determine whatever else might be causing the failure, including updating my FPC compiler, to no avail. Tests confirm it is the improper eof() function result.
The same code works properly on a Mac. (FreePascal supports various platforms.)
Any other poor soul out there had this evil befall and stall out a nice project? If so, how was it fixed, if it was?
Here's how I solved the problem:
{}
{$ifdef WIN}
procedure starttext (var F :file; var Feof :boolean);
begin
reset(F,1); Feof := filesize(F) = 0;
end;
procedure gettext (var F :file; Feoln :array of byte; var Feof :boolean; var S :string);
{ gets the next text line from F into S. Returns false at end of file.
It returns the last string and sets eof if there are no additional strings.}
var endline, endfile :boolean; P, R :longint; C, D :byte;
begin
S := '';
endline := false;
endfile := false;
repeat
P := filepos(F);
blockread(F,C,1,R);
if R = 0 then begin
endline := true;
endfile := true; end
else begin
P := P + 1;
if C = Feoln[0] then begin
if high(Feoln) > 0 then begin
blockread(F,D,1,R);
if (R <> 0) then begin
if D = Feoln[1] then begin
endline := true;
P := P + 1; end
else
seek(F, P);
end else
P := P + 1;
end else
endline := true;
end else
S := S + chr(C);
endfile := P = (filesize(F));
end;
until
(endline = true) or (endfile = true);
Feof := endfile;
end;
{$endif}
{}
...
{}
close(PdfTmp);
{$ifdef OSX}
reset(PdfTmp);
while not eof(PdfTmp) do begin
readln(PdfTmp,InpLine);
putpdfln(InpLine);
end;
close(PdfTmp);
{$endif}
{$ifdef WIN}
assign(PdfWrk,FileID+'.$$$'); {same file as PdfTmp}
starttext(PdfWrk,eofPdfWrk);
while not eofPdfWrk do begin
gettext(PdfWrk, [13,10], eofPdfWrk, InpLine);
putpdfln(InpLine);
end;
close(PdfWrk);
{$endif}
{}
...
I abandoned the idea that Windows was a viable product when I realized Microsoft had failed to follow IBM's instructions for how to handle interrupts which they published with the first IBM-PC. This failure still plagues the monstrous ill-conceived class structure of Windows; and leads to that enigmatic occasional glitch we've all experienced in Windows applications.
Personally, I don't believe an operating system should be built with classes, which impose an unnecessary overhead for process code that will be needed only once in the system (which if properly done will be true for all the code in the OS). A good API would suffice.

FPC uses AVL_TREE

I'm using Ubuntu 11.04 and Free Pascal Compiler version 2.4.0-2ubuntu3.1 [2011/06/17] for x86_64 Copyright (c) 1993-2009 by Florian Klaempfl
when I'm trying to compile this code:
program test;
uses AVL_Tree;
const N = 10;
type Number = ^Integer;
var all : TAVLTree;
actual :TAVLTreeNode;
a,i :Integer;
t : array[1..N] of Integer;
x :Number;
function compare(a,b:Pointer):LongInt;
begin
compare := Number(a)^ - Number(b)^;
end;
begin
randomize;
for i := 1 to N do
t[i] := i;
all := TAVLTree.Create(#compare);
for i := N downto 1 do
begin
a:=1+random(i);
new(x);
x^:=t[a];
all.add(x);
t[a]:=t[i];
end;
actual := all.findLowest;
while actual <> nil do
begin
Writeln(Number(actual.data)^);
dispose(Number(actual.data));
actual := all.FindSuccessor(actual);
end;
all.Free;
end.
it gives me:
Compiling avl.pas
Fatal: Can't find unit AVL_Tree used by test
Fatal: Compilation aborted
Error: /usr/bin/ppcx64 returned an error exitcode (normal if you did not specify a source file to be compiled)
I don't know what is going on.. in my school this code worked fine.. Any ideas what should I do?

How to get MAC address in windows7? [duplicate]

This question already has answers here:
Closed 12 years ago.
Possible Duplicates:
Getting Machine’s MAC Address — Good Solution?
How do I get the MAC address of a network card using Delphi?
I am using MAC address as hardware id for protection(ofcourse I have encrypted this data)
I am using below code to get MAC address on user computer
function MacAddress: string;
var
Lib: Cardinal;
Func: function(GUID: PGUID): Longint; stdcall;
GUID1, GUID2: TGUID;
begin
Result := '';
Lib := LoadLibrary('rpcrt4.dll');
if Lib <> 0 then
begin
#Func := GetProcAddress(Lib, 'UuidCreateSequential');
if Assigned(Func) then
begin
if (Func(#GUID1) = 0) and
(Func(#GUID2) = 0) and
(GUID1.D4[2] = GUID2.D4[2]) and
(GUID1.D4[3] = GUID2.D4[3]) and
(GUID1.D4[4] = GUID2.D4[4]) and
(GUID1.D4[5] = GUID2.D4[5]) and
(GUID1.D4[6] = GUID2.D4[6]) and
(GUID1.D4[7] = GUID2.D4[7]) then
begin
Result :=
IntToHex(GUID1.D4[2], 2) + '-' +
IntToHex(GUID1.D4[3], 2) + '-' +
IntToHex(GUID1.D4[4], 2) + '-' +
IntToHex(GUID1.D4[5], 2) + '-' +
IntToHex(GUID1.D4[6], 2) + '-' +
IntToHex(GUID1.D4[7], 2);
end;
end;
end;
end;
above code works perfectly on windows XP
but its giving different values in windows7 ,the value changing every time after computer resratred :(
is there any chance of getting MAC address thats constant (unless user changed his MAC address)
or is there any good code which retrvies constant data on all OS ?
thanks in advance
#steve0, to retrieve the mac address of an Network Adapter you can use the WMI and the Win32_NetworkAdapterConfiguration Class and check the MACAddress property.
Check this code:
program WMI_MAC;
{$APPTYPE CONSOLE}
uses
SysUtils
,ActiveX
,ComObj
,Variants;
function VarToStrNil(Value:Variant):string; //Dummy function to onvert an variant value to string
begin
if VarIsNull(Value) then
Result:=''
else
Result:=VarToStr(Value);
end;
Procedure GetMacAddress;
var
objWMIService : OLEVariant;
colItems : OLEVariant;
colItem : OLEVariant;
oEnum : IEnumvariant;
iValue : LongWord;
wmiHost, root, wmiClass: string;
function GetWMIObject(const objectName: String): IDispatch;
var
chEaten: Integer;
BindCtx: IBindCtx;//for access to a bind context
Moniker: IMoniker;//Enables you to use a moniker object
begin
OleCheck(CreateBindCtx(0, bindCtx));
OleCheck(MkParseDisplayName(BindCtx, StringToOleStr(objectName), chEaten, Moniker));//Converts a string into a moniker that identifies the object named by the string
OleCheck(Moniker.BindToObject(BindCtx, nil, IDispatch, Result));//Binds to the specified object
end;
begin
wmiHost := '.';
root := 'root\CIMV2';
wmiClass := 'Win32_NetworkAdapterConfiguration';
objWMIService := GetWMIObject(Format('winmgmts:\\%s\%s',[wmiHost,root]));
colItems := objWMIService.ExecQuery(Format('SELECT * FROM %s',[wmiClass]),'WQL',0);
oEnum := IUnknown(colItems._NewEnum) as IEnumVariant;
while oEnum.Next(1, colItem, iValue) = 0 do
//if VarToStrNil(colItem.MACAddress)<>'' then //uncomment if you only want list the interfaces with mac adress
//if colItem.IPEnabled then // uncomment if you only want list the active interfaces
begin
WriteLn('Card Description '+VarToStrNil(colItem.Caption));
WriteLn('MACAddress '+VarToStrNil(colItem.MACAddress));
end;
end;
begin
try
CoInitialize(nil);
try
GetMacAddress;
Readln;
finally
CoUninitialize;
end;
except
on E:Exception do
Begin
Writeln(E.Classname, ': ', E.Message);
Readln;
End;
end;
end.
Here is some code working well for any computer on your network - may try it to get your own, using '127.0.0.1' as IP:
function GetRemoteMacAddress(const IP: AnsiString): TSockData;
// implements http://msdn.microsoft.com/en-us/library/aa366358(VS.85).aspx
type
TSendARP = function(DestIp: DWORD; srcIP: DWORD; pMacAddr: pointer; PhyAddrLen: Pointer): DWORD; stdcall;
const
HexChars: array[0..15] of AnsiChar = '0123456789ABCDEF';
var dwRemoteIP: DWORD;
PhyAddrLen: Longword;
pMacAddr : array [0..7] of byte;
I: integer;
P: PAnsiChar;
SendARPLibHandle: THandle;
SendARP: TSendARP;
begin
result := '';
SendARPLibHandle := LoadLibrary('iphlpapi.dll');
if SendARPLibHandle<>0 then
try
SendARP := GetProcAddress(SendARPLibHandle,'SendARP');
if #SendARP=nil then
exit; // we are not under 2K or later
dwremoteIP := inet_addr(pointer(IP));
if dwremoteIP<>0 then begin
PhyAddrLen := 8;
if SendARP(dwremoteIP, 0, #pMacAddr, #PhyAddrLen)=NO_ERROR then begin
if PhyAddrLen=6 then begin
SetLength(result,12);
P := pointer(result);
for i := 0 to 5 do begin
P[0] := HexChars[pMacAddr[i] shr 4];
P[1] := HexChars[pMacAddr[i] and $F];
inc(P,2);
end;
end;
end;
end;
finally
FreeLibrary(SendARPLibHandle);
end;
end;
This code is extracted from our freeware and open source framework, unit SynCrtSock.pas. See http://synopse.info/fossil

Inno Setup: How to automatically uninstall previous installed version?

I'm using Inno Setup to create an installer.
I want the installer to automatically uninstall the previous installed version, instead of overwriting it. How can I do that?
I have used the following. I'm not sure it's the simplest way to do it but it works.
This uses {#emit SetupSetting("AppId")} which relies on the Inno Setup Preprocessor. If you don't use that, cut-and-paste your App ID in directly.
[Code]
{ ///////////////////////////////////////////////////////////////////// }
function GetUninstallString(): String;
var
sUnInstPath: String;
sUnInstallString: String;
begin
sUnInstPath := ExpandConstant('Software\Microsoft\Windows\CurrentVersion\Uninstall\{#emit SetupSetting("AppId")}_is1');
sUnInstallString := '';
if not RegQueryStringValue(HKLM, sUnInstPath, 'UninstallString', sUnInstallString) then
RegQueryStringValue(HKCU, sUnInstPath, 'UninstallString', sUnInstallString);
Result := sUnInstallString;
end;
{ ///////////////////////////////////////////////////////////////////// }
function IsUpgrade(): Boolean;
begin
Result := (GetUninstallString() <> '');
end;
{ ///////////////////////////////////////////////////////////////////// }
function UnInstallOldVersion(): Integer;
var
sUnInstallString: String;
iResultCode: Integer;
begin
{ Return Values: }
{ 1 - uninstall string is empty }
{ 2 - error executing the UnInstallString }
{ 3 - successfully executed the UnInstallString }
{ default return value }
Result := 0;
{ get the uninstall string of the old app }
sUnInstallString := GetUninstallString();
if sUnInstallString <> '' then begin
sUnInstallString := RemoveQuotes(sUnInstallString);
if Exec(sUnInstallString, '/SILENT /NORESTART /SUPPRESSMSGBOXES','', SW_HIDE, ewWaitUntilTerminated, iResultCode) then
Result := 3
else
Result := 2;
end else
Result := 1;
end;
{ ///////////////////////////////////////////////////////////////////// }
procedure CurStepChanged(CurStep: TSetupStep);
begin
if (CurStep=ssInstall) then
begin
if (IsUpgrade()) then
begin
UnInstallOldVersion();
end;
end;
end;
Alternatives
See also this blog post "Inno Setup Script Sample for Version Comparison" which goes one step further, and reads the version number of any previously installed version, and compares that version number with that of the current installation package.
You should be able to read the uninstall string from the registry, given the AppId (i.e. the value you used for AppID in the [Setup]-section). It could be found under Software\Microsoft\Windows\CurrentVersion\Uninstall\{AppId}\ (could be either HKLM or HKCU, so best check both) where {AppId} should be substituted with the actual value you used. Look for the UninstallString or QuietUninstallString values and use the Exec function to run it from your InitializeSetup() event function.
If you "just want to remove the old icons" (because yours have changed/updated) you can use this:
; attempt to remove previous versions' icons
[InstallDelete]
Type: filesandordirs; Name: {group}\*;
This is run "at the beginning of installation" so basically removes the old icons, and your new ones will still be installed there after this is completely done.
I just do this with every install "in case anything has changed" icon wise (it all gets reinstalled anyway).
When using Inno Setup, there's no reason to uninstall a previous version unless that version was installed by a different installer program. Otherwise upgrades are handled automatically.
Here is a simplified version based on answer from Craig McQueen:
const
UninstallRegisterPath = 'Software\Microsoft\Windows\CurrentVersion\Uninstall\' + '{#emit SetupSetting("AppName")}' + '_is1';
function GetUninstallerPath(): String;
begin
result := '';
if (not RegQueryStringValue(HKLM, UninstallRegisterPath, 'UninstallString', result)) then
RegQueryStringValue(HKCU, UninstallRegisterPath, 'UninstallString', result);
end;
procedure UninstallOldVersion();
var
UninstallerPath: String;
ResultCode: Integer;
begin
UninstallerPath := GetUninstallerPath();
if (UninstallerPath <> '') then begin
Exec(UninstallerPath, '/VERYSILENT /NORESTART /SUPPRESSMSGBOXES', '', SW_HIDE, ewWaitUntilTerminated, ResultCode);
end;
end;
procedure CurStepChanged(CurStep: TSetupStep);
begin
if (CurStep = ssInstall) then
begin
UninstallOldVersion();
end;
end;
Note: in my case, I use AppName instead of AppId.
The answer provided by Craig McQueen is totally viable. Although, I would add those comments:
The {#emit SetupSetting("AppId")} code does not work for me, so I just add my App ID.
I didn't want to execute my uninstallation program, because I have a INI config file stored in the AppData/ folder which is removed by the uninstaller, and I don't want it to be erased when installing a new version. So, I modified a bit the code provided by Craig McQueen to remove the directory where is installed the program, after retrieving its path.
So, regarding the code of Craig McQueen, changes are:
Retrieve the InstallLocation key instead of the UninstallString key.
Use the DelTree function instead of the Exec(sUnInstallString, ...)
For anyone that uses the GetUninstallString() suggested above to force an uninstall inside CurStepChanged() and has disk caching issues, see below for a related solution that actually waits a while after unistallation for the uninstaller exe to be deleted!
Disk caching issue with inno-setup?
For those interested, I wrote a DLL for Inno Setup 6 and later that provides a simple mechanism for supporting automatic uninstall.
The DLL provides a way to detect if the package you are installing is already installed (via AppId) and to decide, based on the installed version, if you want to automatically uninstall it (for example, you might want to automatically uninstall if user is downgrading).
https://github.com/Bill-Stewart/UninsIS
You can exec an uninstaller in the [code] section. You have to figure out how to get the path to the existing uninstaller. For simplicity when I install my apps I add a registry string value that points to the folder containing the uninstaller, and just exec the uninstaller in the InitializeWizard callback.
Keep in mind that Inno setup uninstaller names are all of the form uninsnnn.exe, you need to take that into account in your code.
i got edited #Crain Mc-Queen code , i think this code is better because not need to modified in different project :
[Code]
function GetNumber(var temp: String): Integer;
var
part: String;
pos1: Integer;
begin
if Length(temp) = 0 then
begin
Result := -1;
Exit;
end;
pos1 := Pos('.', temp);
if (pos1 = 0) then
begin
Result := StrToInt(temp);
temp := '';
end
else
begin
part := Copy(temp, 1, pos1 - 1);
temp := Copy(temp, pos1 + 1, Length(temp));
Result := StrToInt(part);
end;
end;
function CompareInner(var temp1, temp2: String): Integer;
var
num1, num2: Integer;
begin
num1 := GetNumber(temp1);
num2 := GetNumber(temp2);
if (num1 = -1) or (num2 = -1) then
begin
Result := 0;
Exit;
end;
if (num1 > num2) then
begin
Result := 1;
end
else if (num1 < num2) then
begin
Result := -1;
end
else
begin
Result := CompareInner(temp1, temp2);
end;
end;
function CompareVersion(str1, str2: String): Integer;
var
temp1, temp2: String;
begin
temp1 := str1;
temp2 := str2;
Result := CompareInner(temp1, temp2);
end;
function InitializeSetup(): Boolean;
var
oldVersion: String;
uninstaller: String;
ErrorCode: Integer;
vCurID :String;
vCurAppName :String;
begin
vCurID:= '{#SetupSetting("AppId")}';
vCurAppName:= '{#SetupSetting("AppName")}';
//remove first "{" of ID
vCurID:= Copy(vCurID, 2, Length(vCurID) - 1);
//
if RegKeyExists(HKEY_LOCAL_MACHINE,
'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\' + vCurID + '_is1') then
begin
RegQueryStringValue(HKEY_LOCAL_MACHINE,
'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\' + vCurID + '_is1',
'DisplayVersion', oldVersion);
if (CompareVersion(oldVersion, '{#SetupSetting("AppVersion")}') < 0) then
begin
if MsgBox('Version ' + oldVersion + ' of ' + vCurAppName + ' is already installed. Continue to use this old version?',
mbConfirmation, MB_YESNO) = IDYES then
begin
Result := False;
end
else
begin
RegQueryStringValue(HKEY_LOCAL_MACHINE,
'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\' + vCurID + '_is1',
'UninstallString', uninstaller);
ShellExec('runas', uninstaller, '/SILENT', '', SW_HIDE, ewWaitUntilTerminated, ErrorCode);
Result := True;
end;
end
else
begin
MsgBox('Version ' + oldVersion + ' of ' + vCurAppName + ' is already installed. This installer will exit.',
mbInformation, MB_OK);
Result := False;
end;
end
else
begin
Result := True;
end;
end;
I must be missing something.
The new files are copied to the target directory before the removal of the old installation occurs.
Then comes the uninstaller deletes them and remove the directory.
Do not use the [Run] section, but the [UninstallRun].
Infact, the program under [Run] are executed after the installation, causing to uninstall your program immediately after the installation :-|
Instead, the [UninstallRun] section is evaluated before the installation.
Follow this link: http://news.jrsoftware.org/news/innosetup/msg55323.html
In InitializeSetup() function, you can call "MSIEXEC /x {your program ID}" after user prompt to uninstall old old version

Resources