1 Option Explicit ' Variables must be declared explicitly
5 '******************************************************************************
7 '******************************************************************************
9 const Version = "2.11.9"
10 const Installer = "cc65 Installer"
11 const SpaceNeeded = 20 ' Free space needed on drive in MiB.
12 const Shortcut = true ' Create shortcut on desktop
16 '******************************************************************************
18 '******************************************************************************
19 const SysEnv = "HKLM\System\CurrentControlSet\Control\Session Manager\Environment"
20 const SysPath = "HKLM\System\CurrentControlSet\Control\Session Manager\Environment\Path"
24 '******************************************************************************
26 '******************************************************************************
27 dim Tab, NewLine, Quote ' String constants
28 dim Shell, FSO ' Global objects
29 dim ProgArgs ' Program arguments
30 dim Dbg ' Output debugging stuff
31 dim Language ' Program language
32 dim SystemDrive ' The system drive
33 dim SystemRoot ' The windows directory
34 dim UserName ' Name if the current user
35 dim UserProfile ' User profile directory
36 dim ProgramFiles ' Program files directory
37 dim AppData ' Application data directory
38 dim InstallSource ' Installation source directory
39 dim InstallTarget ' Installation target directory
40 dim UninstallCtrlFileName ' Name of the control file for the uninstaller
41 dim UninstallCtrlFile ' Control file for the uninstaller
42 dim Uninstaller ' Path to the uninstaller file
43 dim UninstallerCmdLine ' Command line for the uninstaller
44 dim Programs ' "Programs" menu folder
45 dim Desktop ' "Desktop" menu folder
46 dim RegUninstall ' Registry key for uninstall entries
47 dim BinDir ' Directory for binaries
48 dim LibDir ' Library directory
49 dim IncDir ' Include directory
50 dim DocIndexFile ' Name of documentation index file
51 dim AnnouncementFile ' Name of the announcement file
55 '******************************************************************************
56 ' Display an error message window with an OK button
57 '******************************************************************************
59 call MsgBox (Msg, vbOkOnly + vbExclamation, Installer)
64 '******************************************************************************
65 ' Display an error message window and abort the installer
66 '******************************************************************************
74 '******************************************************************************
75 ' Display a message with an OK button
76 '******************************************************************************
78 call MsgBox (Msg, vbOkOnly + vbInformation, Installer)
83 '******************************************************************************
84 ' Convert a number to a string
85 '******************************************************************************
86 function ToString (Num)
87 ToString = FormatNumber (Num, vbFalse, vbTrue, vbFalse, vbFalse)
92 '******************************************************************************
93 ' Return a message in the current language
94 '******************************************************************************
98 ' Handle other languages here
101 if IsEmpty (Msg) then
102 ' No assignment, use english
105 Msg = "Installation was aborted."
107 Msg = "You must be Administrator to install %1."
108 Msg = Msg & " Are you sure you want to continue?"
110 Msg = "Cannot copy %1 to %2: " & NewLine & "%3"
112 Msg = "%1 does not exist." & NewLine & "Create it?"
114 Msg = "Cannot create %1:" & NewLine & "%2"
116 Msg = "Cannot delete %1:" & NewLine & "%2"
117 case "MSG_DRIVESPACE"
118 Msg = "Not enough space left on drive %1" & NewLine
119 Msg = Msg & "At least %2 MB are needed."
120 case "MSG_INSTALLPATH"
121 Msg = "The package will be installed in %1"
123 Msg = "%1 Documentation"
124 case "MSG_REGREADERR"
125 Msg = "Installation failed: Cannot read the registry!"
126 case "MSG_REGWRITEERR"
127 Msg = "Installation failed: Cannot write to the registry!"
128 case "MSG_REMOVEENTRY"
131 Msg = "A folder with the name %1 does already exist."
132 Msg = Msg & " Is it ok to remove the folder?"
134 Msg = "Found an old version. Remove it?"
136 Msg = "Installation was successful!"
137 case "MSG_UNINSTALLERR"
138 Msg = "There was a problem uninstalling the old version. Please"
139 Msg = Msg & " uninstall the old program manually and restart"
140 Msg = Msg & " the installation."
141 case "MSG_ANNOUNCEMENT"
142 Msg = "cc65 Announcement"
143 case "MSG_INCOMPLETE"
144 Msg = "The package seems to be incomplete and cannot be"
145 Msg = Msg & " installed."
155 '******************************************************************************
156 ' Format a string replacing %n specifiers in the format string F
157 '******************************************************************************
158 function Fmt (F, Values)
159 dim I, Count, Key, Val, Start, Pos
160 Count = UBound (Values) ' How many values?
161 for I = Count to 0 step -1
162 Key = "%" & ToString (I)
163 select case VarType (Values (I))
167 Val = ToString (Values (I))
169 Val = ToString (Values (I))
173 Val = ToString (Values (I))
175 Val = ToString (Values (I))
179 Abort ("Internal error: Invalid conversion in Format()")
181 F = Replace (F, Key, Val)
188 '******************************************************************************
189 ' Format a message replacing %n specifiers in the format string F
190 '******************************************************************************
191 function FmtMsg (Msg, Values)
192 FmtMsg = Fmt (GetMsg (Msg), Values)
197 '******************************************************************************
198 ' Return an environment string. Fix up Microsoft's "innovative" ideas.
199 '******************************************************************************
200 function GetEnv (Key)
202 Value = Shell.ExpandEnvironmentStrings (Key)
204 GetEnv = vbNullString
212 '******************************************************************************
213 ' Build a path from two components
214 '******************************************************************************
215 function BuildPath (Path, Name)
216 BuildPath = FSO.BuildPath (Path, Name)
221 '******************************************************************************
222 ' Return true if the file with the given name exists
223 '******************************************************************************
224 function FileExists (Name)
226 FileExists = FSO.FileExists (Name)
231 '******************************************************************************
232 ' Return true if the folder with the given name exists
233 '******************************************************************************
234 function FolderExists (Name)
236 FolderExists = FSO.FolderExists (Name)
241 '******************************************************************************
242 ' Copy a file and return an error message (empty string if no error)
243 '******************************************************************************
244 function CopyFile (Source, Target)
245 if Right (Target, 1) <> "\" and FolderExists (Target) then
246 Target = Target & "\"
249 call FSO.CopyFile (Source, Target)
251 CopyFile = Err.Description
256 '******************************************************************************
257 ' Create a folder and all parent folders and return an error string
258 '******************************************************************************
259 function CreateFolder (Path)
261 ' If the parent folder does not exist, try to create it
263 ParentFolder = FSO.GetParentFolderName (Path)
264 if ParentFolder <> "" and not FolderExists (ParentFolder) then
265 CreateFolder (ParentFolder)
268 ' Now try to create the actual folder
270 FSO.CreateFolder (Path)
271 CreateFolder = Err.Description
277 '******************************************************************************
278 ' Delete a file and return an error string
279 '******************************************************************************
280 function DeleteFile (Name)
282 call FSO.DeleteFile (Name, true)
283 DeleteFile = Err.Description
288 '******************************************************************************
289 ' Delete a folder and return an error string
290 '******************************************************************************
291 function DeleteFolder (Path)
293 call FSO.DeleteFolder (Path, true)
294 DeleteFolder = Err.Description
299 '******************************************************************************
300 ' Return the type of a registry entry
301 '******************************************************************************
302 function RegType (Value)
306 ' Determine the type of the registry value. If the string contains percent
307 ' signs, use REG_EXPAND_SZ, otherwise use REG_SZ. This isn't always safe,
308 ' but there is no way to determine the type, and VBS itself is too stupid
309 ' to choose the correct type itself. Add the usual curse over Microsoft
311 Result = InStr (1, Value, "%")
315 RegType = "REG_EXPAND_SZ"
321 '******************************************************************************
322 ' Read a string from the registry. Return an empty string if nothing was found.
323 '******************************************************************************
324 function RegReadStr (Key)
326 RegReadStr = Shell.RegRead (Key)
327 if Err.Number <> 0 then
334 '******************************************************************************
335 ' Write a binary value to the registry, return an error description
336 '******************************************************************************
337 function RegWriteBin (Key, Value)
339 Shell.RegWrite Key, Value, "REG_BINARY"
340 RegWriteBin = Err.Description
342 WriteUninstallCtrlFile ("R " & Key)
347 '******************************************************************************
348 ' Write a string value to the registry, return an error description
349 '******************************************************************************
350 function RegWriteStr (Key, Value)
352 Shell.RegWrite Key, Value, "REG_SZ"
353 RegWriteStr = Err.Description
355 WriteUninstallCtrlFile ("R " & Key)
360 '******************************************************************************
361 ' Run a program, wait for its termination and return an error code.
362 '******************************************************************************
363 function Run (Cmd, WinState)
367 ErrCode = Shell.Run (Cmd, WinState, true)
368 if Err.Number <> 0 then
376 '******************************************************************************
377 ' Display a progress bar using the internet exploder
378 '******************************************************************************
379 dim PBDoc ' Progress bar document object
380 dim PBVal ' Current progress bar setting
381 dim IEApp ' Internet exploder application object
386 sub ProgressBar (Percent)
388 ' Remember the last setting
391 'Create the progress bar window
392 if PBDoc is nothing then
394 if ((Cint (Percent) < 0) or (Cint (Percent) > 100)) then
395 ' Close request, but object already destroyed
399 ' Create an object that control the internet exploder
400 set IEApp = CreateObject ("InternetExplorer.Application")
402 ' Set the exploder to fullscreen and retrieve its size
403 dim ScreenHeight, ScreenWidth
404 IEApp.Visible = false
405 IEApp.FullScreen = true
406 ScreenWidth = IEApp.Width
407 ScreenHeight = IEApp.Height
408 IEApp.FullScreen = false
410 ' Now prepare the actual window
412 IEApp.AddressBar = false
415 IEApp.MenuBar = false
416 IEApp.StatusBar = false
418 IEApp.ToolBar = false
419 IEApp.Resizable = false
420 IEApp.Left = (ScreenWidth - IEApp.Width) / 2
421 IEApp.Top = (ScreenHeight - IEApp.Height) / 2
422 call IEApp.Navigate ("about:blank")
424 call WScript.Sleep (100)
427 ' Connect to the displayed document
428 do until not PBDoc is nothing
429 call WScript.Sleep (100)
430 set PBDoc = IEApp.Document
433 ' Generate a new document showing a progress bar
435 call PBDoc.Write ("<html><head><title>" & Installer & " progress</title></head>")
436 call PBDoc.Write ("<body bgcolor=#C0C0C0><center>")
437 call PBDoc.Write ("<table width=100% border=1 frame=box><tr><td>")
438 call PBDoc.Write ("<table id=progress width=0 border=0 cellpadding=0 cellspacing=0 bgcolor=#FFFFFF>")
439 call PBDoc.Write ("<tr><td> </td></tr></table>")
440 call PBDoc.Write ("</td></tr></table>")
441 call PBDoc.Write ("</center></body></html>")
444 ' Display the exploder window
448 if ((Cint (Percent) < 0) or (Cint (Percent) > 100)) then
449 ' Request for shutdown
450 IEApp.Visible = false
455 ' Update the progress bar
456 if Cint (Percent) = 0 then
457 PBDoc.all.progress.width = "1%"
458 PBDoc.all.progress.bgcolor = "#C0C0C0"
460 PBDoc.all.progress.width = Cstr (Cint (Percent)) & "%"
461 PBDoc.all.progress.bgcolor = "#0000C0"
469 '******************************************************************************
470 ' Initialize global variables
471 '******************************************************************************
472 sub InitializeGlobals ()
475 ' String stuff used for formatting
481 set Shell = WScript.CreateObject ("WScript.Shell")
482 set FSO = CreateObject ("Scripting.FileSystemObject")
485 set ProgArgs = WScript.Arguments
487 ' Handle program arguments
490 for I = 0 to ProgArgs.Count-1
491 select case ProgArgs(I)
501 ' Paths and locations
502 SystemDrive = GetEnv ("%SystemDrive%")
503 if SystemDrive = vbNullString then
506 SystemRoot = GetEnv ("%SystemRoot%")
507 if SystemRoot = vbNullString then
508 SystemRoot = BuildPath (SystemDrive, "winnt")
510 UserName = GetEnv ("%USERNAME%")
511 if UserName = vbNullString then
512 UserName = "Administrator"
514 UserProfile = GetEnv ("%USERPROFILE%")
515 if UserProfile = vbNullString then
516 UserProfile = BuildPath (SystemDrive, "Dokumente und Einstellungen\" & UserName)
518 ProgramFiles = GetEnv ("%ProgramFiles%")
519 if ProgramFiles = vbNullString then
520 ProgramFiles = BuildPath (SystemDrive, "Programme")
522 AppData = GetEnv ("%AppData%")
523 if AppData = vbNullString then
524 AppData = UserProfile
526 InstallSource = FSO.GetParentFolderName (WScript.ScriptFullName)
527 InstallTarget = BuildPath (ProgramFiles, AppName)
529 Programs = Shell.SpecialFolders ("AllUsersPrograms")
530 Desktop = Shell.SpecialFolders ("AllUsersDesktop")
533 set UninstallCtrlFile = nothing
534 Uninstaller = Quote & BuildPath (InstallTarget, "uninstall.vbs") & Quote
535 UninstallCtrlFileName = BuildPath (InstallTarget, "uninstall.lst")
536 UninstallerCmdLine = "-" & Language & " " & AppName & " " & Quote & UninstallCtrlFileName & Quote
539 RegUninstall = "HKLM\Software\Microsoft\Windows\CurrentVersion\Uninstall\" & AppName & "\"
542 BinDir = BuildPath (InstallTarget, "bin")
543 LibDir = BuildPath (InstallTarget, "lib")
544 IncDir = BuildPath (InstallTarget, "include")
547 AnnouncementFile = "announce.txt"
548 DocIndexFile = "doc\index.html"
553 '******************************************************************************
554 ' Ask a yes/no question and return the result. "Yes" is default.
555 '******************************************************************************
556 function AskYesNo (Question)
557 AskYesNo = MsgBox (Question, vbYesNo + vbQuestion + vbDefaultButton1, Installer)
562 '******************************************************************************
563 ' Ask a yes/no question and return the result. "No" is default.
564 '******************************************************************************
565 function AskNoYes (Question)
566 AskNoYes = MsgBox (Question, vbYesNo + vbQuestion + vbDefaultButton2, Installer)
571 '******************************************************************************
572 ' Tell the user that the installation was aborted and terminate the script
573 '******************************************************************************
575 call MsgBox (GetMsg ("MSG_ABORTINFO"), vbOkOnly + vbInformation, Installer)
581 '******************************************************************************
582 ' Input routine with the window caption preset
583 '******************************************************************************
584 function Input (Prompt, Default)
585 Input = InputBox (Prompt, Installer, Default)
590 '******************************************************************************
591 ' Check if a directory is a given the path
592 '******************************************************************************
593 function DirInPath (ByVal Dir)
597 ' Get the path in lower case
598 Path = LCase (GetEnv ("%Path%"))
600 ' Convert the directory to lower case
603 ' Split the path into separate entries
604 Entries = Split (Path, ";")
607 for I = LBound (Entries) to UBound (Entries)
608 if Entries(I) = Dir then
620 '******************************************************************************
621 ' Function that displays the paths and locations found
622 '******************************************************************************
623 function OneLoc (Key, Value)
626 if Len (Result) <= 8 then
627 Result = Result & Tab
629 OneLoc = Result & Tab & "=" & Tab & Value & NewLine
632 sub ShowPathsAndLocations ()
634 Msg = Msg & OneLoc ("SystemDrive", SystemDrive)
635 Msg = Msg & OneLoc ("SystemRoot", SystemRoot)
636 Msg = Msg & OneLoc ("User Name", UserName)
637 Msg = Msg & OneLoc ("UserProfile", UserProfile)
638 Msg = Msg & OneLoc ("ProgramFiles", ProgramFiles)
639 Msg = Msg & OneLoc ("AppData", AppData)
640 Msg = Msg & OneLoc ("InstallSource", InstallSource)
641 Msg = Msg & OneLoc ("InstallTarget", InstallTarget)
642 Msg = Msg & OneLoc ("Programs", Programs)
643 Msg = Msg & OneLoc ("Desktop", Desktop)
644 Msg = Msg & OneLoc ("Free space", ToString (GetDriveSpace (InstallTarget)))
646 call MsgBox (Msg, vbOkOnly, "Paths and Locations")
651 '******************************************************************************
652 ' Return the amount of free space for a path (in Megabytes)
653 '******************************************************************************
654 function GetDriveSpace (Path)
657 set Drive = FSO.GetDrive (FSO.GetDriveName (Path))
658 if Err.Number <> 0 then
661 GetDriveSpace = Drive.FreeSpace / (1024 * 1024)
667 '******************************************************************************
668 ' Check that there's something to install
669 '******************************************************************************
670 sub CheckFilesToInstall ()
672 ' If the uninstaller is unavailable for some reason or the other, we
673 ' have a problem, because the installer will create an uninstaller entry
674 ' in the registry, but it will not work, which means that the package
675 ' cannot be deinstalled or overwritten. So we have to check that at least
676 ' the uninstaller is available in the same directory as the installer.
677 if not FileExists (BuildPath (InstallSource, "uninstall.vbs")) then
678 Abort (GetMsg ("MSG_INCOMPLETE"))
684 '******************************************************************************
685 ' Check that were running this script as admin
686 '******************************************************************************
687 sub CheckAdminRights ()
689 ' FIXME: This check is not perfect
690 if UserName <> "Administrator" then
694 if AskNoYes (FmtMsg ("MSG_ADMIN", Args)) <> vbYes then
703 '******************************************************************************
704 ' Remove an old installation.
705 '******************************************************************************
706 sub RemoveOldInstall (UninstallCmd)
710 ' Execute the uninstall
711 ErrCode = Run (UninstallCmd, 0)
713 ' Tell the user that the uninstall is done
715 call Abort (GetMsg ("MSG_UNINSTALLERR"))
721 '******************************************************************************
722 ' Check if there is an old installation. Offer to remove it.
723 '******************************************************************************
724 sub CheckOldInstall ()
728 ' Read the uninstall command from the registry
729 UninstallCmd = RegReadStr (RegUninstall & "UninstallString")
731 ' Check if there is already an executable
732 if UninstallCmd <> "" then
734 ' Ask to remove an old install
735 if AskYesNo (GetMsg ("MSG_REMOVEOLD")) = vbYes then
736 ' Remove the old installation
737 call RemoveOldInstall (UninstallCmd)
746 '******************************************************************************
747 ' Check that the install target exists. Offer to create it.
748 '******************************************************************************
749 sub CheckInstallTarget ()
751 dim Msg, Result, Args(2)
753 ' Tell the user about the install target and ask if it's ok
754 Args(1) = InstallTarget
755 Msg = FmtMsg ("MSG_INSTALLPATH", Args)
756 if MsgBox (Msg, vbOkCancel, Installer) <> vbOk then
760 ' Check if there's enough space left on the target drive
761 if GetDriveSpace (InstallTarget) < SpaceNeeded then
762 Args(1) = FSO.GetDriveName (InstallTarget)
763 Args(2) = SpaceNeeded
764 call Abort (FmtMsg ("MSG_DRIVESPACE", Args))
767 ' Check if the install path exist, create it if necessary
768 if not FolderExists (InstallTarget) then
769 Result = CreateFolder (InstallTarget)
771 Args(1) = InstallTarget
773 call Abort (FmtMsg ("MSG_CREATEERR", Args))
781 '******************************************************************************
782 ' Create the uninstall control file
783 '******************************************************************************
784 sub CreateUninstallCtrlFile ()
788 ' Generate the filename
790 set UninstallCtrlFile = FSO.CreateTextFile (UninstallCtrlFileName, true)
792 if Err.Number <> 0 then
794 Args(1) = UninstallCtrlFileName
795 Args(2) = Err.Description
796 call ErrorMsg (FmtMsg ("MSG_CREATEERR", Args))
800 ' Write the name of the target directory to the file
801 call WriteUninstallCtrlFile ("D " & InstallTarget)
803 ' Write the name of the file itself to the file
804 call WriteUninstallCtrlFile ("F " & UninstallCtrlFileName)
810 '******************************************************************************
811 ' Write to the uninstall control file
812 '******************************************************************************
813 sub WriteUninstallCtrlFile (Line)
816 UninstallCtrlFile.WriteLine (Line)
817 if Err.Number <> 0 then
819 Args(1) = UninstallCtrlFileName
820 Args(2) = Err.Description
821 call ErrorMsg (FmtMsg ("MSG_WRITEERR", Args))
829 '******************************************************************************
830 ' Close the uninstall control file
831 '******************************************************************************
832 sub CloseUninstallCtrlFile ()
835 UninstallCtrlFile.Close
836 if Err.Number <> 0 then
838 Args(1) = UninstallCtrlFileName
839 Args(2) = Err.Description
840 call ErrorMsg (FmtMsg ("MSG_WRITEERR", Args))
848 '******************************************************************************
849 ' Copy the application files
850 '******************************************************************************
851 sub RecursiveCopy (Dir, SourcePath, TargetPath)
853 dim File, TargetFile, SubDir, SourceName, TargetName, Result, Args(3)
855 ' Copy all files in this folder
856 for each File in Dir.Files
858 ' Generate source and target file names
859 SourceName = BuildPath (SourcePath, File.Name)
860 TargetName = BuildPath (TargetPath, File.Name)
862 ' Copy the file. The error check doesn't seem to work.
864 File.Copy (TargetName)
866 if Err.Number <> 0 then
869 Args(3) = Err.Description
870 call ErrorMsg (FmtMsg ("MSG_COPYERR", Args))
874 ' Remove the r/o attribute from the target file if set
875 set TargetFile = FSO.GetFile (TargetName)
876 if TargetFile.Attributes mod 2 = 1 then
877 TargetFile.Attributes = TargetFile.Attributes - 1
880 ' Remember this file in the uninstall control file
881 call WriteUninstallCtrlFile ("F " & TargetName)
884 ' Handle all subdirectories
885 for each SubDir in Dir.SubFolders
887 ' Update the progress bar with each copied directory
889 call ProgressBar (PBVal + 5)
892 ' Generate the new directory names
893 SourceName = BuildPath (SourcePath, SubDir.Name)
894 TargetName = BuildPath (TargetPath, SubDir.Name)
896 ' Generate the new target dir. Notify the user about errors, but
897 ' otherwise ignore them.
898 Result = CreateFolder (TargetName)
900 ' Display an error but try to continue
903 call ErrorMsg (FmtMsg ("MSG_CREATEERR", Args))
906 ' Recursively process files in the subdirectory
907 call RecursiveCopy (SubDir, SourceName, TargetName)
909 ' Remember the subdirectory in the uninstall control file
910 WriteUninstallCtrlFile ("D " & TargetName)
917 ' Update the progress bar
918 call ProgressBar (10)
920 ' Copy all files generating entries in the uninstall control file
921 call RecursiveCopy (FSO.GetFolder (InstallSource), InstallSource, InstallTarget)
923 ' Update the progress bar
924 call ProgressBar (90)
929 '******************************************************************************
930 ' Create the registry entries
931 '******************************************************************************
932 sub CreateRegEntries ()
936 ' Create the entry in Systemsteuerung -> Software. Check if the first write
937 ' succeeds. If not, we don't have admin rights.
938 if RegWriteBin (RegUninstall, 1) <> "" then
939 call Abort (GetMsg ("MSG_REGWRITEERR"))
941 call RegWriteStr (RegUninstall & "DisplayName", AppName & " " & Version)
942 call RegWriteStr (RegUninstall & "UninstallString", "wscript /nologo " & Uninstaller & " " & UninstallerCmdLine)
948 '******************************************************************************
949 ' Function that creates an URL
950 '******************************************************************************
951 sub CreateUrl (Name, Url, Description)
956 set Link = Shell.CreateShortcut (Name)
957 Link.TargetPath = Url
958 Link.Description = Description
964 ' Write the file name to the uninstall control file
965 WriteUninstallCtrlFile ("F " & Name)
970 '******************************************************************************
971 ' Function that creates a shortcut
972 '******************************************************************************
973 sub CreateShortcut (Name, Exe, Args, Description)
978 set Link = Shell.CreateShortcut (Name)
979 Link.TargetPath = Exe
980 Link.Arguments = Args
982 Link.Description = Description
983 Link.WorkingDirectory = AppData
989 ' Write the file name to the uninstall control file
990 WriteUninstallCtrlFile ("F " & Name)
995 '******************************************************************************
996 ' Function that creates the menu entries
997 '******************************************************************************
998 sub CreateMenuEntries ()
999 dim Folder, Result, Name, Desc, Target, Args(2)
1001 ' Create the start menu folder.
1002 Folder = BuildPath (Programs, AppName)
1003 Result = CreateFolder (Folder)
1004 if Result <> "" then
1005 ' Display an error but try to continue
1008 call ErrorMsg (FmtMsg ("MSG_CREATEERR", Args))
1011 ' Create an uninstall shortcut in the menu folder
1013 Desc = FmtMsg ("MSG_REMOVEENTRY", Args)
1014 Name = BuildPath (Folder, Desc & ".lnk")
1015 call CreateShortcut (Name, Uninstaller, UninstallerCmdLine, Desc)
1017 ' Create a documentation shortcut in the menu folder
1018 Target = BuildPath (InstallTarget, DocIndexFile)
1019 if FileExists (Target) then
1021 Desc = FmtMsg ("MSG_DOCENTRY", Args)
1022 Name = BuildPath (Folder, Desc & ".url")
1023 call CreateUrl (Name, "file://" & Target, Desc)
1026 ' Create the shortcut to the announcement in the menu folder
1027 Target = BuildPath (InstallTarget, AnnouncementFile)
1028 if FileExists (Target) then
1029 Desc = GetMsg ("MSG_ANNOUNCEMENT")
1030 Name = BuildPath (Folder, Desc & ".url")
1031 call CreateUrl (Name, "file://" & Target, Desc)
1034 ' Update the uninstall control file
1035 call WriteUninstallCtrlFile ("D " & Folder)
1040 '******************************************************************************
1041 ' Add a directory to the system path
1042 '******************************************************************************
1043 sub AddToSysPath (Dir)
1047 ' Handle errors. Assume failure
1048 on error resume next
1050 ' Retrieve the PATH setting
1051 Path = Shell.RegRead (SysPath)
1052 if Err.Number <> 0 then
1054 call Abort (GetMsg ("MSG_REGREADERR"))
1057 ' Add the new directory to the path
1058 if (Len (Path) > 0) and (Right (Path, 1) <> ";") then
1063 ' Write the new path
1064 call Shell.RegWrite (SysPath, Path, "REG_EXPAND_SZ")
1065 if Err.Number <> 0 then
1067 call Abort (GetMsg ("MSG_REGWRITEERR"))
1073 '******************************************************************************
1074 ' Add environment variables
1075 '******************************************************************************
1076 sub AddEnvironment ()
1079 if RegWriteStr (SysEnv & "\CC65_LIB", LibDir) <> "" then
1080 call Abort (GetMsg ("MSG_REGWRITEERR"))
1084 if RegWriteStr (SysEnv & "\CC65_INC", IncDir) <> "" then
1085 call Abort (GetMsg ("MSG_REGWRITEERR"))
1088 ' Add the bin directory to the path if it's not already there
1089 if not DirInPath (BinDir) then
1090 call AddToSysPath (BinDir)
1093 ' Run the wm_envchange program to notify other running programs
1094 ' of the changed environment. Ignore errors.
1095 call Run (BuildPath (BinDir, "wm_envchange.exe"), 0)
1101 '******************************************************************************
1102 ' Function that tells the user that the install was successful
1103 '******************************************************************************
1105 call MsgBox (GetMsg ("MSG_SUCCESS"), vbOkOnly + vbInformation, Installer)
1110 '******************************************************************************
1112 '******************************************************************************
1115 ' Initialize global variables. This includes the paths used
1116 call InitializeGlobals ()
1118 call ShowPathsAndLocations ()
1121 ' Check that there's something to install
1122 call CheckFilesToInstall ()
1124 ' Check that we're running this script as admin
1125 call CheckAdminRights ()
1127 ' Check if there is an old installation and offer to remove it
1128 call CheckOldInstall ()
1130 ' Check if the source directory does really exist
1131 call CheckInstallTarget ()
1133 ' Display the progress bar
1134 call ProgressBar (0)
1136 ' Create the uninstall file
1137 call CreateUninstallCtrlFile ()
1138 call ProgressBar (2)
1140 ' Create registry entries
1142 call Progressbar (5)
1144 ' Copy the application files (will do automatic progress bar updates)
1147 ' Create the menu entries
1148 call CreateMenuEntries ()
1149 call ProgressBar (90)
1151 ' Add entries to the enviroment
1152 call AddEnvironment ()
1153 call ProgressBar (95)
1155 ' Close the uninstall control file
1156 call CloseUninstallCtrlFile ()
1159 call ProgressBar (100)
1160 call ProgressBar (-1)
1163 ' Return a success code
1169 '******************************************************************************
1170 ' The script body just calls Main...
1171 '******************************************************************************