class EL_APPLICATION_INSTALLER

(source code)

description

Windows application installer

note
	description: "Windows application installer"

	author: "Finnian Reilly"
	copyright: "Copyright (c) 2001-2022 Finnian Reilly"
	contact: "finnian at eiffel hyphen loop dot com"

	license: "MIT license (See: en.wikipedia.org/wiki/MIT_License)"
	date: "2022-11-15 19:56:07 GMT (Tuesday 15th November 2022)"
	revision: "6"

deferred class
	EL_APPLICATION_INSTALLER

inherit
	EXECUTION_ENVIRONMENT
		rename
			current_working_directory as install_files_root
		export
			{NONE} all
		end

	EL_MODULE_FILE_SYSTEM

	EL_MODULE_LOG

feature {NONE} -- Initialization

	make
			-- Initialize `Current'.
		do
			create shell_link.make
		end

feature -- Access

	program_menu_path: DIR_PATH

feature -- Element change

	 set_application_home (an_application_home: like application_home)
			--
		do
			application_home := an_application_home
		end

	set_desktop_shortcut (a_desktop_shortcut: like has_desktop_shortcut)
			-- Set `has_desktop_shortcut' to `a_desktop_shortcut'.
		do
			has_desktop_shortcut := a_desktop_shortcut
		ensure
			desktop_shortcut_assigned: has_desktop_shortcut = a_desktop_shortcut
		end

	set_program_menu_path (a_program_menu_path: like program_menu_path)
			-- Set `program_menu_path' to `a_program_menu_path'.
		do
			program_menu_path := a_program_menu_path
		ensure
			program_menu_path_assigned: program_menu_path = a_program_menu_path
		end

feature -- Access

	application_home: DIR_PATH

feature -- Basic operations

	install
			--
		require
			application_home_is_set: application_home /= Void
		local
			program_file_link_path: FILE_PATH
			target_path: FILE_PATH
		do
			log.enter ("install")
			File_system.make_directory (application_home)
			File_system.make_directory (program_menu_path)

			across File_source_directories as path loop
				place_files_in_destination (path.item)
			end
			target_path := application_home + Launch_command_relative_path

			shell_link.load (File_link_path)
			shell_link.set_target_path (target_path)
			if not Launch_command_arguments.is_empty then
				shell_link.set_command_arguments (Launch_command_arguments)
			end
			shell_link.set_working_directory (target_path.parent)
			shell_link.set_icon_location (Shell_link_icon_path, 1)

			program_file_link_path := program_menu_path + Launch_shortcut_name
			program_file_link_path.add_extension ("lnk")

			shell_link.save (program_file_link_path)
			if has_desktop_shortcut then
				shell_link.save (Desktop_link_path)
			end
			log.exit
		end

feature {NONE} -- Implementation

	place_files_in_destination (directory: ZSTRING)
			--
		local
			l_command: EL_OS_COMMAND
			source_path, destination_path: DIR_PATH
			source_drive, destination_drive: CHARACTER_32
		do
			log.enter_with_args ("place_files_in_destination", << directory >>)
			create source_path.make (install_files_root)
			source_path.append_step (directory)
			create destination_path.make (application_home)

			source_drive := source_path.first_step [1]
			destination_drive := application_home.first_step [1]

			if source_drive = destination_drive then
				l_command := (Move_directory_command)
			else
				l_command := (Copy_directory_command)
				destination_path.append_step (directory)
			end
			l_command.put_path ("source", source_path)
			l_command.put_path ("application_home", destination_path)
			l_command.execute
			log.exit
		end

	has_desktop_shortcut: BOOLEAN

	shell_link: EL_SHELL_LINK

	source: STRING

	File_link_path: FILE_PATH
			-- relative to installation root
		local
			l_dir: DIR_PATH
		do
			l_dir := install_files_root
			Result := l_dir + File_link_relative_path
		end

feature -- Constants

	Default_application_home: STRING
			--
		deferred
		end

	Default_menu_folder_name: STRING
			--
		deferred
		end

	Launch_shortcut_name: STRING
			--
		deferred
		end

	Desktop_link_path: FILE_PATH
			--
		once
			create Result.make (item ("USERPROFILE"))
			Result.append_step ("Desktop")
			Result.append_step (Launch_shortcut_name)
			Result.add_extension ("lnk")
		end

	File_source_directories: ARRAY [STRING]
			--
		deferred
		end

	File_link_relative_path: STRING
			-- relative to installation root
		deferred
		end

	Launch_command_relative_path: STRING
			-- relative to installation root
		deferred
		end

	Launch_command_arguments: STRING
			-- Arguments to launch command
		once
			create Result.make_empty
		end

	Executable_relative_path: STRING
			-- relative to installation root
		deferred
		end

	Shell_link_icon_path: FILE_PATH
			--
		once
			Result := application_home + Executable_relative_path
		end

feature {NONE} -- OS commands

	Copy_directory_command: EL_OS_COMMAND
		once
			create Result.make ("xcopy /I /S /Y %"$source%" %"$application_home%"")
		end

	Move_directory_command: EL_OS_COMMAND
		once
			create Result.make ("move /Y %"$source%" %"$application_home%"")
		end

feature -- Window  constants

	Window_title: STRING
			--
		deferred
		end

	Window_icon: EV_PIXMAP
			--
		deferred
		end

	Application_logo_pixmap: EV_PIXMAP
			--
		deferred
		end

	Application_icons: EL_APPLICATION_ICON
			--
		once
			create Result
		end

end