new Windows installer for FC

This commit is contained in:
donovaly
2019-04-02 01:20:04 +02:00
committed by wmayer
parent ff1fb11af1
commit 5ccae96920
58 changed files with 5034 additions and 784 deletions

View File

@@ -0,0 +1,75 @@
/*
declaration.nsh
Configuration and variables of FreeCAD installer
*/
#--------------------------------
# File locations
!define FILES_LICENSE "license.rtf"
#--------------------------------
# Names and version
!define APP_NAME "FreeCAD"
!define APP_VERSION_NUMBER "${APP_VERSION_MAJOR}.${APP_VERSION_MINOR}.${APP_VERSION_REVISION}.${APP_VERSION_BUILD}"
# for the proposed install folder we use the scheme "FreeCAD 0.18" while we need for the registry the scheme "FreeCAD 0.18.1"
# to check if it is exactly this version (to support side by side installations)
!define APP_SERIES_NAME "${APP_VERSION_MAJOR}.${APP_VERSION_MINOR}"
!define APP_SERIES_KEY "${APP_VERSION_MAJOR}${APP_VERSION_MINOR}${APP_VERSION_REVISION}${APP_VERSION_EMERGENCY}"
!define APP_SERIES_KEY2 "${APP_VERSION_MAJOR}.${APP_VERSION_MINOR}.${APP_VERSION_REVISION}${APP_EMERGENCY_DOT}${APP_VERSION_EMERGENCY}"
!define APP_DIR_REGKEY "Software\Microsoft\Windows\CurrentVersion\App Paths\${APP_NAME}.exe"
!define APP_DIR "${APP_NAME} ${APP_SERIES_NAME}"
# Fixme: FC should use different prefernces folder for every release
!define APP_DIR_USERDATA ${APP_NAME}
#!define APP_DIR_USERDATA "${APP_NAME}${APP_VERSION_MAJOR}.${APP_VERSION_MINOR}"
!define APP_INFO "${APP_NAME} - Your Own 3D Parametric Modeler"
!define APP_WEBPAGE "https://freecadweb.org/"
!define APP_WEBPAGE_INFO "${APP_NAME} Website"
!define APP_WIKI "https://www.freecadweb.org/wiki/Main_Page"
!define APP_WIKI_INFO "${APP_NAME} Wiki"
!define APP_COPYRIGHT "${APP_NAME} is Copyright © 2001-${COPYRIGHT_YEAR} by the ${APP_NAME} Team"
!define APP_RUN "bin\FreeCAD.exe"
!define BIN_FREECAD "FreeCAD.exe"
!define APP_REGKEY "Software\${APP_NAME}${APP_SERIES_KEY}" # like "FreeCAD0180"
!define APP_REGKEY_SETUP "${APP_REGKEY}\Setup"
!define APP_REGKEY_SETTINGS "${APP_REGKEY}\Settings"
!define APP_REGNAME_DOC "${APP_NAME}.Document"
!define APP_EXT ".FCStd"
!define APP_MIME_TYPE "application/x-zip-compressed"
!define APP_UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${SETUP_UNINSTALLER_KEY}"
#--------------------------------
# Setup settings
!define SETUP_EXE ${ExeFile}
!define SETUP_ICON "icons\FreeCAD.ico"
!define SETUP_HEADERIMAGE "graphics\header.bmp"
!define SETUP_WIZARDIMAGE "graphics\orange.bmp"
!define SETUP_UNINSTALLER "Uninstall-${APP_NAME}.exe"
!define SETUP_UNINSTALLER_KEY "${APP_NAME}${APP_SERIES_KEY}"
#--------------------------------
# Variables that are shared between multiple files
Var APPDATemp
Var AppPre
var AppSubfolder
Var AppSuff
Var CreateDesktopIcon
Var CreateFileAssociations
Var OldVersionNumber
Var Pointer
Var Search
Var SVGPath
Var StartmenuFolder
Var String
Var UserList
Var LangName

View File

@@ -0,0 +1,46 @@
/*
detection.nsh
Detection of external component locations
*/
# This script contains the following functions:
#
# - SearchExternal, calls the functions:
# MissingPrograms
#
# - MissingPrograms, (check if third-party programs are installed), uses:
# SEARCH_MIKTEX
# SEARCH_TEXLIVE
#
#--------------------------
Function SearchExternal
Call MissingPrograms
FunctionEnd
# ---------------------------------------
Function MissingPrograms
# check if third-party programs are installed
${if} ${RunningX64}
SetRegView 64
${endif}
# test if Inkscape is installed
ReadRegStr $SVGPath HKLM "SOFTWARE\Classes\inkscape.svg\DefaultIcon" ""
${if} $SVGPath != ""
StrCpy $SVGPath $SVGPath "" 1 # remove the leading quote
StrCpy $SVGPath $SVGPath -14 # # delete '\inkscape.exe"'
${endif}
${if} $SVGPath == ""
# this was used before Inkscape 0.91:
ReadRegStr $SVGPath HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Inkscape" "InstallLocation"
${endif}
FunctionEnd
# ---------------------------------------

View File

@@ -0,0 +1,94 @@
/*
gui.nsh
Installer user interface settings
*/
#--------------------------------
# General
Name "${APP_NAME} ${APP_VERSION}"
BrandingText " "
#--------------------------------
# Interface settings
!define MUI_ABORTWARNING
!define MUI_ICON "${SETUP_ICON}"
!define MUI_UNICON "${SETUP_ICON}"
!define MUI_HEADERIMAGE
!define MUI_HEADERIMAGE_BITMAP "${SETUP_HEADERIMAGE}"
!define MUI_HEADERIMAGE_RIGHT
!define MUI_WELCOMEFINISHPAGE_BITMAP "${SETUP_WIZARDIMAGE}"
!define MUI_UNWELCOMEFINISHPAGE_BITMAP "${SETUP_WIZARDIMAGE}"
#--------------------------------
# Pages
# Installer
# Welcome page
!define MUI_WELCOMEPAGE_TEXT $(TEXT_WELCOME)
!insertmacro MUI_PAGE_WELCOME
# Show the license.
!insertmacro MUI_PAGE_LICENSE "${FILES_LICENSE}"
# Decision if it should be installed as admin or not
!insertmacro MULTIUSER_PAGE_INSTALLMODE
# Specify the installation directory.
!insertmacro MUI_PAGE_DIRECTORY
# Define which components to install.
!insertmacro MUI_PAGE_COMPONENTS
# Specify where to install program shortcuts.
!define MUI_STARTMENUPAGE_REGISTRY_VALUENAME "Start Menu Folder"
!define MUI_STARTMENUPAGE_DEFAULTFOLDER "${APP_DIR}"
!insertmacro MUI_PAGE_STARTMENU ${APP_NAME} $StartmenuFolder
# Watch the components being installed.
!insertmacro MUI_PAGE_INSTFILES
# The option to run FreeCAD from the finish page is currently disabled because
# it may run with Administrator priviledges, therefore causing a different
# user directory to be used. This could be fixed by creating a separate
# process without UAC elevation.
#!define MUI_FINISHPAGE_RUN_TEXT "$(FinishPageRun)"
#!define MUI_FINISHPAGE_RUN "$INSTDIR\${APP_RUN}"
!define MUI_FINISHPAGE_SHOWREADME
!define MUI_FINISHPAGE_SHOWREADME_NOTCHECKED
!define MUI_FINISHPAGE_SHOWREADME_FUNCTION StartFreeCAD
!define MUI_FINISHPAGE_SHOWREADME_TEXT $(FinishPageRun)
!define MUI_FINISHPAGE_LINK $(TEXT_FINISH_WEBSITE)
!define MUI_FINISHPAGE_LINK_LOCATION "https://freecadweb.org/"
#!define MUI_PAGE_CUSTOMFUNCTION_SHOW CheckDesktopShortcut
!insertmacro MUI_PAGE_FINISH
# Uninstaller
!insertmacro MUI_UNPAGE_WELCOME
!insertmacro MUI_UNPAGE_CONFIRM
!insertmacro MUI_UNPAGE_COMPONENTS
!insertmacro MUI_UNPAGE_INSTFILES
!insertmacro MUI_UNPAGE_FINISH
#--------------------------------
# Installer Languages
!include lang\TranslatedLanguages.nsh
#--------------------------------
# Version information
VIProductVersion "${APP_VERSION_NUMBER}"
VIAddVersionKey /LANG=${LANG_ENGLISH} "ProductName" "${APP_NAME}"
VIAddVersionKey /LANG=${LANG_ENGLISH} "ProductVersion" "${APP_DIR}.${APP_VERSION_REVISION}"
VIAddVersionKey /LANG=${LANG_ENGLISH} "FileDescription" "${APP_INFO}"
VIAddVersionKey /LANG=${LANG_ENGLISH} "FileVersion" "${APP_VERSION}"
VIAddVersionKey /LANG=${LANG_ENGLISH} "LegalCopyright" "${APP_COPYRIGHT}"
VIAddVersionKey /LANG=${LANG_ENGLISH} "CompanyName" "${APP_NAME} Team"
VIAddVersionKey /LANG=${LANG_ENGLISH} "LegalTrademarks" ""

View File

@@ -0,0 +1,208 @@
/*
init.nsh
Initialization functions
*/
#--------------------------------
# User initialization
Var FCLangName
Function InitUser
# Get FreeCAD language
ReadRegStr $FCLangName SHELL_CONTEXT "${APP_REGKEY_SETUP}" "FreeCAD Language"
${If} $FCLangName != ""
StrCpy $LangName $FCLangName
${EndIf}
FunctionEnd
#--------------------------------
# visible installer sections
Section "!${APP_NAME}" SecCore
SectionIn RO
SectionEnd
Section "$(SecFileAssocTitle)" SecFileAssoc
StrCpy $CreateFileAssociations "true"
SectionEnd
Section "$(SecDesktopTitle)" SecDesktop
StrCpy $CreateDesktopIcon "true"
SectionEnd
# Section descriptions
!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN
!insertmacro MUI_DESCRIPTION_TEXT ${SecCore} "$(SecCoreDescription)"
!insertmacro MUI_DESCRIPTION_TEXT ${SecFileAssoc} "$(SecFileAssocDescription)"
!insertmacro MUI_DESCRIPTION_TEXT ${SecDesktop} "$(SecDesktopDescription)"
!insertmacro MUI_FUNCTION_DESCRIPTION_END
# .onInit must be here after the section definition because we have to set
# the selection states of the dictionary sections
Function .onInit
ReadRegStr $R0 HKLM "SOFTWARE\Microsoft\Windows NT\CurrentVersion" CurrentVersion
${if} $R0 == "5.0" # 2000
${orif} $R0 == "5.1" # XP
${orif} $R0 == "5.2" # 2003
${orif} $R0 == "6.0" # Vista
MessageBox MB_OK|MB_ICONSTOP "${APP_NAME} ${APP_VERSION} requires Windows 7 or newer." /SD IDOK
Quit
${endif}
# check if it is a 64bit system
${if} ${RunningX64}
SetRegView 64
${endif}
# Check that FreeCAD is not currently running
${nsProcess::FindProcess} ${BIN_FREECAD} $R0
# if running result is '0', if not running it is '603'
${if} $R0 == "0"
MessageBox MB_OK|MB_ICONSTOP "$(UnInstallRunning)" /SD IDOK
Abort
${endif}
# plugin must be unloaded
${nsProcess::Unload}
# initialize the multi-uder installer UI
!insertmacro MULTIUSER_INIT
# check if this FreeCAD version is already installed
${if} $MultiUser.Privileges == "Admin"
${orif} $MultiUser.Privileges == "Power"
ReadRegStr $0 HKLM "${APP_UNINST_KEY}" "DisplayIcon"
${else}
ReadRegStr $0 HKCU "${APP_UNINST_KEY}" "DisplayIcon"
# handle also the case that FreeCAD is already installed in HKLM
${if} $0 == ""
ReadRegStr $0 HKLM "${APP_UNINST_KEY}" "DisplayIcon"
${endif}
${endif}
${if} $0 != ""
# check if the uninstaller was acidentally deleted
# if so don't bother the user if he really wants to install a new FreeCAD over an existing one
# because he won't have a chance to deny this
StrCpy $4 $0 -16 # remove '\bin\FreeCAD.exe'
# (for FileCheck the variables $0 and $1 cannot be used)
!insertmacro FileCheck $5 "Uninstall-${APP_NAME}.exe" "$4" # macro from Utils.nsh
${if} $5 == "False"
Goto ForceInstallation
${endif}
# installing over an existing installation of the same FreeCAD release is not necessary
# if the users does this he most probably has a problem with FreeCAD that can better be solved
# by reinstalling FreeCAD
# for beta and other test releases over-installing can even cause errors
MessageBox MB_YESNO|MB_DEFBUTTON2|MB_ICONEXCLAMATION "$(AlreadyInstalled)" /SD IDNO IDYES ForceInstallation
Abort
ForceInstallation:
${endif}
# check if there is an existing FreeCAD installation of the same FreeCAD series
# we usually don't release more than 10 versions so with 20 we are safe to check if a newer version is installed
IntOp $4 ${APP_VERSION_REVISION} + 20
${for} $5 0 $4
${if} $MultiUser.Privileges == "Admin"
${orif} $MultiUser.Privileges == "Power"
ReadRegStr $0 HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APP_NAME}${APP_VERSION_MAJOR}${APP_VERSION_MINOR}$5" "DisplayVersion"
# also check for an emergency release
${if} $0 == ""
ReadRegStr $0 HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APP_NAME}${APP_VERSION_MAJOR}${APP_VERSION_MINOR}$51" "DisplayVersion"
${endif}
${else}
ReadRegStr $0 HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APP_NAME}${APP_VERSION_MAJOR}${APP_VERSION_MINOR}$5" "DisplayVersion"
# also check for an emergency release
${if} $0 == ""
ReadRegStr $0 HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APP_NAME}${APP_VERSION_MAJOR}${APP_VERSION_MINOR}$51" "DisplayVersion"
${endif}
${endif}
${if} $0 != ""
StrCpy $R5 $0 # store the read version number
StrCpy $OldVersionNumber "${APP_VERSION_MAJOR}${APP_VERSION_MINOR}$5"
# we don't stop here because we want the latest installed version
${endif}
${next}
${if} $OldVersionNumber > ${APP_SERIES_KEY}
# store the version number and reformat it temporarily for the error message
StrCpy $R0 $OldVersionNumber
StrCpy $OldVersionNumber $R5
MessageBox MB_OK|MB_ICONSTOP "$(NewerInstalled)" /SD IDOK
StrCpy $OldVersionNumber $R0
Abort
${endif}
# this can be reset to "true" in section SecDesktop
StrCpy $CreateDesktopIcon "false"
StrCpy $CreateFileAssociations "false"
${IfNot} ${Silent}
# Show banner while installer is intializating
Banner::show /NOUNLOAD "Checking system"
${EndIf}
Call SearchExternal
${IfNot} ${Silent}
Banner::destroy
${EndIf}
FunctionEnd
# this function is called at first after starting the uninstaller
Function un.onInit
!insertmacro MULTIUSER_UNINIT
# Check that FreeCAD is not currently running
FindProcDLL::FindProc "${BIN_FREECAD}"
${if} $R0 == "1"
MessageBox MB_OK|MB_ICONSTOP "$(UnInstallRunning)" /SD IDOK
Abort
${endif}
# check if it is a 64bit system
${if} ${RunningX64}
SetRegView 64
${endif}
# set registry root key
${if} $MultiUser.Privileges == "Admin"
${orif} $MultiUser.Privileges == "Power"
SetShellVarContext all
${else}
SetShellVarContext current
${endif}
# Ascertain whether the user has sufficient privileges to uninstall.
# abort when FreeCAD was installed with admin permissions but the user doesn't have administrator privileges
ReadRegStr $0 HKLM "${APP_UNINST_KEY}" "DisplayVersion"
${if} $0 != ""
${andif} $MultiUser.Privileges != "Admin"
${andif} $MultiUser.Privileges != "Power"
MessageBox MB_OK|MB_ICONSTOP "$(UnNotAdminLabel)" /SD IDOK
Abort
${endif}
# warning when FreeCAD couldn't be found in the registry
${if} $0 == "" # check in HKCU
ReadRegStr $0 HKCU "${APP_UNINST_KEY}" "DisplayVersion"
${if} $0 == ""
MessageBox MB_OK|MB_ICONEXCLAMATION "$(UnNotInRegistryLabel)" /SD IDOK
${endif}
${endif}
# Macro to investigate name of FreeCAD's preferences folders to be able remove them
!insertmacro UnAppPreSuff $AppPre $AppSuff # macro from Utils.nsh
# question message if the user really wants to uninstall FreeCAD
MessageBox MB_ICONQUESTION|MB_YESNO|MB_DEFBUTTON2 "$(UnReallyRemoveLabel)" /SD IDYES IDYES +2 # continue if yes
Abort
FunctionEnd

View File

@@ -0,0 +1,268 @@
# This script contains the following functions:
#
# - un.DelAppPathSub and UnAppPreSuff,
# (delete the folder ~\Documents and Settings\username\Application Data\FreeCAD for all users), uses:
# un.GetParentA
# un.GetUsers
# un.StrPoint
# StrPointer
# StrPoint
# UnAppPreSuff
#
# - FileCheck (checks if a given file exists)
#
#--------------------------
!macro StrPointer FindStr SearchStr Pointer
# searches for a string/character (SearchStr) in another string (FindStr)
# and returns the number of the character in the FindStr where the SearchStr was found (Pointer)
# if nothing was found or the search is impossible the Pointer is set to -1
StrLen $R2 ${SearchStr}
StrLen $R4 ${FindStr}
StrCpy $R5 0
${if} $R2 == 0
${orif} $R4 == 0
Goto NotFound
${endif}
IntCmp $R4 $R2 loopA NotFound
loopA:
StrCpy $R3 ${FindStr} $R2 $R5
StrCmp $R3 ${SearchStr} Found
IntOp $R5 $R5 + 1
IntCmp $R4 $R5 loopA NotFound
Goto loopA
Found:
StrCpy ${Pointer} $R5
Goto done
NotFound:
StrCpy ${Pointer} "-1"
done:
!macroend
#--------------------------------
Function StrPoint
!insertmacro StrPointer $String $Search $Pointer
FunctionEnd
#--------------------------------
!macro RevStrPointer FindStr SearchStr Pointer
# searches for a string/character (SearchStr) in another string (FindStr) in reverse order
# and returns the number of the character in the FindStr where the SearchStr was found (Pointer)
# if nothing was found or the search is impossible the Pointer is set to +1
StrLen $R2 ${SearchStr}
StrLen $R4 ${FindStr}
${if} $R2 == 0
${orif} $R4 == 0
Goto NotFound
${endif}
IntCmp $R4 $R2 loopA NotFound
StrCpy $R5 "-$R2"
loopA:
StrCpy $R3 ${FindStr} $R2 $R5
StrCmp $R3 ${SearchStr} Found
IntOp $R5 $R5 - 1
IntCmp "$R5" "-$R4" loopA NotFound
Goto loopA
Found:
StrCpy ${Pointer} $R5
Goto done
NotFound:
StrCpy ${Pointer} "+1"
done:
!macroend
#--------------------------------
!macro AppPreSuff AppPre AppSuff
# the APPDATA path for a local user has for WinXP and 2000 the following structure:
# C:\Documents and Settings\username\Application Data
# for Win Vista the structure is:
# C:\Users\username\AppData\Roaming
# this macro saves the "C:\Documents and Settings\" substring into the variable "AppPre"
# and the "Application Data" substring into the variable "AppSuff"
# switch temporarily to local user because the all users application data path is in
# Vista only C:\ProgramData
SetShellVarContext current
StrCpy $String "$APPDATA"
Var /GLOBAL APPDATemp
StrCpy $APPDATemp "$APPDATA"
${If} $MultiUser.Privileges == "Admin"
${OrIf} $MultiUser.Privileges == "Power"
SetShellVarContext all # move back to all users
${endif}
StrCpy $Search "\"
Call StrPoint # search for the first "\"
IntOp $Pointer $Pointer + 1 # jump after the "\"
StrCpy $String $String "" $Pointer # cut off the part before the first "\"
StrCpy $0 $Pointer
Call StrPoint # search for the second "\"
IntOp $0 $0 + $Pointer # $0 is now the pointer to the second "\" in the APPDATA string
StrCpy ${AppPre} $APPDATemp $0 # save the part before the second "\"
IntOp $Pointer $Pointer + 1 # jump after the "\"
StrCpy $String $String "" $Pointer # cut off the part before the second "\"
Call StrPoint # search for the third "\"
IntOp $Pointer $Pointer + 1 # jump after the "\"
StrCpy ${AppSuff} $String "" $Pointer # save the part after the third "\"
!macroend
#--------------------------------
Function un.GetParentA
# deletes a subfolder of the APPDATA path for all users
# used by the function "un.getUsers"
Exch $R0
Push $R1
Push $R2
Push $R3
StrCpy $R1 0
StrLen $R2 $R0
loop:
IntOp $R1 $R1 + 1
IntCmp $R1 $R2 get 0 get
StrCpy $R3 $R0 1 -$R1
StrCmp $R3 "\" get
Goto loop
get:
StrCpy $R0 $R0 -$R1
Pop $R3
Pop $R2
Pop $R1
Exch $R0
FunctionEnd
#--------------------------------
Function un.GetUsers
# reads the subfolders of the "Documents and Settings" folder to get a list of the users
StrCpy $R3 ""
Push "$PROFILE"
Call un.GetParentA
Pop $R2
StrCpy $R2 "$R2"
FindFirst $R0 $R1 "$R2\*"
StrCmp $R1 "" findend 0
findloop:
IfFileExists "$R2\$R1\*.*" 0 notDir
StrCmp $R1 "." notDir
StrCmp $R1 ".." notDir
StrCmp $R1 "All Users" notDir
StrCmp $R1 "Default User" notDir
StrCmp $R1 "All Users.WINNT" notDir
StrCmp $R1 "Default User.WINNT" notDir
StrCpy $R3 "$R3|$R1"
notDir:
FindNext $R0 $R1
StrCmp $R1 "" findend 0
Goto findloop
findend:
FindClose $R0
FunctionEnd
#--------------------------------
Function un.StrPoint
!insertmacro StrPointer $String $Search $Pointer
FunctionEnd
#--------------------------------
!macro UnAppPreSuff AppPre AppSuff
# the APPDATA path for a local user has for WinXP and 2000 the following structure:
# C:\Documents and Settings\username\Application Data
# for Win Vista the structure is:
# C:\Users\username\AppData\Roaming
# this macro saves the "C:\Documents and Settings\" substring into the variable "AppPre"
# and the "Application Data" substring into the variable "AppSuff"
SetShellVarContext current # switch temoprarily to local user
StrCpy $String "$APPDATA"
StrCpy $APPDATemp "$APPDATA"
${if} $MultiUser.Privileges == "Admin"
${orif} $MultiUser.Privileges == "Power"
SetShellVarContext all # move back to all users
${endif}
StrCpy $Search "\"
Call un.StrPoint # search for the first "\"
IntOp $Pointer $Pointer + 1 # jump after the "\"
StrCpy $String $String "" $Pointer # cut off the part before the first "\"
StrCpy $0 $Pointer
Call un.StrPoint # search for the second "\"
IntOp $0 $0 + $Pointer # $0 is now the pointer to the second "\" in the APPDATA string
StrCpy ${AppPre} $APPDATemp $0 # save the part before the second "\"
IntOp $Pointer $Pointer + 1 # jump after the "\"
StrCpy $String $String "" $Pointer # cut off the part before the second "\"
Call un.StrPoint # search for the third "\"
IntOp $Pointer $Pointer + 1 # jump after the "\"
StrCpy ${AppSuff} $String "" $Pointer # save the part after the third "\"
!macroend
#--------------------------------
Function un.DelAppPathSub
# deletes a subfolder of the APPDATA path for all users
# get list of all users
Push $R0
Push $R1
Push $R2
Push $R3
Call un.GetUsers
StrCpy $UserList $R3 "" 1 # cut off the "|" at the end of the list
Pop $R3
Pop $R2
Pop $R1
Pop $R0
# the usernames in the list of all users is separated by "|"
loop:
StrCpy $String "$UserList"
StrCpy $Search "|"
Call un.StrPoint # search for the "|"
StrCmp $Pointer "-1" ready
StrCpy $0 $UserList $Pointer # $0 contains now the username
IntOp $Pointer $Pointer + 1 # jump after the "|"
StrCpy $UserList $UserList "" $Pointer # cut off the first username in the list
# generate the string for the current user
# AppPre and AppSuff are generated in the macro "AppPreSuff"
RMDir /r "$AppPre\$0\$AppSuff\$AppSubfolder" # delete the folder
Goto loop
ready:
StrCpy $0 $UserList
RMDir /r "$AppPre\$0\$AppSuff\$AppSubfolder" # delete the folder
FunctionEnd
#--------------------------------
!macro FileCheck Result FileName FilePath
# checks if a file exists, returns "True" or "False"
Push $0
Push $1
StrCpy $0 ""
StrCpy $1 ""
FileOpen $0 "${FilePath}\${FileName}" r
${if} $0 = ""
StrCpy $1 "False"
${Else}
StrCpy $1 "True"
${endif}
FileClose $0
StrCpy ${Result} $1
Pop $1
Pop $0
!macroend