Commit bcd29b66 authored by rgaudin's avatar rgaudin
Browse files

Fixed #207: Provide a way to manually install (or uninstall) external dependency Imdisk.

* One might want to uninstall ImDisk
* One might need to reinstall ImDisk
* One might need to install it manually if auto-install failed (see #206)
parent 6aa1a410
......@@ -2,6 +2,7 @@
* Domain tld changed to .hotstop (was .lan)
* Supplied file (edupi_resource, logo, css, favicon) checked for existence
* Fixed JSON export on Windows [regression]
* Fixed ImDisk installation (Windows)
2.0-rc4
* Use decimal (GB) sizes for SD card selection
......
imdisk.png

7.45 KB

......@@ -22,6 +22,7 @@ a = Analysis(['pibox-installer/__main__.py'],
binaries=[(os.path.join(typelib_path, tl), 'gi_typelibs') for tl in os.listdir(typelib_path)],
datas=[('ui.glade', '.'),
('contents.json', '.'),
('imdisk.png', '.'),
('pibox-installer-logo.png', '.'),
('ansiblecube', 'ansiblecube'),
('pibox-installer-vexpress-boot', 'pibox-installer-vexpress-boot'),
......
......@@ -22,6 +22,7 @@ a = Analysis(['pibox-installer/__main__.py'],
binaries=[(os.path.join(typelib_path, tl), 'gi_typelibs') for tl in os.listdir(typelib_path)],
datas=[('ui.glade', '.'),
('contents.json', '.'),
('imdisk.png', '.'),
('pibox-installer-logo.png', '.'),
('ansiblecube', 'ansiblecube'),
('pibox-installer-vexpress-boot', 'pibox-installer-vexpress-boot'),
......
......@@ -13,7 +13,8 @@ import tempfile
from data import data_dir
from backend.content import get_content
from backend.qemu import get_qemu_image_size
from backend.util import subprocess_pretty_check_call, subprocess_pretty_call
from backend.util import (subprocess_pretty_check_call, subprocess_pretty_call,
subprocess_external)
def system_has_exfat():
......@@ -78,9 +79,11 @@ def install_imdisk(logger, force=False):
''' install imdisk manually (replicating steps from install.cmd) '''
# assume already installed
logger.std("Looking for {}".format(imdisk_exe))
if os.path.exists(imdisk_exe) and not force:
logger.std("imdisk present at {}".format(imdisk_exe))
logger.std("ImDisk already present.")
return
logger.std("Imdisk IS NOT present. Installing...")
# disable integrity checks (allow install of unsigned driver)
subprocess_pretty_call([os.path.join(system32, 'bcdedit.exe'),
......@@ -114,38 +117,14 @@ def install_imdisk(logger, force=False):
"Please reboot your computer and retry"
.format(" ".join(failed)))
assert os.path.exists(imdisk_exe)
def install_imdisk_via_cmd(logger):
''' install imdisk via its .cmd file (silent mode)
doesn't provide much feedback '''
# set silent variable to prevent popup
os.environ['IMDISK_SILENT_SETUP'] = "1"
cwd = os.getcwd()
try:
os.chdir(imdiskinst)
subprocess_pretty_check_call(['cmd.exe', 'install.cmd'], logger)
except Exception:
pass
finally:
os.chdir(cwd)
def uninstall_imdisk(logger):
''' uninstall imdisk using its uninstaller script '''
# set silent variable to prevent popup
os.environ['IMDISK_SILENT_SETUP'] = "1"
cwd = os.getcwd()
try:
os.chdir(imdiskinst)
subprocess_pretty_check_call(
['cmd.exe', 'uninstall_imdisk.cmd'], logger)
except Exception:
pass
finally:
os.chdir(cwd)
def open_explorer_for_imdisk(logger):
subprocess_external([
os.path.join(os.environ['SystemRoot'], 'explorer.exe'),
'/select,', os.path.normpath(os.path.join(imdiskinst, 'install.cmd'))],
logger)
def get_avail_drive_letter(logger):
......
......@@ -38,7 +38,7 @@ def subprocess_pretty_call(cmd, logger, stdin=None,
if sys.platform == "win32":
if logger is not None:
logger.std("Call (as admin): " + str(cmd))
return run_as_win_admin(cmd)
return run_as_win_admin(cmd, logger)
from_cli = logger is None or type(logger) == CLILogger
cmd = get_admin_command(cmd, from_gui=not from_cli)
......@@ -74,6 +74,12 @@ def subprocess_pretty_check_call(cmd, logger, stdin=None, as_admin=False):
stdin=stdin, check=True, as_admin=as_admin)
def subprocess_external(cmd, logger):
''' spawn a new process without capturing nor watching it '''
logger.std("Opening: " + str(cmd))
subprocess.Popen(cmd)
def is_admin():
''' whether current process is ran as Windows Admin or unix root '''
if sys.platform == "win32":
......@@ -86,7 +92,7 @@ def is_admin():
def run_as_win_admin(command, logger):
''' run specified command with admin rights '''
params = " ".join(['"{}"'.format(x) for x in command[1:]])
params = " ".join(['"{}"'.format(x) for x in command[1:]]).strip()
rc = ctypes.windll.shell32.ShellExecuteW(None, "runas",
command[0],
params, None, 1)
......
......@@ -4,6 +4,7 @@ gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, Gdk, GLib, GdkPixbuf, GObject
from backend.catalog import YAML_CATALOGS
from backend.content import get_expanded_size, get_collection, get_required_image_size, get_content, isremote
from backend.mount import open_explorer_for_imdisk
from run_installation import run_installation
import pytz
import tzlocal
......@@ -86,6 +87,8 @@ class Logger(ProgressHelper):
GLib.idle_add(self.main_thread_failed, error)
def main_thread_text(self, text, end="\n", tag=None):
if not isinstance(text, str):
text = str(text)
text += end
text_iter = self.text_buffer.get_end_iter()
if tag is None:
......@@ -233,6 +236,12 @@ class Application:
self.component.menu_help.connect(
"activate", self.activate_menu_help)
# imdisk menu is windows only
if sys.platform == "win32" or True:
self.component.menu_imdisk.set_visible(True)
self.component.menu_imdisk.connect(
"activate", self.activate_menu_imdisk)
# wifi password
self.component.wifi_password_switch.connect("notify::active", lambda switch, state: self.component.wifi_password_revealer.set_reveal_child(not switch.get_active()))
......@@ -493,6 +502,40 @@ class Application:
def activate_menu_help(self, widget):
webbrowser.open(data.help_url)
def activate_menu_imdisk(self, widget):
class ImDiskDialog(Gtk.Dialog):
def __init__(self, parent):
Gtk.Dialog.__init__(
self, "Install or Uninstall ImDisk Manually", parent, 0,
(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
Gtk.STOCK_OK, Gtk.ResponseType.OK))
self.set_default_size(500, 300)
label = Gtk.Label()
label.set_markup(
"\nBy selecting OK bellow, you will be directed to the "
"ImDisk installation folder.\n"
"<b>Right-click on <i>install.cmd</i></b> and choose to "
"<u>Run as Administrator</u>.\n")
label.set_alignment(0, 0.5)
label2 = Gtk.Label()
label2.set_markup(
"\nYou can also uninstall it from that folder by "
"doing the same with <i>uninstall_imdisk.cmd</i>.\n")
label2.set_alignment(0, 0.5)
image = Gtk.Image.new_from_file(
os.path.join(data.data_dir, 'imdisk.png'))
box = self.get_content_area()
box.add(label)
box.add(image)
box.add(label2)
self.show_all()
dialog = ImDiskDialog(self.component.window)
if dialog.run() == Gtk.ResponseType.OK:
open_explorer_for_imdisk(self.logger)
dialog.close()
def installation_done(self, error):
ok = error == None
validate_label(self.component.done_label, ok)
......
......@@ -316,6 +316,14 @@
<property name="use_underline">True</property>
</object>
</child>
<child>
<object class="GtkMenuItem" id="menu_imdisk">
<property name="label">(un)Install ImDisk Manually</property>
<property name="visible">False</property>
<property name="can_focus">False</property>
<property name="use_underline">True</property>
</object>
</child>
<child>
<object class="GtkMenuItem" id="menu_help">
<property name="label">Open Help / FAQ</property>
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment