From e7f6dc6b8609ca5b5453a9fb381b630b8a17b559 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Wed, 25 Aug 2021 16:05:38 -0600 Subject: [PATCH 01/40] Remove erroneous docstring --- scripts/wk/kit/ufd.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/wk/kit/ufd.py b/scripts/wk/kit/ufd.py index cc8dee28..5b700b6a 100644 --- a/scripts/wk/kit/ufd.py +++ b/scripts/wk/kit/ufd.py @@ -269,7 +269,7 @@ def copy_source(source, items, overwrite=False): def create_table(dev_path, use_mbr=False, images=None): - """Create GPT or DOS partition table, returns dict.""" + """Create GPT or DOS partition table.""" cmd = [ 'sudo', 'parted', dev_path, From 0e124dc1f23220057097e58421d78f76c2c000ab Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Tue, 31 Aug 2021 17:06:38 -0600 Subject: [PATCH 02/40] Skip Autologon cleanup if it wasn't used We found in a few cases systems starting requiring logon passwords after Auto Repairs were run. Autologon might be the cause so we should avoid running it, and the cleanup, if settings are already present. Addresses issue #175 --- scripts/auto_repairs.py | 2 +- scripts/wk/repairs/win.py | 45 ++++++++++++++++++++++----------------- 2 files changed, 26 insertions(+), 21 deletions(-) diff --git a/scripts/auto_repairs.py b/scripts/auto_repairs.py index e441632c..c4cdb339 100644 --- a/scripts/auto_repairs.py +++ b/scripts/auto_repairs.py @@ -1,4 +1,4 @@ -"""Wizard Kit: Auto-Repair Tool""" +"""Wizard Kit: Auto Repair Tool""" # vim: sts=2 sw=2 ts=2 import os diff --git a/scripts/wk/repairs/win.py b/scripts/wk/repairs/win.py index 15406f83..4eff3795 100644 --- a/scripts/wk/repairs/win.py +++ b/scripts/wk/repairs/win.py @@ -202,17 +202,6 @@ def build_menus(base_menus, title): def end_session(): """End Auto Repairs session.""" - # Delete Auto Repairs keys - try: - reg_delete_value('HKCU', AUTO_REPAIR_KEY, 'SessionStarted') - except FileNotFoundError: - LOG.error('Ending repair session but session not started.') - try: - cmd = ['reg', 'delete', fr'HKCU\{AUTO_REPAIR_KEY}', '/f'] - run_program(cmd) - except CalledProcessError: - LOG.error('Failed to remote Auto Repairs session settings') - # Remove logon task cmd = [ 'schtasks', '/delete', '/f', @@ -224,20 +213,26 @@ def end_session(): LOG.error("Failed to remove scheduled task or it doesn't exist.") # Disable Autologon - if is_autologon_enabled(): + autologon_selected = reg_read_value( + 'HKCU', AUTO_REPAIR_KEY, 'Use Autologon', + ) + if autologon_selected and is_autologon_enabled(): run_tool('Sysinternals', 'Autologon', download=True) reg_set_value( 'HKLM', r'Software\Microsoft\Windows NT\CurrentVersion\Winlogon', 'AutoAdminLogon', '0', 'SZ', ) - reg_delete_value( - 'HKLM', r'Software\Microsoft\Windows NT\CurrentVersion\Winlogon', - 'DefaultUserName', - ) - reg_delete_value( - 'HKLM', r'Software\Microsoft\Windows NT\CurrentVersion\Winlogon', - 'DefaultDomainName', - ) + + # Delete Auto Repairs keys + try: + reg_delete_value('HKCU', AUTO_REPAIR_KEY, 'SessionStarted') + except FileNotFoundError: + LOG.error('Ending repair session but session not started.') + try: + cmd = ['reg', 'delete', fr'HKCU\{AUTO_REPAIR_KEY}', '/f'] + run_program(cmd) + except CalledProcessError: + LOG.error('Failed to remote Auto Repairs session settings') def get_entry_settings(group, name): @@ -270,6 +265,12 @@ def init(menus): download=True, msg_good='DONE', ) + # Check if autologon is needed + if not session_started and is_autologon_enabled(): + # Avoid running Autologon and keep current settings + menus['Options'].options['Use Autologon']['Selected'] = False + save_selection_settings(menus) + # Start or resume a repair session if session_started: load_settings(menus) @@ -414,6 +415,10 @@ def run_auto_repairs(base_menus): save_selection_settings(menus) print_info('Initializing...') init_run(menus['Options'].options) + reg_set_value( + 'HKCU', AUTO_REPAIR_KEY, 'Use Autologon', + int(is_autologon_enabled()), 'DWORD', + ) if not is_autologon_enabled(): # Either it wasn't selected or a password wasn't entered menus['Options'].options['Use Autologon']['Selected'] = False From 7dfd399e6e6e4d599837ef58f70acba2aa583a5d Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Mon, 13 Sep 2021 18:42:36 -0600 Subject: [PATCH 03/40] Update __init__.py files --- scripts/wk/__init__.py | 28 ++++++++++++++-------------- scripts/wk/cfg/__init__.py | 14 +++++++------- scripts/wk/hw/__init__.py | 8 ++++---- scripts/wk/kit/__init__.py | 4 ++-- scripts/wk/os/__init__.py | 6 +++--- scripts/wk/repairs/__init__.py | 2 +- scripts/wk/setup/__init__.py | 7 +++++++ scripts/wk/sw/__init__.py | 1 - 8 files changed, 38 insertions(+), 32 deletions(-) create mode 100644 scripts/wk/setup/__init__.py delete mode 100644 scripts/wk/sw/__init__.py diff --git a/scripts/wk/__init__.py b/scripts/wk/__init__.py index 25620f35..51521ea3 100644 --- a/scripts/wk/__init__.py +++ b/scripts/wk/__init__.py @@ -3,20 +3,20 @@ from sys import version_info as version -from wk import cfg -from wk import debug -from wk import exe -from wk import graph -from wk import hw -from wk import io -from wk import kit -from wk import log -from wk import net -from wk import os -from wk import repairs -from wk import std -from wk import sw -from wk import tmux +from . import cfg +from . import debug +from . import exe +from . import graph +from . import hw +from . import io +from . import kit +from . import log +from . import net +from . import os +from . import repairs +from . import setup +from . import std +from . import tmux # Check env diff --git a/scripts/wk/cfg/__init__.py b/scripts/wk/cfg/__init__.py index d35b8874..c3eb64da 100644 --- a/scripts/wk/cfg/__init__.py +++ b/scripts/wk/cfg/__init__.py @@ -1,9 +1,9 @@ """WizardKit: cfg module init""" -from wk.cfg import ddrescue -from wk.cfg import hw -from wk.cfg import log -from wk.cfg import main -from wk.cfg import net -from wk.cfg import tools -from wk.cfg import ufd +from . import ddrescue +from . import hw +from . import log +from . import main +from . import net +from . import tools +from . import ufd diff --git a/scripts/wk/hw/__init__.py b/scripts/wk/hw/__init__.py index ad2b04cb..741d3151 100644 --- a/scripts/wk/hw/__init__.py +++ b/scripts/wk/hw/__init__.py @@ -1,6 +1,6 @@ """WizardKit: hw module init""" -from wk.hw import ddrescue -from wk.hw import diags -from wk.hw import obj -from wk.hw import sensors +from . import ddrescue +from . import diags +from . import obj +from . import sensors diff --git a/scripts/wk/kit/__init__.py b/scripts/wk/kit/__init__.py index 4641fae7..c6eedd73 100644 --- a/scripts/wk/kit/__init__.py +++ b/scripts/wk/kit/__init__.py @@ -3,7 +3,7 @@ import platform -from wk.kit import tools +from . import tools if platform.system() == 'Linux': - from wk.kit import ufd + from . import ufd diff --git a/scripts/wk/os/__init__.py b/scripts/wk/os/__init__.py index dff18ac2..693ec59c 100644 --- a/scripts/wk/os/__init__.py +++ b/scripts/wk/os/__init__.py @@ -4,8 +4,8 @@ import platform if platform.system() == 'Darwin': - from wk.os import mac + from . import mac if platform.system() == 'Linux': - from wk.os import linux + from . import linux if platform.system() == 'Windows': - from wk.os import win + from . import win diff --git a/scripts/wk/repairs/__init__.py b/scripts/wk/repairs/__init__.py index cbdf27e4..724c52c0 100644 --- a/scripts/wk/repairs/__init__.py +++ b/scripts/wk/repairs/__init__.py @@ -4,4 +4,4 @@ import platform if platform.system() == 'Windows': - from wk.repairs import win + from . import win diff --git a/scripts/wk/setup/__init__.py b/scripts/wk/setup/__init__.py new file mode 100644 index 00000000..33b5ea29 --- /dev/null +++ b/scripts/wk/setup/__init__.py @@ -0,0 +1,7 @@ +"""WizardKit: repairs module init""" +# vim: sts=2 sw=2 ts=2 + +import platform + +#if platform.system() == 'Windows': +# from . import win diff --git a/scripts/wk/sw/__init__.py b/scripts/wk/sw/__init__.py deleted file mode 100644 index 1cc6236f..00000000 --- a/scripts/wk/sw/__init__.py +++ /dev/null @@ -1 +0,0 @@ -"""WizardKit: sw module init""" From 56a8ffea03a709cecb6fb5d6815013d6c61c8d3b Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Mon, 13 Sep 2021 20:45:16 -0600 Subject: [PATCH 04/40] Fix path to main.py config file --- scripts/Launch.cmd | 4 ++-- scripts/Launcher_Template.cmd | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/Launch.cmd b/scripts/Launch.cmd index 1afddb2b..b7603453 100644 --- a/scripts/Launch.cmd +++ b/scripts/Launch.cmd @@ -18,8 +18,8 @@ call :DeQuote L_PATH call :DeQuote L_TYPE :SetVariables -rem Set variables using settings\main.py file -set "SETTINGS=%bin%\Scripts\settings\main.py" +rem Set variables using wk\cfg\main.py file +set "SETTINGS=%bin%\Scripts\wk\cfg\main.py" for %%v in (ARCHIVE_PASSWORD KIT_NAME_FULL OFFICE_SERVER_IP QUICKBOOKS_SERVER_IP) do ( set "var=%%v" for /f "tokens=* usebackq" %%f in (`findstr "!var!=" "%SETTINGS%"`) do ( diff --git a/scripts/Launcher_Template.cmd b/scripts/Launcher_Template.cmd index 9bb03a97..86ddd9be 100644 --- a/scripts/Launcher_Template.cmd +++ b/scripts/Launcher_Template.cmd @@ -67,8 +67,8 @@ popd @exit /b 0 :SetTitle -rem Sets title using KIT_NAME_FULL from settings\main.py -set "SETTINGS=%bin%\Scripts\settings\main.py" +rem Sets title using KIT_NAME_FULL from wk\cfg\main.py +set "SETTINGS=%bin%\Scripts\wk\cfg\main.py" for /f "tokens=* usebackq" %%f in (`findstr KIT_NAME_FULL "%SETTINGS%"`) do ( set "_v=%%f" set "_v=!_v:*'=!" From e90b59853c1eb417a2eb550dd2515253daa0af73 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Tue, 14 Sep 2021 19:14:01 -0600 Subject: [PATCH 05/40] Update launch scripts to use new config location --- scripts/Launch.cmd | 2 +- scripts/Launcher_Template.cmd | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/Launch.cmd b/scripts/Launch.cmd index b7603453..ade2f35a 100644 --- a/scripts/Launch.cmd +++ b/scripts/Launch.cmd @@ -18,7 +18,7 @@ call :DeQuote L_PATH call :DeQuote L_TYPE :SetVariables -rem Set variables using wk\cfg\main.py file +rem Set variables using settings\main.py file set "SETTINGS=%bin%\Scripts\wk\cfg\main.py" for %%v in (ARCHIVE_PASSWORD KIT_NAME_FULL OFFICE_SERVER_IP QUICKBOOKS_SERVER_IP) do ( set "var=%%v" diff --git a/scripts/Launcher_Template.cmd b/scripts/Launcher_Template.cmd index 86ddd9be..9bb03a97 100644 --- a/scripts/Launcher_Template.cmd +++ b/scripts/Launcher_Template.cmd @@ -67,8 +67,8 @@ popd @exit /b 0 :SetTitle -rem Sets title using KIT_NAME_FULL from wk\cfg\main.py -set "SETTINGS=%bin%\Scripts\wk\cfg\main.py" +rem Sets title using KIT_NAME_FULL from settings\main.py +set "SETTINGS=%bin%\Scripts\settings\main.py" for /f "tokens=* usebackq" %%f in (`findstr KIT_NAME_FULL "%SETTINGS%"`) do ( set "_v=%%f" set "_v=!_v:*'=!" From ae4a72036d4b6338769554e60871c4916b84fa9b Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Tue, 14 Sep 2021 19:14:44 -0600 Subject: [PATCH 06/40] Extract ERUNT before running --- scripts/wk/repairs/win.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/scripts/wk/repairs/win.py b/scripts/wk/repairs/win.py index 4eff3795..7024d902 100644 --- a/scripts/wk/repairs/win.py +++ b/scripts/wk/repairs/win.py @@ -25,7 +25,12 @@ from wk.io import ( non_clobber_path, rename_item, ) -from wk.kit.tools import download_tool, get_tool_path, run_tool +from wk.kit.tools import ( + download_tool, + extract_tool, + get_tool_path, + run_tool, + ) from wk.log import format_log_path, update_log_path from wk.os.win import ( get_timezone, @@ -926,7 +931,8 @@ def backup_registry(): """Backup Registry.""" backup_path = set_backup_path('Registry', date=True) backup_path.parent.mkdir(parents=True, exist_ok=True) - run_tool('Erunt', 'ERUNT', backup_path, 'sysreg', 'curuser', 'otherusers') + extract_tool('ERUNT') + run_tool('ERUNT', 'ERUNT', backup_path, 'sysreg', 'curuser', 'otherusers') def delete_registry_null_keys(): From e485cc96745cbd119bca30ef386e9f435b741aac Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Wed, 15 Sep 2021 09:18:02 -0600 Subject: [PATCH 07/40] Add Auto Setup scripts --- scripts/auto_setup.py | 176 +++++++++++++++++++++++++ scripts/wk/kit/tools.py | 3 +- scripts/wk/setup/win.py | 283 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 461 insertions(+), 1 deletion(-) create mode 100644 scripts/auto_setup.py create mode 100644 scripts/wk/setup/win.py diff --git a/scripts/auto_setup.py b/scripts/auto_setup.py new file mode 100644 index 00000000..8d87958a --- /dev/null +++ b/scripts/auto_setup.py @@ -0,0 +1,176 @@ +"""Wizard Kit: Auto System Setup Tool""" +# vim: sts=2 sw=2 ts=2 + +import os +import sys + +os.chdir(os.path.dirname(os.path.realpath(__file__))) +sys.path.append(os.getcwd()) +import wk # pylint: disable=wrong-import-position + + +# STATIC VARIABLES +PRESETS = { + 'Additional User': { + 'Configure System': ( + 'Chrome Notifications', + 'Open Shell', + 'uBlock Origin', + 'Enable BSoD MiniDumps', + 'Enable RegBack', + 'Enable System Restore', + 'Set System Restore Size', + 'Enable Windows Updates', + 'Windows Explorer', + ), + 'System Summary': ( + 'Operating System', + 'Windows Activation', + 'Secure Boot', + 'Installed RAM', + 'Storage Volumes', + 'Virus Protection', + 'Partitions 4K Aligned', + ), + }, + 'Hardware': { + 'Configure System': ( + 'Enable BSoD MiniDumps', + 'Enable RegBack', + 'Enable System Restore', + 'Set System Restore Size', + 'Enable Windows Updates', + ), + 'System Information': ( + 'Backup Registry', + ), + 'System Summary': ( + 'Operating System', + 'Windows Activation', + 'Secure Boot', + 'Installed RAM', + 'Storage Volumes', + 'Virus Protection', + 'Partitions 4K Aligned', + ), + 'Run Programs': ( + 'Device Manager', + 'HWiNFO Sensors', + 'XMPlay', + ), + }, + 'Verify': { + 'Configure System': ( + 'Enable BSoD MiniDumps', + 'Enable RegBack', + 'Enable System Restore', + 'Set System Restore Size', + 'Enable Windows Updates', + 'Windows Explorer', + ), + 'System Summary': ( + 'Operating System', + 'Windows Activation', + 'Secure Boot', + 'Installed RAM', + 'Storage Volumes', + 'Virus Protection', + 'Installed Office', + 'Partitions 4K Aligned', + ), + }, + } + +# Classes +class MenuEntry(): + # pylint: disable=too-few-public-methods + """Simple class to allow cleaner code below.""" + def __init__(self, name, function=None, **kwargs): + self.name = name + self.details = { + 'Function': function, + 'Selected': True, + **kwargs, + } + + +# TODO: DELETEME +def no_op(*args): + """No Op""" + +# STATIC VARIABLES +BASE_MENUS = { + 'Groups': { + 'Backup Settings': ( + # Add checks for existing backups and skip if detected + MenuEntry('Backup Browsers', 'auto_backup_browser_profiles'), + MenuEntry('Backup Power Plans', 'auto_backup_power_plans'), + MenuEntry('Reset Power Plans', 'auto_reset_power_plans'), + MenuEntry('Set Custom Power Plan', 'auto_set_custom_power_plan'), + ), + 'Install Software': ( + MenuEntry('Visual C++ Runtimes', no_op), # only 2012, 2013, & 2019 rest are EOL + #MenuEntry('ESET NOD32 Antivirus', no_op), + MenuEntry('LibreOffice', no_op), + MenuEntry('Open Shell Skin', no_op), + MenuEntry('uBlock Origin', no_op), + MenuEntry('Software Bundle', no_op), # include FF x32 -> x64 convertion? + ), + 'Configure System': ( + MenuEntry('Chrome Notifications', no_op), + #MenuEntry('O&O ShutUp 10', no_op), + MenuEntry('Open Shell', no_op), + MenuEntry('uBlock Origin', no_op), + #MenuEntry('Disable Fast Startup', no_op), + MenuEntry('Enable BSoD MiniDumps', no_op), + #MenuEntry('Enable Hibernation', no_op), + MenuEntry('Enable RegBack', 'auto_enable_regback'), + MenuEntry('Enable System Restore', 'auto_system_restore_enable'), + MenuEntry('Set System Restore Size', 'auto_system_restore_set_size'), + MenuEntry('Create System Restore', 'auto_system_restore_create'), + MenuEntry('Enable Windows Updates', 'auto_windows_updates_enable'), + MenuEntry('User Account Control', no_op), + MenuEntry('Windows Activation', no_op), + MenuEntry('Windows Explorer', no_op), + MenuEntry(r'Windows\Temp Fix', no_op), + ), + 'System Information': ( + MenuEntry('AIDA64 Reports', no_op), + MenuEntry('Backup Registry', 'auto_backup_registry'), + MenuEntry('Everything (File List)', no_op), + ), + 'System Summary': ( + MenuEntry('Operating System', no_op), + MenuEntry('Windows Activation', no_op), + MenuEntry('Secure Boot', no_op), + MenuEntry('Installed RAM', no_op), + MenuEntry('Storage Volumes', no_op), + MenuEntry('Virus Protection', no_op), + MenuEntry('Partitions 4K Aligned', no_op), + ), + 'Run Programs': ( + MenuEntry('Device Manager', no_op), + MenuEntry('HWiNFO Sensors', no_op), + #MenuEntry('Snappy Driver Installer', no_op), + MenuEntry('Windows Updates', no_op), + MenuEntry('Windows Activation', no_op), + MenuEntry('XMPlay', no_op), + ), + }, + 'Actions': ( + MenuEntry('Load Preset'), + MenuEntry('Start', Separator=True), + MenuEntry('Quit'), + ), + } + + +if __name__ == '__main__': + try: + wk.setup.win.run_auto_setup(BASE_MENUS, PRESETS) + except KeyboardInterrupt: + wk.std.abort() + except SystemExit: + raise + except: #pylint: disable=bare-except + wk.std.major_exception() diff --git a/scripts/wk/kit/tools.py b/scripts/wk/kit/tools.py index bed41823..092104ca 100644 --- a/scripts/wk/kit/tools.py +++ b/scripts/wk/kit/tools.py @@ -4,6 +4,7 @@ from datetime import datetime, timedelta import logging import pathlib +import platform import sys import requests @@ -15,7 +16,7 @@ from wk.std import GenericError # STATIC VARIABLES -ARCH = '64' if sys.maxsize > 2**32 else '32' +ARCH = '64' if platform.architecture()[0] == '64bit' else '32' LOG = logging.getLogger(__name__) diff --git a/scripts/wk/setup/win.py b/scripts/wk/setup/win.py new file mode 100644 index 00000000..0a28041d --- /dev/null +++ b/scripts/wk/setup/win.py @@ -0,0 +1,283 @@ +"""WizardKit: Setup - Windows""" +# vim: sts=2 sw=2 ts=2 + +import logging +import os +import platform +import re +import sys +import time + +from subprocess import CalledProcessError, DEVNULL + +from wk.cfg.main import KIT_NAME_FULL, KIT_NAME_SHORT +from wk.exe import ( + get_procs, + run_program, + popen_program, + wait_for_procs, + ) +from wk.io import ( + delete_folder, + get_path_obj, + non_clobber_path, + rename_item, + ) +from wk.kit.tools import ( + ARCH, + download_tool, + extract_tool, + get_tool_path, + run_tool, + ) +from wk.log import format_log_path, update_log_path +from wk.os.win import ( + reg_delete_value, + reg_read_value, + reg_set_value, + reg_write_settings, + disable_service, + enable_service, + stop_service, + ) +from wk.repairs.win import ( + auto_backup_registry, + auto_backup_browser_profiles, + auto_backup_power_plans, + auto_reset_power_plans, + auto_set_custom_power_plan, + auto_enable_regback, + auto_system_restore_enable, + auto_system_restore_set_size, + auto_system_restore_create, + auto_windows_updates_enable, + ) +from wk.std import ( + GenericError, + GenericWarning, + Menu, + TryAndPrint, + abort, + ask, + clear_screen, + color_string, + pause, + print_info, + print_standard, + print_warning, + set_title, + show_data, + sleep, + strip_colors, + ) + + +# STATIC VARIABLES +LOG = logging.getLogger(__name__) +CONEMU_EXE = get_tool_path('ConEmu', 'ConEmu', check=False) +IN_CONEMU = 'ConEmuPID' in os.environ +MENU_PRESETS = Menu() +PROGRAMFILES_32 = os.environ.get( + 'PROGRAMFILES(X86)', os.environ.get( + 'PROGRAMFILES', r'C:\Program Files (x86)', + ), + ) +OS_VERSION = float(platform.win32_ver()[0]) +SYSTEMDRIVE = os.environ.get('SYSTEMDRIVE', 'C:') +WIDTH = 50 +TRY_PRINT = TryAndPrint() +TRY_PRINT.width = WIDTH +TRY_PRINT.verbose = True +for error in ('CalledProcessError', 'FileNotFoundError'): + TRY_PRINT.add_error(error) + + +# Auto Setup +def build_menus(base_menus, title, presets): + """Build menus, returns dict.""" + menus = {} + menus['Main'] = Menu(title=f'{title}\n{color_string("Main Menu", "GREEN")}') + + # Main Menu + for entry in base_menus['Actions']: + menus['Main'].add_action(entry.name, entry.details) + for group in base_menus['Groups']: + menus['Main'].add_option(group, {'Selected': True}) + + # Run groups + for group, entries in base_menus['Groups'].items(): + menus[group] = Menu(title=f'{title}\n{color_string(group, "GREEN")}') + for entry in entries: + menus[group].add_option(entry.name, entry.details) + menus[group].add_action('All') + menus[group].add_action('None') + menus[group].add_action('Main Menu', {'Separator': True}) + menus[group].add_action('Quit') + + # Initialize main menu display names + menus['Main'].update() + + # Fix Function references + for group, menu in menus.items(): + if group not in base_menus['Groups']: + continue + for name in menu.options: + _function = menu.options[name]['Function'] + if isinstance(_function, str): + menu.options[name]['Function'] = getattr( + sys.modules[__name__], _function, + ) + + # Update presets Menu + MENU_PRESETS.title = f'{title}\n{color_string("Load Preset", "GREEN")}' + MENU_PRESETS.add_option('Default') + for name in presets: + MENU_PRESETS.add_option(name) + MENU_PRESETS.add_action('Main Menu') + MENU_PRESETS.add_action('Quit') + MENU_PRESETS.update() + + # Done + return menus + + +def load_preset(menus, presets): + """Load menu settings from preset.""" + selection = MENU_PRESETS.simple_select() + + # Exit early + if 'Main Menu' in selection: + return + if 'Quit' in selection: + raise SystemExit + + # Default case + if 'Default' in selection: + for menu in menus.values(): + for name in menu.options: + menu.options[name]['Selected'] = True + return + + # Load preset + preset = presets[selection[0]] + for group, menu in menus.items(): + group_enabled = group in preset + for name in menu.options: + value = group_enabled and name in preset[group] + menu.options[name]['Selected'] = value + + +def run_auto_setup(base_menus, presets): + """Run Auto Setup.""" + update_log_path(dest_name='Auto Setup', timestamp=True) + title = f'{KIT_NAME_FULL}: Auto Setup' + clear_screen() + set_title(title) + print_info(title) + print('') + + # Generate menus + print_standard('Initializing...') + menus = build_menus(base_menus, title, presets) + + # Show Menu + show_main_menu(base_menus, menus, presets) + + # Start setup + clear_screen() + print_standard(title) + print('') + print_info('Running setup') + + # Run setup + for group, menu in menus.items(): + if group in ('Main', 'Options'): + continue + try: + run_group(group, menu) + except KeyboardInterrupt: + abort() + + # Done + print_info('Done') + pause('Press Enter to exit...') + + +def run_group(group, menu): + """Run entries in group if appropriate.""" + print_info(f' {group}') + for name, details in menu.options.items(): + name_str = strip_colors(name) + + # Not selected + if not details.get('Selected', False): + show_data(f'{name_str}...', 'Skipped', 'YELLOW', width=WIDTH) + continue + + # Selected + details['Function'](group, name) + + +def show_main_menu(base_menus, menus, presets): + """Show main menu and handle actions.""" + while True: + update_main_menu(menus) + selection = menus['Main'].simple_select(update=False) + if selection[0] in base_menus['Groups'] or selection[0] == 'Options': + show_sub_menu(menus[selection[0]]) + if selection[0] == 'Load Preset': + load_preset(menus, presets) + elif 'Start' in selection: + break + elif 'Quit' in selection: + raise SystemExit + + +def show_sub_menu(menu): + """Show sub-menu and handle sub-menu actions.""" + while True: + selection = menu.advanced_select() + if 'Main Menu' in selection: + break + if 'Quit' in selection: + raise SystemExit + + # Select all or none + value = 'All' in selection + for name in menu.options: + if not menu.options[name].get('Disabled', False): + menu.options[name]['Selected'] = value + + +def update_main_menu(menus): + """Update main menu based on current selections.""" + index = 1 + skip = 'Reboot' + for name in menus['Main'].options: + checkmark = ' ' + selected = [ + _v['Selected'] for _k, _v in menus[name].options.items() if _k != skip + ] + if all(selected): + checkmark = '✓' + elif any(selected): + checkmark = '-' + display_name = f' {index}: [{checkmark}] {name}' + index += 1 + menus['Main'].options[name]['Display Name'] = display_name + + +# Auto Setup: Wrapper Functions +## TODO + +# Misc Functions +## TODO? + +# Tool Functions +## TODO? + +# OS Built-in Functions +## TODO? + +if __name__ == '__main__': + print("This file is not meant to be called directly.") From 673a92b3233df5e26a1984fe80a9de558ffbeb83 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Wed, 15 Sep 2021 09:19:15 -0600 Subject: [PATCH 08/40] Add install_vcredists() --- scripts/auto_setup.py | 2 +- scripts/wk/cfg/tools.py | 6 ++++++ scripts/wk/setup/__init__.py | 1 + scripts/wk/setup/win.py | 21 ++++++++++++++++++++- 4 files changed, 28 insertions(+), 2 deletions(-) diff --git a/scripts/auto_setup.py b/scripts/auto_setup.py index 8d87958a..73febb4b 100644 --- a/scripts/auto_setup.py +++ b/scripts/auto_setup.py @@ -109,7 +109,7 @@ BASE_MENUS = { MenuEntry('Set Custom Power Plan', 'auto_set_custom_power_plan'), ), 'Install Software': ( - MenuEntry('Visual C++ Runtimes', no_op), # only 2012, 2013, & 2019 rest are EOL + MenuEntry('Visual C++ Runtimes', 'auto_install_vcredists'), #MenuEntry('ESET NOD32 Antivirus', no_op), MenuEntry('LibreOffice', no_op), MenuEntry('Open Shell Skin', no_op), diff --git a/scripts/wk/cfg/tools.py b/scripts/wk/cfg/tools.py index 03eca518..7e7081cd 100644 --- a/scripts/wk/cfg/tools.py +++ b/scripts/wk/cfg/tools.py @@ -57,6 +57,12 @@ SOURCES = { 'smartmontools': 'https://1278-105252244-gh.circle-artifacts.com/0/builds/smartmontools-win32-setup-7.3-r5216.exe', 'TDSSKiller': 'https://media.kaspersky.com/utilities/VirusUtilities/EN/tdsskiller.exe', 'TestDisk': 'https://www.cgsecurity.org/testdisk-7.2-WIP.win.zip', + 'VCRedist_2012_x32': 'https://download.microsoft.com/download/1/6/B/16B06F60-3B20-4FF2-B699-5E9B7962F9AE/VSU_4/vcredist_x86.exe', + 'VCRedist_2012_x64': 'https://download.microsoft.com/download/1/6/B/16B06F60-3B20-4FF2-B699-5E9B7962F9AE/VSU_4/vcredist_x64.exe', + 'VCRedist_2013_x32': 'https://aka.ms/highdpimfc2013x86enu', + 'VCRedist_2013_x64': 'https://aka.ms/highdpimfc2013x64enu', + 'VCRedist_2019_x32': 'https://aka.ms/vs/16/release/vc_redist.x86.exe', + 'VCRedist_2019_x64': 'https://aka.ms/vs/16/release/vc_redist.x64.exe', 'wimlib32': 'https://wimlib.net/downloads/wimlib-1.13.3-windows-i686-bin.zip', 'wimlib64': 'https://wimlib.net/downloads/wimlib-1.13.3-windows-x86_64-bin.zip', 'WinAIO Repair': 'http://www.tweaking.com/files/setups/tweaking.com_windows_repair_aio.zip', diff --git a/scripts/wk/setup/__init__.py b/scripts/wk/setup/__init__.py index 33b5ea29..3e5683bb 100644 --- a/scripts/wk/setup/__init__.py +++ b/scripts/wk/setup/__init__.py @@ -5,3 +5,4 @@ import platform #if platform.system() == 'Windows': # from . import win +from . import win diff --git a/scripts/wk/setup/win.py b/scripts/wk/setup/win.py index 0a28041d..0c8a1685 100644 --- a/scripts/wk/setup/win.py +++ b/scripts/wk/setup/win.py @@ -268,7 +268,26 @@ def update_main_menu(menus): # Auto Setup: Wrapper Functions -## TODO +def auto_install_vcredists(): + """Install latest supported Visual C++ runtimes.""" + TRY_PRINT.run('Visual C++ Runtimes...', install_vcredists) + +# Install Functions +def install_vcredists(): + """Install latest supported Visual C++ runtimes.""" + for year in (2012, 2013, 2019): + cmd_args = ['/install', '/passive', '/norestart'] + if year == 2012: + cmd_args.pop(0) + name = f'VCRedist_{year}_x32' + download_tool('VCRedist', name) + installer = get_tool_path('VCRedist', name) + run_program([installer, *cmd_args]) + if ARCH == '64': + name = f'{name[:-2]}64' + download_tool('VCRedist', name) + installer = get_tool_path('VCRedist', name) + run_program([installer, *cmd_args]) # Misc Functions ## TODO? From 3d984f5f29301849a008846014fb06d981d73216 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Wed, 15 Sep 2021 09:58:01 -0600 Subject: [PATCH 09/40] Import standard repair functions instead of auto --- scripts/wk/repairs/win.py | 4 +- scripts/wk/setup/win.py | 79 +++++++++++++++++++++++++++++++++------ 2 files changed, 70 insertions(+), 13 deletions(-) diff --git a/scripts/wk/repairs/win.py b/scripts/wk/repairs/win.py index 7024d902..7f243bbd 100644 --- a/scripts/wk/repairs/win.py +++ b/scripts/wk/repairs/win.py @@ -777,7 +777,7 @@ def auto_restore_uac_defaults(group, name): def auto_set_custom_power_plan(group, name): - """Set to a custom power plan.""" + """Set custom power plan.""" result = TRY_PRINT.run('Set Custom Power Plan...', create_custom_power_plan) save_settings(group, name, result=result) @@ -789,7 +789,7 @@ def auto_sfc(group, name): def auto_system_restore_create(group, name): - """Create a System Restore point.""" + """Create System Restore point.""" result = TRY_PRINT.run( 'Create System Restore...', create_system_restore_point, ) diff --git a/scripts/wk/setup/win.py b/scripts/wk/setup/win.py index 0c8a1685..0cffef6f 100644 --- a/scripts/wk/setup/win.py +++ b/scripts/wk/setup/win.py @@ -41,16 +41,14 @@ from wk.os.win import ( stop_service, ) from wk.repairs.win import ( - auto_backup_registry, - auto_backup_browser_profiles, - auto_backup_power_plans, - auto_reset_power_plans, - auto_set_custom_power_plan, - auto_enable_regback, - auto_system_restore_enable, - auto_system_restore_set_size, - auto_system_restore_create, - auto_windows_updates_enable, + backup_all_browser_profiles, + backup_registry, + create_custom_power_plan, + create_system_restore_point, + enable_windows_updates, + export_power_plans, + reset_power_plans, + set_system_restore_size, ) from wk.std import ( GenericError, @@ -215,7 +213,7 @@ def run_group(group, menu): continue # Selected - details['Function'](group, name) + details['Function']() def show_main_menu(base_menus, menus, presets): @@ -267,6 +265,65 @@ def update_main_menu(menus): menus['Main'].options[name]['Display Name'] = display_name +# Auto Repairs: Wrapper Functions +def auto_backup_registry(): + """Backup registry.""" + TRY_PRINT.run('Backup Registry...', backup_registry) + + +def auto_backup_browser_profiles(): + """Backup browser profiles.""" + backup_all_browser_profiles(use_try_print=True) + + +def auto_backup_power_plans(): + """Backup power plans.""" + TRY_PRINT.run('Backup Power Plans...', export_power_plans) + + +def auto_reset_power_plans(): + """Reset power plans.""" + TRY_PRINT.run('Reset Power Plans...', reset_power_plans) + + +def auto_set_custom_power_plan(): + """Set custom power plan.""" + TRY_PRINT.run('Set Custom Power Plan...', create_custom_power_plan) + + +def auto_enable_regback(): + """Enable RegBack.""" + TRY_PRINT.run( + 'Enable RegBack...', reg_set_value, 'HKLM', + r'System\CurrentControlSet\Control\Session Manager\Configuration Manager', + 'EnablePeriodicBackup', 1, 'DWORD', + ) + + +def auto_system_restore_enable(): + """Enable System Restore.""" + cmd = [ + 'powershell', '-Command', 'Enable-ComputerRestore', + '-Drive', SYSTEMDRIVE, + ] + TRY_PRINT.run('Enable System Restore...', run_program, cmd=cmd) + + +def auto_system_restore_set_size(): + """Set System Restore size.""" + TRY_PRINT.run('Set System Restore Size...', set_system_restore_size) + + +def auto_system_restore_create(): + """Create System Restore point.""" + TRY_PRINT.run('Create System Restore...', create_system_restore_point) + + +def auto_windows_updates_enable(): + """Enable Windows Updates.""" + TRY_PRINT.run('Enable Windows Updates...', enable_windows_updates) + + # Auto Setup: Wrapper Functions def auto_install_vcredists(): """Install latest supported Visual C++ runtimes.""" From bec4ed520c5174ff3782349de265c6be82b1e8ae Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Wed, 15 Sep 2021 12:25:32 -0600 Subject: [PATCH 10/40] Add LibreOffice install sections --- scripts/auto_setup.py | 2 +- scripts/wk/setup/win.py | 47 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/scripts/auto_setup.py b/scripts/auto_setup.py index 73febb4b..92a68716 100644 --- a/scripts/auto_setup.py +++ b/scripts/auto_setup.py @@ -111,7 +111,7 @@ BASE_MENUS = { 'Install Software': ( MenuEntry('Visual C++ Runtimes', 'auto_install_vcredists'), #MenuEntry('ESET NOD32 Antivirus', no_op), - MenuEntry('LibreOffice', no_op), + MenuEntry('LibreOffice', 'auto_install_libreoffice'), MenuEntry('Open Shell Skin', no_op), MenuEntry('uBlock Origin', no_op), MenuEntry('Software Bundle', no_op), # include FF x32 -> x64 convertion? diff --git a/scripts/wk/setup/win.py b/scripts/wk/setup/win.py index 0cffef6f..2b1be61b 100644 --- a/scripts/wk/setup/win.py +++ b/scripts/wk/setup/win.py @@ -27,6 +27,7 @@ from wk.kit.tools import ( ARCH, download_tool, extract_tool, + find_kit_dir, get_tool_path, run_tool, ) @@ -74,6 +75,14 @@ from wk.std import ( LOG = logging.getLogger(__name__) CONEMU_EXE = get_tool_path('ConEmu', 'ConEmu', check=False) IN_CONEMU = 'ConEmuPID' in os.environ +LIBREOFFICE_XCU_DATA = ''' + +Impress MS PowerPoint 2007 XML +Calc MS Excel 2007 XML +MS Word 2007 XML +false + +''' MENU_PRESETS = Menu() PROGRAMFILES_32 = os.environ.get( 'PROGRAMFILES(X86)', os.environ.get( @@ -325,11 +334,49 @@ def auto_windows_updates_enable(): # Auto Setup: Wrapper Functions +def auto_install_libreoffice(): + """Install LibreOffice. + + NOTE: It is assumed that auto_install_vcredists() will be run + before this function to satisfy the vcredist=False usage. + """ + TRY_PRINT.run('LibreOffice...', install_libreoffice, vcredist=False) + + def auto_install_vcredists(): """Install latest supported Visual C++ runtimes.""" TRY_PRINT.run('Visual C++ Runtimes...', install_vcredists) # Install Functions +def install_libreoffice( + register_mso_types=True, use_mso_formats=False, vcredist=True): + """Install LibreOffice.""" + installer = find_kit_dir('Installers').joinpath('LibreOffice.msi') + xcu_dir = get_path_obj(f'{os.environ.get("APPDATA")}/LibreOffice/4/user') + xcu_file = xcu_dir.joinpath('registrymodifications.xcu') + + # Set default save formats to MSO types + if use_mso_formats and not xcu_file.exists(): + xcu_dir.mkdir(parents=True, exist_ok=True) + with open(xcu_file, 'w', encoding='utf-8', newline='\n') as _f: + _f.write(LIBREOFFICE_XCU_DATA) + + # Build cmd + cmd = [ + 'msiexec', '/passive', '/norestart', + '/i', installer, + 'REBOOTYESNO=No', + f'VC_REDIST={1 if vcredist else 0}', + ] + if register_mso_types: + cmd.append('REGISTER_ALL_MSO_TYPES=1') + else: + cmd.append('REGISTER_NO_MSO_TYPES=1') + + # Install LibreOffice + run_program(cmd) + + def install_vcredists(): """Install latest supported Visual C++ runtimes.""" for year in (2012, 2013, 2019): From 90f2a3753124af5ead2e0fe2c26ce65ab2a46427 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Wed, 15 Sep 2021 16:37:25 -0600 Subject: [PATCH 11/40] Rename wk/cfg/tools.py to wk/cfg/sources.py --- scripts/wk/cfg/__init__.py | 2 +- scripts/wk/cfg/{tools.py => sources.py} | 0 scripts/wk/kit/tools.py | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) rename scripts/wk/cfg/{tools.py => sources.py} (100%) diff --git a/scripts/wk/cfg/__init__.py b/scripts/wk/cfg/__init__.py index c3eb64da..bb77be75 100644 --- a/scripts/wk/cfg/__init__.py +++ b/scripts/wk/cfg/__init__.py @@ -5,5 +5,5 @@ from . import hw from . import log from . import main from . import net -from . import tools +from . import sources from . import ufd diff --git a/scripts/wk/cfg/tools.py b/scripts/wk/cfg/sources.py similarity index 100% rename from scripts/wk/cfg/tools.py rename to scripts/wk/cfg/sources.py diff --git a/scripts/wk/kit/tools.py b/scripts/wk/kit/tools.py index 092104ca..c3c5e75d 100644 --- a/scripts/wk/kit/tools.py +++ b/scripts/wk/kit/tools.py @@ -10,7 +10,7 @@ import sys import requests from wk.cfg.main import ARCHIVE_PASSWORD -from wk.cfg.tools import SOURCES, DOWNLOAD_FREQUENCY +from wk.cfg.sources import DOWNLOAD_FREQUENCY, SOURCES from wk.exe import popen_program, run_program from wk.std import GenericError From 38fd38f1ecbf6b5873115db6687b92b6e082821e Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Wed, 15 Sep 2021 16:38:11 -0600 Subject: [PATCH 12/40] Support suffixes other than exe for kit tools --- scripts/wk/kit/tools.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/scripts/wk/kit/tools.py b/scripts/wk/kit/tools.py index c3c5e75d..f86ef0ae 100644 --- a/scripts/wk/kit/tools.py +++ b/scripts/wk/kit/tools.py @@ -62,10 +62,10 @@ def download_file(out_path, source_url, as_new=False, overwrite=False): return out_path -def download_tool(folder, name): +def download_tool(folder, name, suffix=None): """Download tool.""" name_arch = f'{name}{ARCH}' - out_path = get_tool_path(folder, name, check=False) + out_path = get_tool_path(folder, name, check=False, suffix=suffix) up_to_date = False # Check if tool is up to date @@ -145,16 +145,18 @@ def find_kit_dir(name=None): return cur_path -def get_tool_path(folder, name, check=True): +def get_tool_path(folder, name, check=True, suffix=None): """Get tool path, returns pathlib.Path""" bin_dir = find_kit_dir('.bin') + if not suffix: + suffix = 'exe' name_arch = f'{name}{ARCH}' # "Search" - tool_path = bin_dir.joinpath(f'{folder}/{name_arch}.exe') + tool_path = bin_dir.joinpath(f'{folder}/{name_arch}.{suffix}') if not (tool_path.exists() or name_arch in SOURCES): # Use "default" path instead - tool_path = tool_path.with_name(f'{name}.exe') + tool_path = tool_path.with_name(f'{name}.{suffix}') # Missing? if check and not tool_path.exists(): From 578925cb704e6f8be95bec090c200cc5c5cf86d9 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Wed, 15 Sep 2021 18:02:36 -0600 Subject: [PATCH 13/40] Add Open-Shell install sections --- scripts/auto_setup.py | 4 +- scripts/wk/cfg/sources.py | 2 + scripts/wk/kit/tools.py | 1 - scripts/wk/os/win.py | 5 ++- scripts/wk/setup/win.py | 89 ++++++++++++++++++++++++++++++++++++++- 5 files changed, 96 insertions(+), 5 deletions(-) diff --git a/scripts/auto_setup.py b/scripts/auto_setup.py index 92a68716..578e565b 100644 --- a/scripts/auto_setup.py +++ b/scripts/auto_setup.py @@ -112,14 +112,14 @@ BASE_MENUS = { MenuEntry('Visual C++ Runtimes', 'auto_install_vcredists'), #MenuEntry('ESET NOD32 Antivirus', no_op), MenuEntry('LibreOffice', 'auto_install_libreoffice'), - MenuEntry('Open Shell Skin', no_op), + MenuEntry('Open Shell', 'auto_install_open_shell'), MenuEntry('uBlock Origin', no_op), MenuEntry('Software Bundle', no_op), # include FF x32 -> x64 convertion? ), 'Configure System': ( MenuEntry('Chrome Notifications', no_op), #MenuEntry('O&O ShutUp 10', no_op), - MenuEntry('Open Shell', no_op), + MenuEntry('Open Shell', 'auto_config_open_shell'), MenuEntry('uBlock Origin', no_op), #MenuEntry('Disable Fast Startup', no_op), MenuEntry('Enable BSoD MiniDumps', no_op), diff --git a/scripts/wk/cfg/sources.py b/scripts/wk/cfg/sources.py index 7e7081cd..e3caed0c 100644 --- a/scripts/wk/cfg/sources.py +++ b/scripts/wk/cfg/sources.py @@ -30,6 +30,7 @@ SOURCES = { 'Everything32': 'https://www.voidtools.com/Everything-1.4.1.1005.x86.en-US.zip', 'Everything64': 'https://www.voidtools.com/Everything-1.4.1.1005.x64.en-US.zip', 'FastCopy': 'https://ftp.vector.co.jp/73/10/2323/FastCopy392_installer.exe', + 'Fluent-Metro': 'https://github.com/bonzibudd/Fluent-Metro/releases/download/v1.5.2/Fluent-Metro_1.5.2.zip', 'FurMark': 'https://geeks3d.com/dl/get/569', 'Firefox uBO': 'https://addons.mozilla.org/firefox/downloads/file/3740966/ublock_origin-1.34.0-an+fx.xpi', 'HitmanPro': 'https://dl.surfright.nl/HitmanPro.exe', @@ -44,6 +45,7 @@ SOURCES = { 'NirCmd32': 'https://www.nirsoft.net/utils/nircmd.zip', 'NirCmd64': 'https://www.nirsoft.net/utils/nircmd-x64.zip', 'NotepadPlusPlus': 'https://github.com/notepad-plus-plus/notepad-plus-plus/releases/download/v7.9.5/npp.7.9.5.portable.minimalist.7z', + 'OpenShell': 'https://github.com/Open-Shell/Open-Shell-Menu/releases/download/v4.4.160/OpenShellSetup_4_4_160.exe', 'Office Deployment Tool': 'https://download.microsoft.com/download/2/7/A/27AF1BE6-DD20-4CB4-B154-EBAB8A7D4A7E/officedeploymenttool_11617-33601.exe', 'ProduKey32': 'http://www.nirsoft.net/utils/produkey.zip', 'ProduKey64': 'http://www.nirsoft.net/utils/produkey-x64.zip', diff --git a/scripts/wk/kit/tools.py b/scripts/wk/kit/tools.py index f86ef0ae..a0466d39 100644 --- a/scripts/wk/kit/tools.py +++ b/scripts/wk/kit/tools.py @@ -5,7 +5,6 @@ from datetime import datetime, timedelta import logging import pathlib import platform -import sys import requests diff --git a/scripts/wk/os/win.py b/scripts/wk/os/win.py index 0eb71971..82e768af 100644 --- a/scripts/wk/os/win.py +++ b/scripts/wk/os/win.py @@ -221,7 +221,10 @@ def reg_key_exists(hive, key): def reg_read_value(hive, key, value, force_32=False, force_64=False): - """Query value from hive/hey, returns multiple types.""" + """Query value from hive/hey, returns multiple types. + + NOTE: Set value='' to read the default value. + """ access = winreg.KEY_READ data = None hive = reg_get_hive(hive) diff --git a/scripts/wk/setup/win.py b/scripts/wk/setup/win.py index 2b1be61b..4d9bfcbf 100644 --- a/scripts/wk/setup/win.py +++ b/scripts/wk/setup/win.py @@ -26,6 +26,7 @@ from wk.io import ( from wk.kit.tools import ( ARCH, download_tool, + extract_archive, extract_tool, find_kit_dir, get_tool_path, @@ -84,12 +85,54 @@ LIBREOFFICE_XCU_DATA = ''' ''' MENU_PRESETS = Menu() +OS_VERSION = float(platform.win32_ver()[0]) PROGRAMFILES_32 = os.environ.get( 'PROGRAMFILES(X86)', os.environ.get( 'PROGRAMFILES', r'C:\Program Files (x86)', ), ) -OS_VERSION = float(platform.win32_ver()[0]) +PROGRAMFILES_64 = os.environ.get( + 'PROGRAMW6432', os.environ.get( + 'PROGRAMFILES', r'C:\Program Files', + ), + ) +REG_OPEN_SHELL_SETTINGS = { + 'HKCU': { + r'Software\OpenShell\StartMenu': ( + ('ShowedStyle2', 1, 'DWORD'), + ), + r'Software\OpenShell\StartMenu\Settings': ( + ('MenuStyle', 'Win7', 'SZ'), + ('RecentPrograms', 'Recent', 'SZ'), + ('SkinW7', 'Fluent-Metro', 'SZ'), + ('SkinVariationW7', '', 'SZ'), + ('SkipMetro', 1, 'DWORD'), + ( + 'SkinOptionsW7', + [ + # NOTE: Seems to need all options specified to work? + 'DARK_MAIN=1', 'METRO_MAIN=0', 'LIGHT_MAIN=0', 'AUTOMODE_MAIN=0', + 'DARK_SUBMENU=0', 'METRO_SUBMENU=0', 'LIGHT_SUBMENU=0', 'AUTOMODE_SUBMENU=1', + 'SUBMENU_SEPARATORS=1', 'DARK_SEARCH=0', 'METRO_SEARCH=0', 'LIGHT_SEARCH=1', + 'AUTOMODE_SEARCH=0', 'SEARCH_FRAME=1', 'SEARCH_COLOR=0', 'SMALL_SEARCH=0', + 'MODERN_SEARCH=1', 'SEARCH_ITALICS=0', 'NONE=0', 'SEPARATOR=0', + 'TWO_TONE=1', 'CLASSIC_SELECTOR=1', 'HALF_SELECTOR=0', 'CURVED_MENUSEL=1', + 'CURVED_SUBMENU=0', 'SELECTOR_REVEAL=0', 'TRANSPARENT=0', 'OPAQUE_SUBMENU=1', + 'OPAQUE_MENU=0', 'OPAQUE=0', 'STANDARD=1', 'SMALL_MAIN2=0', + 'SMALL_ICONS=0', 'COMPACT_SUBMENU=0', 'PRESERVE_MAIN2=0', 'LESS_PADDING=0', + 'EXTRA_PADDING=1', '24_PADDING=0', 'LARGE_PROGRAMS=0', 'TRANSPARENT_SHUTDOWN=0', + 'OUTLINE_SHUTDOWN=0', 'BUTTON_SHUTDOWN=1', 'EXPERIMENTAL_SHUTDOWN=0', 'LARGE_FONT=0', + 'CONNECTED_BORDER=1', 'FLOATING_BORDER=0', 'LARGE_SUBMENU=0', 'LARGE_LISTS=0', + 'THIN_MAIN2=0', 'EXPERIMENTAL_MAIN2=1', 'USER_IMAGE=1', 'USER_OUTSIDE=0', + 'SCALING_USER=1', '56=0', '64=0', 'TRANSPARENT_USER=0', + 'UWP_SCROLLBAR=1', 'MODERN_SCROLLBAR=0', 'OLD_ICONS=0', 'NEW_ICONS=1', + 'SMALL_ARROWS=0', 'ICON_FRAME=0', 'SEARCH_SEPARATOR=0', 'NO_PROGRAMS_BUTTON=0', + ], + 'MULTI_SZ', + ), + ), + }, + } SYSTEMDRIVE = os.environ.get('SYSTEMDRIVE', 'C:') WIDTH = 50 TRY_PRINT = TryAndPrint() @@ -334,6 +377,11 @@ def auto_windows_updates_enable(): # Auto Setup: Wrapper Functions +def auto_config_open_shell(): + """Configure Open Shell.""" + TRY_PRINT.run('Open Shell...', reg_write_settings, REG_OPEN_SHELL_SETTINGS) + + def auto_install_libreoffice(): """Install LibreOffice. @@ -343,10 +391,20 @@ def auto_install_libreoffice(): TRY_PRINT.run('LibreOffice...', install_libreoffice, vcredist=False) +def auto_install_open_shell(): + """Install Open Shell.""" + TRY_PRINT.run('Open Shell...', install_open_shell) + + def auto_install_vcredists(): """Install latest supported Visual C++ runtimes.""" TRY_PRINT.run('Visual C++ Runtimes...', install_vcredists) + +# Configure Functions +# TODO? + + # Install Functions def install_libreoffice( register_mso_types=True, use_mso_formats=False, vcredist=True): @@ -377,6 +435,34 @@ def install_libreoffice( run_program(cmd) +def install_open_shell(): + """Install Open Shell (just the Start Menu).""" + installer = get_tool_path('OpenShell', 'OpenShell', check=False) + download_tool('OpenShell', 'OpenShell') + download_tool('OpenShell', 'Fluent-Metro', suffix='zip') + cmd = [installer, '/qn', 'ADDLOCAL=StartMenu'] + run_program(cmd) + + # Install Skin + skin_zip = installer.with_name('Fluent-Metro.zip') + extract_archive(skin_zip, f'{PROGRAMFILES_64}/Open-Shell/Skins', '-aoa') + + # Add scheduled task to handle OS upgrades + cmd = ['schtasks', '/query', '/tn', 'Open-Shell OS upgrade check'] + proc = run_program(cmd, check=False) + if proc.returncode == 0: + # Task already exists, bail and leave current task unmodified + return + cmd = [ + 'schtasks', '/create', + '/ru', r'NT AUTHORITY\SYSTEM', + '/sc', 'ONSTART', + '/tn', 'Open-Shell OS upgrade check', + '/tr', r'"%PROGRAMFILES%\Open-Shell\StartMenu.exe" -upgrade -silent', + ] + run_program(cmd) + + def install_vcredists(): """Install latest supported Visual C++ runtimes.""" for year in (2012, 2013, 2019): @@ -393,6 +479,7 @@ def install_vcredists(): installer = get_tool_path('VCRedist', name) run_program([installer, *cmd_args]) + # Misc Functions ## TODO? From 14ff5a943769db31ff5a7afb8e477043a1d08a8c Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Sat, 18 Sep 2021 16:11:09 -0600 Subject: [PATCH 14/40] Add Firefox and uBlock Origin sections --- scripts/auto_setup.py | 8 ++- scripts/wk/cfg/sources.py | 3 +- scripts/wk/setup/win.py | 138 +++++++++++++++++++++++++++++++++++++- 3 files changed, 145 insertions(+), 4 deletions(-) diff --git a/scripts/auto_setup.py b/scripts/auto_setup.py index 578e565b..f05fe61c 100644 --- a/scripts/auto_setup.py +++ b/scripts/auto_setup.py @@ -23,6 +23,9 @@ PRESETS = { 'Enable Windows Updates', 'Windows Explorer', ), + 'Install Software': ( + 'Firefox', # Needed to handle profile upgrade nonsense + ), 'System Summary': ( 'Operating System', 'Windows Activation', @@ -111,10 +114,11 @@ BASE_MENUS = { 'Install Software': ( MenuEntry('Visual C++ Runtimes', 'auto_install_vcredists'), #MenuEntry('ESET NOD32 Antivirus', no_op), + MenuEntry('Firefox', 'auto_install_firefox'), MenuEntry('LibreOffice', 'auto_install_libreoffice'), MenuEntry('Open Shell', 'auto_install_open_shell'), - MenuEntry('uBlock Origin', no_op), - MenuEntry('Software Bundle', no_op), # include FF x32 -> x64 convertion? + MenuEntry('uBlock Origin', 'auto_install_ublock_origin'), + MenuEntry('Software Bundle', no_op), ), 'Configure System': ( MenuEntry('Chrome Notifications', no_op), diff --git a/scripts/wk/cfg/sources.py b/scripts/wk/cfg/sources.py index e3caed0c..5ee9a483 100644 --- a/scripts/wk/cfg/sources.py +++ b/scripts/wk/cfg/sources.py @@ -32,7 +32,8 @@ SOURCES = { 'FastCopy': 'https://ftp.vector.co.jp/73/10/2323/FastCopy392_installer.exe', 'Fluent-Metro': 'https://github.com/bonzibudd/Fluent-Metro/releases/download/v1.5.2/Fluent-Metro_1.5.2.zip', 'FurMark': 'https://geeks3d.com/dl/get/569', - 'Firefox uBO': 'https://addons.mozilla.org/firefox/downloads/file/3740966/ublock_origin-1.34.0-an+fx.xpi', + 'Firefox32': 'https://download.mozilla.org/?product=firefox-latest-ssl&os=win&lang=en-US', + 'Firefox64': 'https://download.mozilla.org/?product=firefox-latest-ssl&os=win64&lang=en-US', 'HitmanPro': 'https://dl.surfright.nl/HitmanPro.exe', 'HitmanPro64': 'https://dl.surfright.nl/HitmanPro_x64.exe', 'HWiNFO': 'https://files1.majorgeeks.com/c8a055180587599139f8f454712dcc618cd1740e/systeminfo/hwi_702.zip', diff --git a/scripts/wk/setup/win.py b/scripts/wk/setup/win.py index 4d9bfcbf..ad5a44f6 100644 --- a/scripts/wk/setup/win.py +++ b/scripts/wk/setup/win.py @@ -1,7 +1,9 @@ """WizardKit: Setup - Windows""" # vim: sts=2 sw=2 ts=2 +import configparser import logging +import json import os import platform import re @@ -13,11 +15,13 @@ from subprocess import CalledProcessError, DEVNULL from wk.cfg.main import KIT_NAME_FULL, KIT_NAME_SHORT from wk.exe import ( get_procs, + kill_procs, run_program, popen_program, wait_for_procs, ) from wk.io import ( + case_insensitive_path, delete_folder, get_path_obj, non_clobber_path, @@ -96,6 +100,13 @@ PROGRAMFILES_64 = os.environ.get( 'PROGRAMFILES', r'C:\Program Files', ), ) +REG_CHROME_UBLOCK_ORIGIN = { + 'HKLM': { + r'Software\Google\Chrome\Extensions\cjpalhdlnbpafiamejdnhcphjbkeiagm': ( + ('update_url', 'https://clients2.google.com/service/update2/crx', 'SZ', '32'), + ) + }, + } REG_OPEN_SHELL_SETTINGS = { 'HKCU': { r'Software\OpenShell\StartMenu': ( @@ -382,6 +393,11 @@ def auto_config_open_shell(): TRY_PRINT.run('Open Shell...', reg_write_settings, REG_OPEN_SHELL_SETTINGS) +def auto_install_firefox(): + """Install Firefox.""" + TRY_PRINT.run('Firefox...', install_firefox) + + def auto_install_libreoffice(): """Install LibreOffice. @@ -396,6 +412,13 @@ def auto_install_open_shell(): TRY_PRINT.run('Open Shell...', install_open_shell) +def auto_install_ublock_origin(): + """Update the registry to auto-add uBlock Origin to Chrome.""" + TRY_PRINT.run( + 'uBlock Origin...', reg_write_settings, REG_CHROME_UBLOCK_ORIGIN, + ) + + def auto_install_vcredists(): """Install latest supported Visual C++ runtimes.""" TRY_PRINT.run('Visual C++ Runtimes...', install_vcredists) @@ -406,6 +429,77 @@ def auto_install_vcredists(): # Install Functions +def install_firefox(): + """Install Firefox. + + As far as I can tell if you use the EXE installers then it will use + the same installation directory as the installed version. As such a + 32-bit installation could be upgraded to a 64-bit one and still use + %PROGRAMFILES(X86)% However, if a 64-bit MSI installer is used then + it ignores the 32-bit directory and just installs a new copy to + %PROGRAMFILES% resulting in two copies of Firefox to be in place. + To address this issue this function will uninstall all copies of + Firefox under 64-bit Windows if it's detected in %PROGRAMFILES(X86)% + before installing the latest 64-bit version. + + Firefox 67 changed how profiles are named to avoid reusing the same + profile between different channels of Firefox (std, beta, ESR, etc). + However the logic used when upgrading from versions before 67 to + current isn't ideal. It can, but doesn't always?, create a new + profile and set it as default; even if there's an existing profile + being used. To address this profiles.ini is read to compare with the + post-install/upgrade state. If the default is changed to a new + profile then it is reverted so the original existing profile instead. + """ + current_default_profile = None + firefox_exe = f'{os.environ["PROGRAMFILES"]}/Mozilla Firefox/firefox.exe' + profiles_ini = case_insensitive_path( + f'{os.environ["APPDATA"]}/Mozilla/Firefox/profiles.ini', + ) + program_path_32bit_exists = False + try: + case_insensitive_path( + f'{PROGRAMFILES_32}/Mozilla Firefox/firefox.exe', + ) + except FileNotFoundError: + # Ignore + pass + else: + program_path_32bit_exists = True + revert_default = False + + # Save current default profile + if profiles_ini.exists(): + current_default_profile = get_firefox_default_profile(profiles_ini) + + # Uninstall Firefox if needed + if ARCH == '64' and program_path_32bit_exists: + uninstall_firefox() + + # Install Firefox + run_tool('Firefox', 'Firefox', '/S', download=True) + + # Open Firefox to force profiles.ini update + popen_program(firefox_exe) + sleep(5) + kill_procs('firefox.exe', force=True) + + # Check if default profile changed + if current_default_profile: + new_default = get_firefox_default_profile(profiles_ini) + revert_default = new_default and new_default != current_default_profile + + # Revert default profile if needed + if revert_default: + out = [] + for line in profiles_ini.read_text().splitlines(): + if 'Default=Profile' in line: + out.append(f'Default={current_default_profile}') + else: + out.append(line) + profiles_ini.write_text('\n'.join(out)) + + def install_libreoffice( register_mso_types=True, use_mso_formats=False, vcredist=True): """Install LibreOffice.""" @@ -480,8 +574,50 @@ def install_vcredists(): run_program([installer, *cmd_args]) +def uninstall_firefox(): + """Uninstall all copies of Firefox.""" + json_file = format_log_path(log_name='Installed Programs', timestamp=True) + json_file = json_file.with_name(f'{json_file.stem}.json') + uninstall_data = None + + # Get uninstall_data from UninstallView + extract_tool('UninstallView') + cmd = [get_tool_path('UninstallView', 'UninstallView'), '/sjson', json_file] + run_program(cmd) + with open(json_file, 'rb') as _f: + uninstall_data = json.load(_f) + + # Uninstall Firefox if found + for item in uninstall_data: + if item['Display Name'].lower().startswith('mozilla firefox'): + uninstaller = item['Uninstall String'].replace('"', '') + run_program([uninstaller, '/S']) + + # Misc Functions -## TODO? +def get_firefox_default_profile(profiles_ini): + """Get Firefox default profile, returns pathlib.Path or None.""" + default_profile = None + parser = None + + # Bail early + if not profiles_ini.exists(): + return None + + # Parse INI + parser = configparser.ConfigParser() + parser.read(profiles_ini) + for section in parser.sections(): + if section.lower().startswith('install'): + default_profile = parser[section].get('default') + break + value = parser[section].get('default') + if value and value == '1': + default_profile = parser[section].get('path') + + # Done + return default_profile + # Tool Functions ## TODO? From b05835d80f5a478f4638d3afb5295d5e2a2e4d00 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Sat, 25 Sep 2021 20:35:47 -0600 Subject: [PATCH 15/40] Enable uBlock Origin in more browsers --- scripts/auto_setup.py | 3 +- scripts/wk/setup/win.py | 63 +++++++++++++++++++++++++++++++++++------ 2 files changed, 56 insertions(+), 10 deletions(-) diff --git a/scripts/auto_setup.py b/scripts/auto_setup.py index f05fe61c..a994fe2a 100644 --- a/scripts/auto_setup.py +++ b/scripts/auto_setup.py @@ -117,14 +117,13 @@ BASE_MENUS = { MenuEntry('Firefox', 'auto_install_firefox'), MenuEntry('LibreOffice', 'auto_install_libreoffice'), MenuEntry('Open Shell', 'auto_install_open_shell'), - MenuEntry('uBlock Origin', 'auto_install_ublock_origin'), MenuEntry('Software Bundle', no_op), ), 'Configure System': ( MenuEntry('Chrome Notifications', no_op), #MenuEntry('O&O ShutUp 10', no_op), MenuEntry('Open Shell', 'auto_config_open_shell'), - MenuEntry('uBlock Origin', no_op), + MenuEntry('uBlock Origin', 'auto_enable_ublock_origin'), #MenuEntry('Disable Fast Startup', no_op), MenuEntry('Enable BSoD MiniDumps', no_op), #MenuEntry('Enable Hibernation', no_op), diff --git a/scripts/wk/setup/win.py b/scripts/wk/setup/win.py index ad5a44f6..0747cf8d 100644 --- a/scripts/wk/setup/win.py +++ b/scripts/wk/setup/win.py @@ -78,6 +78,13 @@ from wk.std import ( # STATIC VARIABLES LOG = logging.getLogger(__name__) +BROWSER_PATHS = { + # Relative to PROGRAMFILES_64, PROGRAMFILES_32, LOCALAPPDATA (in that order) + 'Google Chrome': 'Google/Chrome/Application/chrome.exe', + 'Mozilla Firefox': 'Mozilla Firefox/firefox.exe', + 'Microsoft Edge': 'Microsoft/Edge/Application/msedge.exe', + 'Opera': 'Opera/launcher.exe', + } CONEMU_EXE = get_tool_path('ConEmu', 'ConEmu', check=False) IN_CONEMU = 'ConEmuPID' in os.environ LIBREOFFICE_XCU_DATA = ''' @@ -151,6 +158,13 @@ TRY_PRINT.width = WIDTH TRY_PRINT.verbose = True for error in ('CalledProcessError', 'FileNotFoundError'): TRY_PRINT.add_error(error) +UBLOCK_ORIGIN_URLS = { + # pylint: disable=line-too-long + 'Google Chrome': 'https://chrome.google.com/webstore/detail/ublock-origin/cjpalhdlnbpafiamejdnhcphjbkeiagm', + 'Microsoft Edge': 'https://microsoftedge.microsoft.com/addons/detail/ublock-origin/odfafepnkmbhccpbejgmiehpchacaeak', + 'Mozilla Firefox': 'https://addons.mozilla.org/addon/ublock-origin/', + 'Opera': 'https://addons.opera.com/extensions/details/ublock/', + } # Auto Setup @@ -393,6 +407,19 @@ def auto_config_open_shell(): TRY_PRINT.run('Open Shell...', reg_write_settings, REG_OPEN_SHELL_SETTINGS) +def auto_enable_ublock_origin(): + """Enable uBlock Origin in supported browsers.""" + prompt = ' Press Enter to continue...' + TRY_PRINT.run( + 'uBlock Origin...', enable_ublock_origin, msg_good='STARTED', + ) + print(prompt, end='', flush=True) + pause('') + + # Move cursor to beginning of the previous line and clear prompt + print(f'\033[F\r{" "*len(prompt)}\r', end='', flush=True) + + def auto_install_firefox(): """Install Firefox.""" TRY_PRINT.run('Firefox...', install_firefox) @@ -412,20 +439,40 @@ def auto_install_open_shell(): TRY_PRINT.run('Open Shell...', install_open_shell) -def auto_install_ublock_origin(): - """Update the registry to auto-add uBlock Origin to Chrome.""" - TRY_PRINT.run( - 'uBlock Origin...', reg_write_settings, REG_CHROME_UBLOCK_ORIGIN, - ) - - def auto_install_vcredists(): """Install latest supported Visual C++ runtimes.""" TRY_PRINT.run('Visual C++ Runtimes...', install_vcredists) # Configure Functions -# TODO? +def enable_ublock_origin(): + """Enable uBlock Origin in supported browsers.""" + base_paths = [ + PROGRAMFILES_64, PROGRAMFILES_32, os.environ.get('LOCALAPPDATA'), + ] + cmds = [] + + # Add Google Chrome registry entries + reg_write_settings(REG_CHROME_UBLOCK_ORIGIN) + + # Build cmds list + for browser, rel_path in BROWSER_PATHS.items(): + browser_path = None + for base_path in base_paths: + try: + browser_path = case_insensitive_path(f'{base_path}/{rel_path}') + except FileNotFoundError: + # Ignore missing browsers + continue + else: + # Found a match, skip checking the rest + break + if browser_path: + cmds.append([browser_path, UBLOCK_ORIGIN_URLS[browser]]) + + # Open detected browsers + for cmd in cmds: + popen_program(cmd) # Install Functions From 68d8e292cca960b4622f2f0fa4d0f9f11966f23b Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Sat, 25 Sep 2021 20:37:39 -0600 Subject: [PATCH 16/40] Restrict OpenShell installs to Windows 10 --- scripts/wk/setup/win.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/scripts/wk/setup/win.py b/scripts/wk/setup/win.py index 0747cf8d..c5311ad0 100644 --- a/scripts/wk/setup/win.py +++ b/scripts/wk/setup/win.py @@ -96,7 +96,9 @@ LIBREOFFICE_XCU_DATA = ''' ''' MENU_PRESETS = Menu() -OS_VERSION = float(platform.win32_ver()[0]) +OS_VERSION = -1 +if platform.system() == 'Windows': + OS_VERSION = float(platform.win32_ver()[0]) PROGRAMFILES_32 = os.environ.get( 'PROGRAMFILES(X86)', os.environ.get( 'PROGRAMFILES', r'C:\Program Files (x86)', @@ -579,6 +581,12 @@ def install_libreoffice( def install_open_shell(): """Install Open Shell (just the Start Menu).""" installer = get_tool_path('OpenShell', 'OpenShell', check=False) + + # Bail early + if OS_VERSION != 10: + raise GenericWarning('Unsupported OS') + + # Install OpenShell download_tool('OpenShell', 'OpenShell') download_tool('OpenShell', 'Fluent-Metro', suffix='zip') cmd = [installer, '/qn', 'ADDLOCAL=StartMenu'] From 49d7e6d78ac7d0572e609eafee5ed8a37211e9cd Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Sat, 25 Sep 2021 20:39:08 -0600 Subject: [PATCH 17/40] Misc updates --- scripts/wk/kit/tools.py | 6 +++--- scripts/wk/kit/ufd.py | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/wk/kit/tools.py b/scripts/wk/kit/tools.py index a0466d39..5e888a3f 100644 --- a/scripts/wk/kit/tools.py +++ b/scripts/wk/kit/tools.py @@ -27,10 +27,10 @@ CACHED_DIRS = {} def download_file(out_path, source_url, as_new=False, overwrite=False): """Download a file using requests, returns pathlib.Path.""" out_path = pathlib.Path(out_path).resolve() + download_msg = f'Downloading {out_path.name}...' if as_new: out_path = out_path.with_suffix(f'{out_path.suffix}.new') - cursor_left = '\u001B[14D' - print(f'Downloading...{cursor_left}', end='', flush=True) + print(download_msg, end='', flush=True) # Avoid clobbering if out_path.exists() and not overwrite: @@ -57,7 +57,7 @@ def download_file(out_path, source_url, as_new=False, overwrite=False): _f.write(chunk) # Done - print(f' {cursor_left}', end='', flush=True) + print(f'\r{" "*len(download_msg)}\r', end='', flush=True) return out_path diff --git a/scripts/wk/kit/ufd.py b/scripts/wk/kit/ufd.py index 5b700b6a..e1f7ee7a 100644 --- a/scripts/wk/kit/ufd.py +++ b/scripts/wk/kit/ufd.py @@ -153,7 +153,7 @@ def build_ufd(): ) for s_label, s_path in sources.items(): try_print.run( - message='Copying {}...'.format(s_label), + message=f'Copying {s_label}...', function=copy_source, source=s_path, items=ITEMS[s_label], From a03d772788846e4154a02e477ced193a7169b767 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Mon, 27 Sep 2021 16:41:57 -0600 Subject: [PATCH 18/40] Add software bundle sections --- scripts/auto_setup.py | 2 +- scripts/wk/cfg/sources.py | 1 + scripts/wk/kit/tools.py | 2 +- scripts/wk/setup/win.py | 30 ++++++++++++++++++++++++++++++ scripts/wk/std.py | 6 +++--- 5 files changed, 36 insertions(+), 5 deletions(-) diff --git a/scripts/auto_setup.py b/scripts/auto_setup.py index a994fe2a..9db1d1c4 100644 --- a/scripts/auto_setup.py +++ b/scripts/auto_setup.py @@ -117,7 +117,7 @@ BASE_MENUS = { MenuEntry('Firefox', 'auto_install_firefox'), MenuEntry('LibreOffice', 'auto_install_libreoffice'), MenuEntry('Open Shell', 'auto_install_open_shell'), - MenuEntry('Software Bundle', no_op), + MenuEntry('Software Bundle', 'auto_install_software_bundle'), ), 'Configure System': ( MenuEntry('Chrome Notifications', no_op), diff --git a/scripts/wk/cfg/sources.py b/scripts/wk/cfg/sources.py index 5ee9a483..518b18e6 100644 --- a/scripts/wk/cfg/sources.py +++ b/scripts/wk/cfg/sources.py @@ -56,6 +56,7 @@ SOURCES = { 'Samsung Magician': 'https://s3.ap-northeast-2.amazonaws.com/global.semi.static/SAMSUNG_SSD_v5_3_0_181121/CD0C7CC1BE00525FAC4675B9E502899B41D5C3909ECE3AA2FB6B74A766B2A1EA/Samsung_Magician_Installer.zip', 'SDIO Themes': 'http://snappy-driver-installer.org/downloads/SDIO_Themes.zip', 'SDIO Torrent': 'http://snappy-driver-installer.org/downloads/SDIO_Update.torrent', + 'Software Bundle': 'https://ninite.com/.net4.8-7zip-chrome-edge-vlc/ninite.exe', 'ShutUp10': 'https://dl5.oo-software.com/files/ooshutup10/OOSU10.exe', 'smartmontools': 'https://1278-105252244-gh.circle-artifacts.com/0/builds/smartmontools-win32-setup-7.3-r5216.exe', 'TDSSKiller': 'https://media.kaspersky.com/utilities/VirusUtilities/EN/tdsskiller.exe', diff --git a/scripts/wk/kit/tools.py b/scripts/wk/kit/tools.py index 5e888a3f..50a98059 100644 --- a/scripts/wk/kit/tools.py +++ b/scripts/wk/kit/tools.py @@ -57,7 +57,7 @@ def download_file(out_path, source_url, as_new=False, overwrite=False): _f.write(chunk) # Done - print(f'\r{" "*len(download_msg)}\r', end='', flush=True) + print(f'\033[{len(download_msg)}D\033[0K', end='', flush=True) return out_path diff --git a/scripts/wk/setup/win.py b/scripts/wk/setup/win.py index c5311ad0..5b54da1d 100644 --- a/scripts/wk/setup/win.py +++ b/scripts/wk/setup/win.py @@ -441,6 +441,11 @@ def auto_install_open_shell(): TRY_PRINT.run('Open Shell...', install_open_shell) +def auto_install_software_bundle(): + """Install standard software bundle.""" + TRY_PRINT.run('Software Bundle...', install_software_bundle) + + def auto_install_vcredists(): """Install latest supported Visual C++ runtimes.""" TRY_PRINT.run('Visual C++ Runtimes...', install_vcredists) @@ -612,6 +617,31 @@ def install_open_shell(): run_program(cmd) +def install_software_bundle(): + """Install standard software bundle.""" + download_tool('Ninite', 'Software Bundle') + installer = get_tool_path('Ninite', 'Software Bundle') + msg = 'Waiting for installations to finish...' + warning = 'NOTE: Press CTRL+c to manually resume if it gets stuck...' + + # Start installations and wait for them to finish + print_standard(msg) + print_warning(warning, end='', flush=True) + proc = popen_program([installer]) + try: + proc.wait() + except KeyboardInterrupt: + # Assuming user-forced continue + pass + + # Clear info lines + print( + '\r\033[0K' # Cursor to start of current line and clear to end of line + '\033[F\033[54C' # Cursor to start of prev line and then move 54 right + '\033[0K', # Clear from cursor to end of line + end='', flush=True) + + def install_vcredists(): """Install latest supported Visual C++ runtimes.""" for year in (2012, 2013, 2019): diff --git a/scripts/wk/std.py b/scripts/wk/std.py index 919c73a4..958d275f 100644 --- a/scripts/wk/std.py +++ b/scripts/wk/std.py @@ -588,11 +588,11 @@ class TryAndPrint(): verbose, ) f_exception = None - catch_all = catch_all if catch_all else self.catch_all - msg_good = msg_good if msg_good else self.msg_good + catch_all = catch_all if catch_all is not None else self.catch_all + msg_good = msg_good if msg_good is not None else self.msg_good output = None result_msg = 'UNKNOWN' - verbose = verbose if verbose else self.verbose + verbose = verbose if verbose is not None else self.verbose # Build exception tuples e_exceptions = tuple(self._get_exception(e) for e in self.list_errors) From b61f243cc86b42966368dcd552b30af19d6d8ec3 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Mon, 27 Sep 2021 16:51:01 -0600 Subject: [PATCH 19/40] Disable display sleep only during auto-repairs --- scripts/wk/repairs/win.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/scripts/wk/repairs/win.py b/scripts/wk/repairs/win.py index 7f243bbd..1f805722 100644 --- a/scripts/wk/repairs/win.py +++ b/scripts/wk/repairs/win.py @@ -778,7 +778,10 @@ def auto_restore_uac_defaults(group, name): def auto_set_custom_power_plan(group, name): """Set custom power plan.""" - result = TRY_PRINT.run('Set Custom Power Plan...', create_custom_power_plan) + result = TRY_PRINT.run( + 'Set Custom Power Plan...', create_custom_power_plan, + keep_display_on=True, + ) save_settings(group, name, result=result) @@ -1082,7 +1085,7 @@ def run_tdsskiller(): # OS Built-in Functions -def create_custom_power_plan(): +def create_custom_power_plan(keep_display_on=False): """Create new power plan and set as active.""" custom_guid = POWER_PLANS['Custom'] @@ -1102,9 +1105,10 @@ def create_custom_power_plan(): run_program(cmd) # Keep the display on - for setting in ('monitor-timeout-ac', 'monitor-timeout-dc'): - cmd = ['powercfg', '-Change', setting, '0'] - run_program(cmd) + if keep_display_on: + for setting in ('monitor-timeout-ac', 'monitor-timeout-dc'): + cmd = ['powercfg', '-Change', setting, '0'] + run_program(cmd) # Set CPU min state for arg in ('-SetacValueIndex', '-SetdcValueIndex'): From cb3ec42b92c4586cf3cc870c11765655c33ce1ef Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Mon, 27 Sep 2021 18:41:34 -0600 Subject: [PATCH 20/40] Add functions to disable Chrome notifications --- scripts/auto_setup.py | 2 +- scripts/wk/setup/win.py | 48 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/scripts/auto_setup.py b/scripts/auto_setup.py index 9db1d1c4..2f4311ea 100644 --- a/scripts/auto_setup.py +++ b/scripts/auto_setup.py @@ -120,7 +120,7 @@ BASE_MENUS = { MenuEntry('Software Bundle', 'auto_install_software_bundle'), ), 'Configure System': ( - MenuEntry('Chrome Notifications', no_op), + MenuEntry('Chrome Notifications', 'auto_disable_chrome_notifications'), #MenuEntry('O&O ShutUp 10', no_op), MenuEntry('Open Shell', 'auto_config_open_shell'), MenuEntry('uBlock Origin', 'auto_enable_ublock_origin'), diff --git a/scripts/wk/setup/win.py b/scripts/wk/setup/win.py index 5b54da1d..bcfcddfb 100644 --- a/scripts/wk/setup/win.py +++ b/scripts/wk/setup/win.py @@ -409,6 +409,11 @@ def auto_config_open_shell(): TRY_PRINT.run('Open Shell...', reg_write_settings, REG_OPEN_SHELL_SETTINGS) +def auto_disable_chrome_notifications(): + """Disable notifications in Google Chrome.""" + TRY_PRINT.run('Chrome Notifications...', disable_chrome_notifications) + + def auto_enable_ublock_origin(): """Enable uBlock Origin in supported browsers.""" prompt = ' Press Enter to continue...' @@ -452,6 +457,49 @@ def auto_install_vcredists(): # Configure Functions +def disable_chrome_notifications(): + """Disable notifications in Google Chrome.""" + defaults_key = 'default_content_setting_values' + profiles = [] + search_path = case_insensitive_path( + f'{os.environ.get("LOCALAPPDATA")}/Google/Chrome/User Data', + ) + + # Bail early + if not search_path: + raise GenericWarning('No profiles detected.') + + # Close any running instances of Chrome + kill_procs('chrome.exe', force=True) + + # Build list of profiles + for item in search_path.iterdir(): + if not item.is_dir(): + continue + + if re.match(r'^(Default|Profile).*', item.name, re.IGNORECASE): + profiles.append(item) + + # Bail if no profiles were detected + if not profiles: + raise GenericWarning('No profiles detected.') + + # Set notifications preference + for profile in profiles: + pref_file = profile.joinpath('Preferences') + if not pref_file.exists(): + continue + + # Update config + pref_data = json.loads(pref_file.read_text()) + if defaults_key not in pref_data['profile']: + pref_data['profile'][defaults_key] = {} + pref_data['profile'][defaults_key]['notifications'] = 2 + + # Save file + pref_file.write_text(json.dumps(pref_data, separators=(',', ':'))) + + def enable_ublock_origin(): """Enable uBlock Origin in supported browsers.""" base_paths = [ From 7009a074c7c0fe66ed8eaba46329ba8edaaa9698 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Mon, 27 Sep 2021 19:30:12 -0600 Subject: [PATCH 21/40] Add BSoD minidump sections --- scripts/auto_setup.py | 2 +- scripts/wk/setup/win.py | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/scripts/auto_setup.py b/scripts/auto_setup.py index 2f4311ea..8bf6fee0 100644 --- a/scripts/auto_setup.py +++ b/scripts/auto_setup.py @@ -125,7 +125,7 @@ BASE_MENUS = { MenuEntry('Open Shell', 'auto_config_open_shell'), MenuEntry('uBlock Origin', 'auto_enable_ublock_origin'), #MenuEntry('Disable Fast Startup', no_op), - MenuEntry('Enable BSoD MiniDumps', no_op), + MenuEntry('Enable BSoD MiniDumps', 'auto_enable_bsod_minidumps'), #MenuEntry('Enable Hibernation', no_op), MenuEntry('Enable RegBack', 'auto_enable_regback'), MenuEntry('Enable System Restore', 'auto_system_restore_enable'), diff --git a/scripts/wk/setup/win.py b/scripts/wk/setup/win.py index bcfcddfb..1f80ff99 100644 --- a/scripts/wk/setup/win.py +++ b/scripts/wk/setup/win.py @@ -370,6 +370,12 @@ def auto_set_custom_power_plan(): TRY_PRINT.run('Set Custom Power Plan...', create_custom_power_plan) +def auto_enable_bsod_minidumps(): + """Enable saving minidumps during BSoDs.""" + cmd = ['wmic', 'RECOVEROS', 'set', 'DebugInfoType', '=', '3'] + TRY_PRINT.run('Enable BSoD mini dumps...', enable_bsod_minidumps) + + def auto_enable_regback(): """Enable RegBack.""" TRY_PRINT.run( @@ -500,6 +506,12 @@ def disable_chrome_notifications(): pref_file.write_text(json.dumps(pref_data, separators=(',', ':'))) +def enable_bsod_minidumps(): + """Enable saving minidumps during BSoDs.""" + cmd = ['wmic', 'RECOVEROS', 'set', 'DebugInfoType', '=', '3'] + run_program(cmd) + + def enable_ublock_origin(): """Enable uBlock Origin in supported browsers.""" base_paths = [ From f9d4b1e3a3f274cd4a3320e0f841e773491e3de7 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Mon, 27 Sep 2021 19:44:25 -0600 Subject: [PATCH 22/40] Add UAC sections --- scripts/auto_setup.py | 2 +- scripts/wk/setup/win.py | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/scripts/auto_setup.py b/scripts/auto_setup.py index 8bf6fee0..48874875 100644 --- a/scripts/auto_setup.py +++ b/scripts/auto_setup.py @@ -132,7 +132,7 @@ BASE_MENUS = { MenuEntry('Set System Restore Size', 'auto_system_restore_set_size'), MenuEntry('Create System Restore', 'auto_system_restore_create'), MenuEntry('Enable Windows Updates', 'auto_windows_updates_enable'), - MenuEntry('User Account Control', no_op), + MenuEntry('User Account Control', 'auto_restore_default_uac'), MenuEntry('Windows Activation', no_op), MenuEntry('Windows Explorer', no_op), MenuEntry(r'Windows\Temp Fix', no_op), diff --git a/scripts/wk/setup/win.py b/scripts/wk/setup/win.py index 1f80ff99..42270c82 100644 --- a/scripts/wk/setup/win.py +++ b/scripts/wk/setup/win.py @@ -153,6 +153,27 @@ REG_OPEN_SHELL_SETTINGS = { ), }, } +UAC_DEFAULTS_WIN7 = { + 'HKLM': { + r'Software\Microsoft\Windows\CurrentVersion\Policies\System': ( + ('ConsentPromptBehaviorAdmin', 5, 'DWORD'), + ('EnableLUA', 1, 'DWORD'), + ('PromptOnSecureDesktop', 1, 'DWORD'), + ), + }, + } +UAC_DEFAULTS_WIN10 = { + 'HKLM': { + r'Software\Microsoft\Windows\CurrentVersion\Policies\System': ( + ('ConsentPromptBehaviorAdmin', 5, 'DWORD'), + ('ConsentPromptBehaviorUser', 3, 'DWORD'), + ('EnableInstallerDetection', 1, 'DWORD'), + ('EnableLUA', 1, 'DWORD'), + ('EnableVirtualization', 1, 'DWORD'), + ('PromptOnSecureDesktop', 1, 'DWORD'), + ), + }, + } SYSTEMDRIVE = os.environ.get('SYSTEMDRIVE', 'C:') WIDTH = 50 TRY_PRINT = TryAndPrint() @@ -462,6 +483,11 @@ def auto_install_vcredists(): TRY_PRINT.run('Visual C++ Runtimes...', install_vcredists) +def auto_restore_default_uac(): + """Restore default UAC settings.""" + TRY_PRINT.run('User Account Control...', restore_default_uac) + + # Configure Functions def disable_chrome_notifications(): """Disable notifications in Google Chrome.""" @@ -542,6 +568,15 @@ def enable_ublock_origin(): popen_program(cmd) +def restore_default_uac(): + """Restore default UAC settings.""" + settings = UAC_DEFAULTS_WIN10 + if OS_VERSION != 10: + settings = UAC_DEFAULTS_WIN7 + + reg_write_settings(settings) + + # Install Functions def install_firefox(): """Install Firefox. From bc320b4d874ce9a27a062a9ce559567844b2e97d Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Mon, 27 Sep 2021 20:48:19 -0600 Subject: [PATCH 23/40] Add remaining 'Configure System' sections --- scripts/auto_setup.py | 6 +-- scripts/wk/setup/win.py | 99 +++++++++++++++++++++++++++++++++++++++-- 2 files changed, 98 insertions(+), 7 deletions(-) diff --git a/scripts/auto_setup.py b/scripts/auto_setup.py index 48874875..4ffc04b7 100644 --- a/scripts/auto_setup.py +++ b/scripts/auto_setup.py @@ -133,9 +133,9 @@ BASE_MENUS = { MenuEntry('Create System Restore', 'auto_system_restore_create'), MenuEntry('Enable Windows Updates', 'auto_windows_updates_enable'), MenuEntry('User Account Control', 'auto_restore_default_uac'), - MenuEntry('Windows Activation', no_op), - MenuEntry('Windows Explorer', no_op), - MenuEntry(r'Windows\Temp Fix', no_op), + MenuEntry('Windows Activation', 'auto_activate_windows'), + MenuEntry('Windows Explorer', 'auto_config_explorer'), + MenuEntry(r'Windows\Temp Fix', 'auto_windows_temp_fix'), ), 'System Information': ( MenuEntry('AIDA64 Reports', no_op), diff --git a/scripts/wk/setup/win.py b/scripts/wk/setup/win.py index 42270c82..7c500af4 100644 --- a/scripts/wk/setup/win.py +++ b/scripts/wk/setup/win.py @@ -38,6 +38,7 @@ from wk.kit.tools import ( ) from wk.log import format_log_path, update_log_path from wk.os.win import ( + activate_with_bios, reg_delete_value, reg_read_value, reg_set_value, @@ -116,6 +117,61 @@ REG_CHROME_UBLOCK_ORIGIN = { ) }, } +REG_WINDOWS_EXPLORER = { + # pylint: disable=line-too-long + 'HKLM': { + # Disable Location Tracking + r'Software\Microsoft\Windows NT\CurrentVersion\Sensor\Overrides\{BFA794E4-F964-4FDB-90F6-51056BFE4B44}': ( + ('SensorPermissionState', 0, 'DWORD'), + ), + r'System\CurrentControlSet\Services\lfsvc\Service\Configuration': ( + ('Status', 0, 'DWORD'), + ), + # Disable Telemetry + r'Software\Microsoft\Windows\CurrentVersion\Policies\DataCollection': ( + ('AllowTelemetry', 0, 'DWORD'), + ('AllowTelemetry', 0, 'DWORD', '32'), + ), + r'Software\Policies\Microsoft\Windows\DataCollection': ( + ('AllowTelemetry', 0, 'DWORD'), + ), + # Disable Wi-Fi Sense + r'Software\Microsoft\PolicyManager\default\WiFi\AllowWiFiHotSpotReporting': ( + ('Value', 0, 'DWORD'), + ), + r'Software\Microsoft\PolicyManager\default\WiFi\AllowAutoConnectToWiFiSenseHotspots': ( + ('Value', 0, 'DWORD'), + ), + }, + 'HKCU': { + # Desktop theme (<= v1809 default) + r'Software\Microsoft\Windows\CurrentVersion\Themes\Personalize': { + ('AppsUseLightTheme', 1, 'DWORD'), + ('SystemUsesLightTheme', 0, 'DWORD'), + }, + # Disable features + r'Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager': { + ('SilentInstalledAppsEnabled', 0, 'DWORD'), + # Tips and Tricks + ('SoftLandingEnabled ', 0, 'DWORD'), + ('SubscribedContent-338389Enabled', 0, 'DWORD'), + }, + # File Explorer + r'Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced': { + # Change default Explorer view to "Computer" + ('LaunchTo', 1, 'DWORD'), + ('SeparateProcess', 1, 'DWORD'), + }, + # Hide People bar + r'Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\People': { + ('PeopleBand', 0, 'DWORD'), + }, + # Hide Search button / box + r'Software\Microsoft\Windows\CurrentVersion\Search': { + ('SearchboxTaskbarMode', 1, 'DWORD'), + }, + }, + } REG_OPEN_SHELL_SETTINGS = { 'HKCU': { r'Software\OpenShell\StartMenu': ( @@ -153,7 +209,7 @@ REG_OPEN_SHELL_SETTINGS = { ), }, } -UAC_DEFAULTS_WIN7 = { +REG_UAC_DEFAULTS_WIN7 = { 'HKLM': { r'Software\Microsoft\Windows\CurrentVersion\Policies\System': ( ('ConsentPromptBehaviorAdmin', 5, 'DWORD'), @@ -162,7 +218,7 @@ UAC_DEFAULTS_WIN7 = { ), }, } -UAC_DEFAULTS_WIN10 = { +REG_UAC_DEFAULTS_WIN10 = { 'HKLM': { r'Software\Microsoft\Windows\CurrentVersion\Policies\System': ( ('ConsentPromptBehaviorAdmin', 5, 'DWORD'), @@ -431,6 +487,16 @@ def auto_windows_updates_enable(): # Auto Setup: Wrapper Functions +def auto_activate_windows(): + """Attempt to activate Windows using BIOS key.""" + TRY_PRINT.run('Windows Activation...', activate_with_bios) + + +def auto_config_explorer(): + """Configure Windows Explorer and restart the process.""" + TRY_PRINT.run('Windows Explorer...', config_explorer) + + def auto_config_open_shell(): """Configure Open Shell.""" TRY_PRINT.run('Open Shell...', reg_write_settings, REG_OPEN_SHELL_SETTINGS) @@ -488,7 +554,21 @@ def auto_restore_default_uac(): TRY_PRINT.run('User Account Control...', restore_default_uac) +def auto_windows_temp_fix(): + """Restore default ACLs for Windows\\Temp.""" + TRY_PRINT.run(r'Windows\Temp fix...', fix_windows_temp) + + + + # Configure Functions +def config_explorer(): + """Configure Windows Explorer and restart the process.""" + reg_write_settings(REG_WINDOWS_EXPLORER) + kill_procs('explorer.exe', force=True) + popen_program(['explorer.exe']) + + def disable_chrome_notifications(): """Disable notifications in Google Chrome.""" defaults_key = 'default_content_setting_values' @@ -568,11 +648,22 @@ def enable_ublock_origin(): popen_program(cmd) +def fix_windows_temp(): + """Restore default permissions for Windows\\Temp.""" + permissions = ( + 'Users:(CI)(X,WD,AD)', + 'Administrators:(OI)(CI)(F)', + ) + for _p in permissions: + cmd = ['icacls', fr'{SYSTEMDRIVE}\Windows\Temp', '/grant:r', _p, '/T'] + run_program(cmd) + + def restore_default_uac(): """Restore default UAC settings.""" - settings = UAC_DEFAULTS_WIN10 + settings = REG_UAC_DEFAULTS_WIN10 if OS_VERSION != 10: - settings = UAC_DEFAULTS_WIN7 + settings = REG_UAC_DEFAULTS_WIN7 reg_write_settings(settings) From 528602d98e37e91ff425b3983d6c66c331c56058 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Mon, 27 Sep 2021 20:48:55 -0600 Subject: [PATCH 24/40] Check if activated before getting the BIOS key --- scripts/wk/os/win.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/scripts/wk/os/win.py b/scripts/wk/os/win.py index 82e768af..b32866ca 100644 --- a/scripts/wk/os/win.py +++ b/scripts/wk/os/win.py @@ -72,6 +72,11 @@ def activate_with_bios(): ##################################################### bios_key = None table = b"MSDM" + # Check if activation is needed + if is_activated(): + raise GenericWarning('System already activated') + + # Get BIOS key if acpi.FindAcpiTable(table) is True: rawtable = acpi.GetAcpiTable(table) #http://msdn.microsoft.com/library/windows/hardware/hh673514 @@ -82,10 +87,6 @@ def activate_with_bios(): if not bios_key: raise GenericError('BIOS key not found.') - # Check if activation is needed - if is_activated(): - raise GenericWarning('System already activated') - # Install Key cmd = ['cscript', '//nologo', SLMGR, '/ipk', bios_key] run_program(cmd, check=False) From 8289df1d621bf2aab9f39c701eef74caba2cb630 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Mon, 27 Sep 2021 20:49:39 -0600 Subject: [PATCH 25/40] Don't prepend exception name for WK generic types --- scripts/wk/std.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/scripts/wk/std.py b/scripts/wk/std.py index 958d275f..f6979d13 100644 --- a/scripts/wk/std.py +++ b/scripts/wk/std.py @@ -442,10 +442,11 @@ class TryAndPrint(): pass # Prepend exception name - try: - message = f'{_exception.__class__.__name__}: {message}' - except Exception: # pylint: disable=broad-except - message = f'UNKNOWN ERROR: {message}' + if _exception.__class__.__name__ not in ('GenericError', 'GenericWarning'): + try: + message = f'{_exception.__class__.__name__}: {message}' + except Exception: # pylint: disable=broad-except + message = f'UNKNOWN ERROR: {message}' # Fix multi-line messages if '\n' in message: @@ -525,8 +526,8 @@ class TryAndPrint(): return obj # Try all modules - for _mod in sys.modules: - obj = getattr(sys.modules[_mod], name, None) + for _mod in sys.modules.values(): + obj = getattr(_mod, name, None) if obj: break From 2e485505d408a9a75e5e41296b4eaaa7b8eb1974 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Mon, 27 Sep 2021 21:21:09 -0600 Subject: [PATCH 26/40] Skip backup sections if backup previously run --- scripts/auto_setup.py | 6 ------ scripts/wk/repairs/win.py | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/scripts/auto_setup.py b/scripts/auto_setup.py index 4ffc04b7..08b2a9ca 100644 --- a/scripts/auto_setup.py +++ b/scripts/auto_setup.py @@ -105,7 +105,6 @@ def no_op(*args): BASE_MENUS = { 'Groups': { 'Backup Settings': ( - # Add checks for existing backups and skip if detected MenuEntry('Backup Browsers', 'auto_backup_browser_profiles'), MenuEntry('Backup Power Plans', 'auto_backup_power_plans'), MenuEntry('Reset Power Plans', 'auto_reset_power_plans'), @@ -113,7 +112,6 @@ BASE_MENUS = { ), 'Install Software': ( MenuEntry('Visual C++ Runtimes', 'auto_install_vcredists'), - #MenuEntry('ESET NOD32 Antivirus', no_op), MenuEntry('Firefox', 'auto_install_firefox'), MenuEntry('LibreOffice', 'auto_install_libreoffice'), MenuEntry('Open Shell', 'auto_install_open_shell'), @@ -121,12 +119,9 @@ BASE_MENUS = { ), 'Configure System': ( MenuEntry('Chrome Notifications', 'auto_disable_chrome_notifications'), - #MenuEntry('O&O ShutUp 10', no_op), MenuEntry('Open Shell', 'auto_config_open_shell'), MenuEntry('uBlock Origin', 'auto_enable_ublock_origin'), - #MenuEntry('Disable Fast Startup', no_op), MenuEntry('Enable BSoD MiniDumps', 'auto_enable_bsod_minidumps'), - #MenuEntry('Enable Hibernation', no_op), MenuEntry('Enable RegBack', 'auto_enable_regback'), MenuEntry('Enable System Restore', 'auto_system_restore_enable'), MenuEntry('Set System Restore Size', 'auto_system_restore_set_size'), @@ -154,7 +149,6 @@ BASE_MENUS = { 'Run Programs': ( MenuEntry('Device Manager', no_op), MenuEntry('HWiNFO Sensors', no_op), - #MenuEntry('Snappy Driver Installer', no_op), MenuEntry('Windows Updates', no_op), MenuEntry('Windows Activation', no_op), MenuEntry('XMPlay', no_op), diff --git a/scripts/wk/repairs/win.py b/scripts/wk/repairs/win.py index 1f805722..b2964fd3 100644 --- a/scripts/wk/repairs/win.py +++ b/scripts/wk/repairs/win.py @@ -875,6 +875,16 @@ def backup_browser_chromium(backup_path, browser, search_path, use_try_print): if not match: continue output_path = backup_path.joinpath(f'{browser}-{item.name}.7z') + if output_path.exists(): + # Assuming backup was already done + if use_try_print: + show_data( + f'{" "*8}{browser} ({item.name})...', 'Backup already exists.', + color='YELLOW', width=WIDTH, + ) + continue + + # Backup data cmd = [ *BACKUP_BROWSER_BASE_CMD, output_path, item.joinpath('*'), '-x!*Cache*', '-x!Service Worker', @@ -891,6 +901,18 @@ def backup_browser_chromium(backup_path, browser, search_path, use_try_print): def backup_browser_firefox(backup_path, search_path, use_try_print): """Backup Firefox browser profile.""" output_path = backup_path.joinpath('Firefox.7z') + + # Bail early + if output_path.exists(): + # Assuming backup was already done + if use_try_print: + show_data( + f'{" "*8}Firefox (All)...', 'Backup already exists.', + color='YELLOW', width=WIDTH, + ) + return + + # Backup data cmd = [ *BACKUP_BROWSER_BASE_CMD, output_path, search_path.joinpath('Profiles'), search_path.joinpath('profiles.ini'), @@ -934,6 +956,12 @@ def backup_registry(): """Backup Registry.""" backup_path = set_backup_path('Registry', date=True) backup_path.parent.mkdir(parents=True, exist_ok=True) + + # Check if backup was already done today + if backup_path.exists(): + raise GenericWarning('Backup already exists.') + + # Backup registry extract_tool('ERUNT') run_tool('ERUNT', 'ERUNT', backup_path, 'sysreg', 'curuser', 'otherusers') @@ -1155,6 +1183,12 @@ def enable_windows_updates(): def export_power_plans(): """Export existing power plans.""" backup_path = set_backup_path('Power Plans', date=True) + + # Bail early + if backup_path.exists(): + raise GenericWarning('Backup already exists.') + + # Get powercfg data backup_path.mkdir(parents=True, exist_ok=True) cmd = ['powercfg', '/L'] proc = run_program(cmd) From 90fb97ad91fb2b95845d90cb79e7577c6dd2be43 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Mon, 27 Sep 2021 21:48:11 -0600 Subject: [PATCH 27/40] Fix various pylint warnings --- scripts/wk/exe.py | 3 ++- scripts/wk/hw/ddrescue.py | 21 +++++++++++---------- scripts/wk/hw/diags.py | 28 ++++++++++++++++------------ scripts/wk/hw/obj.py | 12 +++++++----- scripts/wk/hw/sensors.py | 2 +- scripts/wk/kit/ufd.py | 2 +- scripts/wk/os/linux.py | 2 +- scripts/wk/repairs/win.py | 18 ++++++++++-------- scripts/wk/setup/win.py | 5 ++--- scripts/wk/std.py | 2 +- 10 files changed, 52 insertions(+), 43 deletions(-) diff --git a/scripts/wk/exe.py b/scripts/wk/exe.py index ab49018b..e57240c9 100644 --- a/scripts/wk/exe.py +++ b/scripts/wk/exe.py @@ -67,7 +67,7 @@ class NonBlockingStreamReader(): out = self.read(0.1) if out: out_bytes += out - with open(out_path, 'a') as _f: + with open(out_path, 'a', encoding='utf-8') as _f: _f.write(out_bytes.decode('utf-8', errors='ignore')) # Close stream to prevent 100% CPU usage @@ -200,6 +200,7 @@ def popen_program(cmd, minimized=False, pipe=False, shell=False, **kwargs): shell=shell, **kwargs) try: + # pylint: disable=consider-using-with proc = subprocess.Popen(**cmd_kwargs) except FileNotFoundError: LOG.error('Command not found: %s', cmd) diff --git a/scripts/wk/hw/ddrescue.py b/scripts/wk/hw/ddrescue.py index ab869313..17faec9b 100644 --- a/scripts/wk/hw/ddrescue.py +++ b/scripts/wk/hw/ddrescue.py @@ -402,7 +402,7 @@ class State(): # Try loading JSON data if settings_file.exists(): - with open(settings_file, 'r') as _f: + with open(settings_file, 'r', encoding='utf-8') as _f: try: settings = json.loads(_f.read()) except (OSError, json.JSONDecodeError) as err: @@ -450,7 +450,7 @@ class State(): # Try saving JSON data try: - with open(settings_file, 'w') as _f: + with open(settings_file, 'w', encoding='utf-8') as _f: json.dump(settings, _f) except OSError as err: std.print_error('Failed to save clone settings') @@ -874,7 +874,7 @@ class State(): f'{self.working_dir}/' f'sfdisk_{self.destination.path.name}.script' ) - with open(script_path, 'w') as _f: + with open(script_path, 'w', encoding='utf-8') as _f: _f.write('\n'.join(sfdisk_script)) # Skip real format for dry runs @@ -884,7 +884,7 @@ class State(): # Format disk LOG.warning('Formatting destination: %s', self.destination.path) - with open(script_path, 'r') as _f: + with open(script_path, 'r', encoding='utf-8') as _f: proc = exe.run_program( cmd=['sudo', 'sfdisk', self.destination.path], stdin=_f, @@ -912,7 +912,7 @@ class State(): pair.status[name] = 'Pending' # Mark all non-trimmed, non-scraped, and bad areas as non-tried - with open(pair.map_path, 'r') as _f: + with open(pair.map_path, 'r', encoding='utf-8') as _f: for line in _f.readlines(): line = line.strip() if line.startswith('0x') and line.endswith(bad_statuses): @@ -920,7 +920,7 @@ class State(): map_data.append(line) # Save updated map - with open(pair.map_path, 'w') as _f: + with open(pair.map_path, 'w', encoding='utf-8') as _f: _f.write('\n'.join(map_data)) # Reinitialize status @@ -991,14 +991,15 @@ class State(): # State (self) std.save_pickles({'state': self}, debug_dir) - with open(f'{debug_dir}/state.report', 'a') as _f: + with open(f'{debug_dir}/state.report', 'a', encoding='utf-8') as _f: _f.write('[Debug report]\n') _f.write('\n'.join(debug.generate_object_report(self))) _f.write('\n') # Block pairs for _bp in self.block_pairs: - with open(f'{debug_dir}/block_pairs.report', 'a') as _f: + with open( + f'{debug_dir}/block_pairs.report', 'a', encoding='utf-8') as _f: _f.write('[Debug report]\n') _f.write('\n'.join(debug.generate_object_report(_bp))) _f.write('\n') @@ -1063,7 +1064,7 @@ class State(): # Write to progress file out_path = pathlib.Path(f'{self.log_dir}/progress.out') - with open(out_path, 'w') as _f: + with open(out_path, 'w', encoding='utf-8') as _f: _f.write('\n'.join(report)) def update_top_panes(self): @@ -1996,7 +1997,7 @@ def run_ddrescue(state, block_pair, pass_name, settings, dry_run=True): """Update SMART pane every 30 seconds.""" state.source.update_smart_details() now = datetime.datetime.now(tz=TIMEZONE).strftime('%Y-%m-%d %H:%M %Z') - with open(f'{state.log_dir}/smart.out', 'w') as _f: + with open(f'{state.log_dir}/smart.out', 'w', encoding='utf-8') as _f: _f.write( std.color_string( ['SMART Attributes', f'Updated: {now}\n'], diff --git a/scripts/wk/hw/diags.py b/scripts/wk/hw/diags.py index a052b6af..e5991b3f 100644 --- a/scripts/wk/hw/diags.py +++ b/scripts/wk/hw/diags.py @@ -357,11 +357,11 @@ class State(): # State (self) std.save_pickles({'state': self}, debug_dir) - with open(f'{debug_dir}/state.report', 'a') as _f: + with open(f'{debug_dir}/state.report', 'a', encoding='utf-8') as _f: _f.write('\n'.join(debug.generate_object_report(self))) # CPU/RAM - with open(f'{debug_dir}/cpu.report', 'a') as _f: + with open(f'{debug_dir}/cpu.report', 'a', encoding='utf-8') as _f: _f.write('\n'.join(debug.generate_object_report(self.cpu))) _f.write('\n\n[Tests]') for name, test in self.cpu.tests.items(): @@ -370,7 +370,9 @@ class State(): # Disks for disk in self.disks: - with open(f'{debug_dir}/disk_{disk.path.name}.report', 'a') as _f: + with open( + f'{debug_dir}/disk_{disk.path.name}.report', 'a', + encoding='utf-8') as _f: _f.write('\n'.join(debug.generate_object_report(disk))) _f.write('\n\n[Tests]') for name, test in disk.tests.items(): @@ -389,7 +391,7 @@ class State(): except Exception: # pylint: disable=broad-except LOG.ERROR('Error(s) encountered while exporting SMC data') data = [line.strip() for line in data] - with open(f'{debug_dir}/smc.data', 'a') as _f: + with open(f'{debug_dir}/smc.data', 'a', encoding='utf-8') as _f: _f.write('\n'.join(data)) def update_clock(self): @@ -426,7 +428,7 @@ class State(): # Write to progress file out_path = pathlib.Path(f'{self.log_dir}/progress.out') - with open(out_path, 'w') as _f: + with open(out_path, 'w', encoding='utf-8') as _f: _f.write('\n'.join(report)) def update_top_pane(self, text): @@ -632,7 +634,7 @@ def check_mprime_results(test_obj, working_dir): """Read file and split into lines, returns list.""" lines = [] try: - with open(f'{working_dir}/{log_name}', 'r') as _f: + with open(f'{working_dir}/{log_name}', 'r', encoding='utf-8') as _f: lines = _f.readlines() except FileNotFoundError: # File may be missing on older systems @@ -916,7 +918,7 @@ def disk_io_benchmark(state, test_objects, skip_usb=True): match.group(1) # Show progress - with open(log_path, 'a') as _f: + with open(log_path, 'a', encoding='utf-8') as _f: if _i % 5 == 0: percent = (_i / dd_values['Read Chunks']) * 100 _f.write(f' {graph.vertical_graph_line(percent, read_rates[-1])}\n') @@ -1095,7 +1097,7 @@ def disk_surface_scan(state, test_objects): # Start scan cmd = ['sudo', 'badblocks', '-sv', '-b', block_size, '-e', '1', dev_path] - with open(log_path, 'a') as _f: + with open(log_path, 'a', encoding='utf-8') as _f: size_str = std.bytes_to_string(dev.details["size"], use_binary=False) _f.write( std.color_string( @@ -1114,7 +1116,7 @@ def disk_surface_scan(state, test_objects): ) # Check results - with open(log_path, 'r') as _f: + with open(log_path, 'r', encoding='utf-8') as _f: for line in _f.readlines(): line = std.strip_colors(line.strip()) if not line or line.startswith('Checking') or line.startswith('['): @@ -1476,13 +1478,13 @@ def show_results(state): def start_mprime(working_dir, log_path): """Start mprime and save filtered output to log, returns Popen object.""" set_apple_fan_speed('max') - proc_mprime = subprocess.Popen( + proc_mprime = subprocess.Popen( # pylint: disable=consider-using-with ['mprime', '-t'], cwd=working_dir, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, ) - proc_grep = subprocess.Popen( + proc_grep = subprocess.Popen( # pylint: disable=consider-using-with 'grep --ignore-case --invert-match --line-buffered stress.txt'.split(), stdin=proc_mprime.stdout, stdout=subprocess.PIPE, @@ -1521,7 +1523,9 @@ def start_sysbench(sensors, sensors_out, log_path, pane): tmux.respawn_pane(pane, watch_file=log_path, watch_cmd='tail') # Start sysbench - filehandle_sysbench = open(log_path, 'a') + filehandle_sysbench = open( # pylint: disable=consider-using-with + log_path, 'a', encoding='utf-8', + ) proc_sysbench = exe.popen_program(sysbench_cmd, stdout=filehandle_sysbench) # Done diff --git a/scripts/wk/hw/obj.py b/scripts/wk/hw/obj.py index 3c09d9fd..d6923432 100644 --- a/scripts/wk/hw/obj.py +++ b/scripts/wk/hw/obj.py @@ -356,9 +356,11 @@ class Disk(BaseObj): self.details[attr] = -1 # Set description - self.description = '{size_str} ({bus}) {model} {serial}'.format( - size_str=bytes_to_string(self.details['size'], use_binary=False), - **self.details, + self.description = ( + f'{bytes_to_string(self.details["size"], use_binary=False)}' + f' ({self.details["bus"]})' + f' {self.details["model"]}' + f' {self.details["serial"]}' ) def get_labels(self): @@ -482,7 +484,7 @@ class Disk(BaseObj): test_minutes = int(test_minutes) + 10 # Start test - with open(log_path, 'w') as _f: + with open(log_path, 'w', encoding='utf-8') as _f: _f.write(f'{header_str}\nInitializing...') cmd = [ 'sudo', @@ -507,7 +509,7 @@ class Disk(BaseObj): status_str = status_str.capitalize() # Update log - with open(log_path, 'w') as _f: + with open(log_path, 'w', encoding='utf-8') as _f: _f.write(f'{header_str}\nSMART self-test status:\n {status_str}') # Check if finished diff --git a/scripts/wk/hw/sensors.py b/scripts/wk/hw/sensors.py index e5b27bc1..f0e7b97c 100644 --- a/scripts/wk/hw/sensors.py +++ b/scripts/wk/hw/sensors.py @@ -141,7 +141,7 @@ class Sensors(): if thermal_action: run_program(thermal_action, check=False) report = self.generate_report(*temp_labels) - with open(out_path, 'w') as _f: + with open(out_path, 'w', encoding='utf-8') as _f: _f.write('\n'.join(report)) # Check if we should stop diff --git a/scripts/wk/kit/ufd.py b/scripts/wk/kit/ufd.py index e1f7ee7a..a29bfcd6 100644 --- a/scripts/wk/kit/ufd.py +++ b/scripts/wk/kit/ufd.py @@ -374,7 +374,7 @@ def get_uuid(path): def hide_items(ufd_dev_first_partition, items): """Set FAT32 hidden flag for items.""" - with open('/root/.mtoolsrc', 'w') as _f: + with open('/root/.mtoolsrc', 'w', encoding='utf-8') as _f: _f.write(f'drive U: file="{ufd_dev_first_partition}"\n') _f.write('mtools_skip_check=1\n') diff --git a/scripts/wk/os/linux.py b/scripts/wk/os/linux.py index 73e6d85b..f3325fb7 100644 --- a/scripts/wk/os/linux.py +++ b/scripts/wk/os/linux.py @@ -218,7 +218,7 @@ def scan_corestorage_container(container, timeout=300): # Create mapper device(s) if necessary for name, cmd in detected_volumes.items(): cmd_file = make_temp_file() - cmd_file.write_text(cmd) + cmd_file.write_text(cmd, encoding='utf-8') proc = run_program( cmd=['sudo', 'dmsetup', 'create', name, cmd_file], check=False, diff --git a/scripts/wk/repairs/win.py b/scripts/wk/repairs/win.py index b2964fd3..7e045c7f 100644 --- a/scripts/wk/repairs/win.py +++ b/scripts/wk/repairs/win.py @@ -987,8 +987,8 @@ def run_bleachbit(cleaners, preview=True): proc = run_tool('BleachBit', 'bleachbit_console', *cmd_args, cbin=True) # Save logs - log_path.write_text(proc.stdout) - log_path.with_suffix('.err').write_text(proc.stderr) + log_path.write_text(proc.stdout, encoding='utf-8') + log_path.with_suffix('.err').write_text(proc.stderr, encoding='utf-8') def run_hitmanpro(): @@ -1025,7 +1025,7 @@ def run_kvrt(): download_tool('KVRT', 'KVRT') kvrt_path = get_tool_path('KVRT', 'KVRT') tmp_file = fr'{os.environ.get("TMP")}\run_kvrt.cmd' - with open(tmp_file, 'w') as _f: + with open(tmp_file, 'w', encoding='utf-8') as _f: _f.write('@echo off\n') _f.write(f'"{kvrt_path}" {" ".join(cmd_args)}\n') cmd = ('cmd', '/c', tmp_file, '-new_console:nb', '-new_console:s33V') @@ -1036,7 +1036,7 @@ def run_kvrt(): # Run in background proc = run_tool('KVRT', 'KVRT', *cmd_args, download=True) - log_path.write_text(proc.stdout) + log_path.write_text(proc.stdout, encoding='utf-8') def run_microsoft_defender(full=True): @@ -1075,7 +1075,7 @@ def run_microsoft_defender(full=True): # Run scan cmd = (defender_path, '-Scan', '-ScanType', '2' if full else '1') proc = run_program(cmd, check=False) - log_path.write_text(proc.stdout) + log_path.write_text(proc.stdout, encoding='utf-8') if proc.returncode > 0: raise GenericError('Failed to run scan or clean items.') @@ -1085,7 +1085,9 @@ def run_rkill(): log_path = format_log_path(log_name='RKill', timestamp=True, tool=True) log_path.parent.mkdir(parents=True, exist_ok=True) whitelist_path = log_path.with_suffix('.wl') - whitelist_path.write_text('\n'.join(map(str, RKILL_WHITELIST))) + whitelist_path.write_text( + '\n'.join(map(str, RKILL_WHITELIST)), encoding='utf-8', + ) cmd_args = ( '-l', log_path, '-w', whitelist_path, @@ -1398,9 +1400,9 @@ def run_sfc_scan(): # Save output os.makedirs(log_path.parent, exist_ok=True) - with open(log_path, 'a') as _f: + with open(log_path, 'a', encoding='utf-8') as _f: _f.write(proc.stdout) - with open(err_path, 'a') as _f: + with open(err_path, 'a', encoding='utf-8') as _f: _f.write(proc.stderr) # Check result diff --git a/scripts/wk/setup/win.py b/scripts/wk/setup/win.py index 7c500af4..80a8ef94 100644 --- a/scripts/wk/setup/win.py +++ b/scripts/wk/setup/win.py @@ -449,7 +449,6 @@ def auto_set_custom_power_plan(): def auto_enable_bsod_minidumps(): """Enable saving minidumps during BSoDs.""" - cmd = ['wmic', 'RECOVEROS', 'set', 'DebugInfoType', '=', '3'] TRY_PRINT.run('Enable BSoD mini dumps...', enable_bsod_minidumps) @@ -732,12 +731,12 @@ def install_firefox(): # Revert default profile if needed if revert_default: out = [] - for line in profiles_ini.read_text().splitlines(): + for line in profiles_ini.read_text(encoding='utf-8').splitlines(): if 'Default=Profile' in line: out.append(f'Default={current_default_profile}') else: out.append(line) - profiles_ini.write_text('\n'.join(out)) + profiles_ini.write_text('\n'.join(out), encoding='utf-8') def install_libreoffice( diff --git a/scripts/wk/std.py b/scripts/wk/std.py index f6979d13..c811bdc5 100644 --- a/scripts/wk/std.py +++ b/scripts/wk/std.py @@ -803,7 +803,7 @@ def generate_debug_report(): if log_path: report.append('------ Start Log -------') report.append('') - with open(log_path, 'r') as log_file: + with open(log_path, 'r', encoding='utf-8') as log_file: report.extend(log_file.read().splitlines()) report.append('') report.append('------- End Log --------') From f0451a98039eb46c87d18539f88fea4fb7f83213 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Tue, 28 Sep 2021 18:34:50 -0600 Subject: [PATCH 28/40] Adjust Windows-specific imports and STATIC VARS --- scripts/wk/repairs/win.py | 41 +++++++++++++++------ scripts/wk/setup/win.py | 77 +++++++++++++++++++-------------------- 2 files changed, 67 insertions(+), 51 deletions(-) diff --git a/scripts/wk/repairs/win.py b/scripts/wk/repairs/win.py index 7e045c7f..910768c1 100644 --- a/scripts/wk/repairs/win.py +++ b/scripts/wk/repairs/win.py @@ -32,17 +32,6 @@ from wk.kit.tools import ( run_tool, ) from wk.log import format_log_path, update_log_path -from wk.os.win import ( - get_timezone, - set_timezone, - reg_delete_value, - reg_read_value, - reg_set_value, - reg_write_settings, - disable_service, - enable_service, - stop_service, - ) from wk.std import ( GenericError, GenericWarning, @@ -61,6 +50,32 @@ from wk.std import ( sleep, strip_colors, ) +if platform.system() == 'Windows': + from wk.os.win import ( + get_timezone, + set_timezone, + reg_delete_value, + reg_read_value, + reg_set_value, + reg_write_settings, + disable_service, + enable_service, + stop_service, + ) +else: + # Workaround to allow basic testing under non-Windows environments + def no_op(*args, **kwargs): # pylint: disable=unused-argument + """No-op function.""" + # wk.os.win + get_timezone = no_op + set_timezone = no_op + reg_delete_value = no_op + reg_read_value = no_op + reg_set_value = no_op + reg_write_settings = no_op + disable_service = no_op + enable_service = no_op + stop_service = no_op # STATIC VARIABLES @@ -118,7 +133,9 @@ PROGRAMFILES_32 = os.environ.get( 'PROGRAMFILES', r'C:\Program Files (x86)', ), ) -OS_VERSION = float(platform.win32_ver()[0]) +OS_VERSION = -1 +if platform.system() == 'Windows': + OS_VERSION = float(platform.win32_ver()[0]) POWER_PLANS = { 'Balanced': '381b4222-f694-41f0-9685-ff5bb260df2e', 'Custom': '01189998-8199-9119-725c-ccccccccccc3', diff --git a/scripts/wk/setup/win.py b/scripts/wk/setup/win.py index 80a8ef94..cd0e29b5 100644 --- a/scripts/wk/setup/win.py +++ b/scripts/wk/setup/win.py @@ -8,25 +8,10 @@ import os import platform import re import sys -import time -from subprocess import CalledProcessError, DEVNULL - -from wk.cfg.main import KIT_NAME_FULL, KIT_NAME_SHORT -from wk.exe import ( - get_procs, - kill_procs, - run_program, - popen_program, - wait_for_procs, - ) -from wk.io import ( - case_insensitive_path, - delete_folder, - get_path_obj, - non_clobber_path, - rename_item, - ) +from wk.cfg.main import KIT_NAME_FULL +from wk.exe import kill_procs, run_program, popen_program +from wk.io import case_insensitive_path, get_path_obj from wk.kit.tools import ( ARCH, download_tool, @@ -37,28 +22,7 @@ from wk.kit.tools import ( run_tool, ) from wk.log import format_log_path, update_log_path -from wk.os.win import ( - activate_with_bios, - reg_delete_value, - reg_read_value, - reg_set_value, - reg_write_settings, - disable_service, - enable_service, - stop_service, - ) -from wk.repairs.win import ( - backup_all_browser_profiles, - backup_registry, - create_custom_power_plan, - create_system_restore_point, - enable_windows_updates, - export_power_plans, - reset_power_plans, - set_system_restore_size, - ) from wk.std import ( - GenericError, GenericWarning, Menu, TryAndPrint, @@ -75,6 +39,41 @@ from wk.std import ( sleep, strip_colors, ) +if platform.system() == 'Windows': + from wk.os.win import ( + activate_with_bios, + reg_read_value, + reg_set_value, + reg_write_settings, + ) + from wk.repairs.win import ( + backup_all_browser_profiles, + backup_registry, + create_custom_power_plan, + create_system_restore_point, + enable_windows_updates, + export_power_plans, + reset_power_plans, + set_system_restore_size, + ) +else: + # Workaround to allow basic testing under non-Windows environments + def no_op(*args, **kwargs): # pylint: disable=unused-argument + """No-op function.""" + # wk.os.win + activate_with_bios = no_op + reg_read_value = no_op + reg_set_value = no_op + reg_write_settings = no_op + # wk.repairs.win + backup_all_browser_profiles = no_op + backup_registry = no_op + create_custom_power_plan = no_op + create_system_restore_point = no_op + enable_windows_updates = no_op + export_power_plans = no_op + reset_power_plans = no_op + set_system_restore_size = no_op # STATIC VARIABLES From d725837f9b829936e11c9a29511430df3b497ff9 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Tue, 28 Sep 2021 19:21:30 -0600 Subject: [PATCH 29/40] Add AIDA64 sections Replaced old report profiles with a new basic profile. Several sections that just slow down the process have been removed. --- scripts/auto_setup.py | 2 +- scripts/wk/setup/win.py | 27 ++++- setup/windows/cbin/_include/AIDA64/basic.rpf | 35 +++++++ setup/windows/cbin/_include/AIDA64/full.rpf | 98 ------------------- .../_include/AIDA64/installed_programs.rpf | 1 - .../windows/cbin/_include/AIDA64/licenses.rpf | 1 - 6 files changed, 60 insertions(+), 104 deletions(-) create mode 100644 setup/windows/cbin/_include/AIDA64/basic.rpf delete mode 100644 setup/windows/cbin/_include/AIDA64/full.rpf delete mode 100644 setup/windows/cbin/_include/AIDA64/installed_programs.rpf delete mode 100644 setup/windows/cbin/_include/AIDA64/licenses.rpf diff --git a/scripts/auto_setup.py b/scripts/auto_setup.py index 08b2a9ca..79f23de5 100644 --- a/scripts/auto_setup.py +++ b/scripts/auto_setup.py @@ -133,7 +133,7 @@ BASE_MENUS = { MenuEntry(r'Windows\Temp Fix', 'auto_windows_temp_fix'), ), 'System Information': ( - MenuEntry('AIDA64 Reports', no_op), + MenuEntry('AIDA64 Report', 'auto_export_aida64_report'), MenuEntry('Backup Registry', 'auto_backup_registry'), MenuEntry('Everything (File List)', no_op), ), diff --git a/scripts/wk/setup/win.py b/scripts/wk/setup/win.py index cd0e29b5..786d4371 100644 --- a/scripts/wk/setup/win.py +++ b/scripts/wk/setup/win.py @@ -23,6 +23,7 @@ from wk.kit.tools import ( ) from wk.log import format_log_path, update_log_path from wk.std import ( + GenericError, GenericWarning, Menu, TryAndPrint, @@ -518,6 +519,11 @@ def auto_enable_ublock_origin(): print(f'\033[F\r{" "*len(prompt)}\r', end='', flush=True) +def auto_export_aida64_report(): + """Export AIDA64 reports.""" + TRY_PRINT.run('AIDA64 Report...', export_aida64_report) + + def auto_install_firefox(): """Install Firefox.""" TRY_PRINT.run('Firefox...', install_firefox) @@ -889,10 +895,25 @@ def get_firefox_default_profile(profiles_ini): # Tool Functions -## TODO? +def export_aida64_report(): + """Export AIDA64 report.""" + report_path = format_log_path( + log_name='AIDA64 System Report', + tool=True, timestamp=True, + ) + report_path = report_path.with_suffix('.html') + report_path.parent.mkdir(parents=True, exist_ok=True) + + # Run AIDA64 and check result + proc = run_tool( + 'AIDA64', 'aida64', + '/R', report_path, + '/CUSTOM', 'basic.rpf', + '/HTML', '/SILENT', '/SAFEST', + cbin=True, cwd=True) + if proc.returncode: + raise GenericError('Error(s) encountered exporting report.') -# OS Built-in Functions -## TODO? if __name__ == '__main__': print("This file is not meant to be called directly.") diff --git a/setup/windows/cbin/_include/AIDA64/basic.rpf b/setup/windows/cbin/_include/AIDA64/basic.rpf new file mode 100644 index 00000000..c3bc9648 --- /dev/null +++ b/setup/windows/cbin/_include/AIDA64/basic.rpf @@ -0,0 +1,35 @@ +InfoPage="Computer;Summary" +InfoPage="Computer;Computer Name" +InfoPage="Computer;DMI" +InfoPage="Computer;IPMI" +InfoPage="Computer;Overclock" +InfoPage="Computer;Power Management" +InfoPage="Motherboard;CPU" +InfoPage="Motherboard;Motherboard" +InfoPage="Motherboard;Memory" +InfoPage="Motherboard;SPD" +InfoPage="Motherboard;Chipset" +InfoPage="Motherboard;BIOS" +InfoPage="Operating System;Operating System" +InfoPage="Server;Users" +InfoPage="Storage;Windows Storage" +InfoPage="Storage;Logical Drives" +InfoPage="Storage;Physical Drives" +InfoPage="Storage;Optical Drives" +InfoPage="Storage;ASPI" +InfoPage="Storage;ATA" +InfoPage="Storage;SMART" +InfoPage="Network;Windows Network" +InfoPage="Devices;Windows Devices" +InfoPage="Devices;Physical Devices" +InfoPage="Devices;PCI Devices" +InfoPage="Software;Auto Start" +InfoPage="Software;Scheduled" +InfoPage="Software;Installed Programs" +InfoPage="Software;Licenses" +InfoPage="Security;Windows Security" +InfoPage="Security;Windows Update" +InfoPage="Security;Anti-Virus" +InfoPage="Security;Firewall" +InfoPage="Security;Anti-Spyware" +InfoPage="Security;Anti-Trojan" diff --git a/setup/windows/cbin/_include/AIDA64/full.rpf b/setup/windows/cbin/_include/AIDA64/full.rpf deleted file mode 100644 index 8d7df2ad..00000000 --- a/setup/windows/cbin/_include/AIDA64/full.rpf +++ /dev/null @@ -1,98 +0,0 @@ -InfoPage="Computer;Summary" -InfoPage="Computer;Computer Name" -InfoPage="Computer;DMI" -InfoPage="Computer;IPMI" -InfoPage="Computer;Overclock" -InfoPage="Computer;Power Management" -InfoPage="Computer;Portable Computer" -InfoPage="Motherboard;CPU" -InfoPage="Motherboard;CPUID" -InfoPage="Motherboard;Motherboard" -InfoPage="Motherboard;Memory" -InfoPage="Motherboard;SPD" -InfoPage="Motherboard;Chipset" -InfoPage="Motherboard;BIOS" -InfoPage="Motherboard;ACPI" -InfoPage="Operating System;Operating System" -InfoPage="Operating System;Processes" -InfoPage="Operating System;System Drivers" -InfoPage="Operating System;Services" -InfoPage="Operating System;AX Files" -InfoPage="Operating System;DLL Files" -InfoPage="Operating System;Certificates" -InfoPage="Operating System;UpTime" -InfoPage="Server;Share" -InfoPage="Server;Opened Files" -InfoPage="Server;Account Security" -InfoPage="Server;Logon" -InfoPage="Server;Users" -InfoPage="Server;Local Groups" -InfoPage="Server;Global Groups" -InfoPage="Display;Windows Video" -InfoPage="Display;PCI / AGP Video" -InfoPage="Display;GPU" -InfoPage="Display;Monitor" -InfoPage="Display;Desktop" -InfoPage="Display;Multi-Monitor" -InfoPage="Display;Video Modes" -InfoPage="Display;OpenGL" -InfoPage="Display;GPGPU" -InfoPage="Display;Mantle" -InfoPage="Display;Vulkan" -InfoPage="Display;Fonts" -InfoPage="Multimedia;Windows Audio" -InfoPage="Multimedia;PCI / PnP Audio" -InfoPage="Multimedia;HD Audio" -InfoPage="Multimedia;OpenAL" -InfoPage="Multimedia;Audio Codecs" -InfoPage="Multimedia;Video Codecs" -InfoPage="Multimedia;MCI" -InfoPage="Multimedia;SAPI" -InfoPage="Storage;Windows Storage" -InfoPage="Storage;Logical Drives" -InfoPage="Storage;Physical Drives" -InfoPage="Storage;Optical Drives" -InfoPage="Storage;ASPI" -InfoPage="Storage;ATA" -InfoPage="Storage;SMART" -InfoPage="Network;Windows Network" -InfoPage="Network;PCI / PnP Network" -InfoPage="Network;RAS" -InfoPage="Network;Net Resources" -InfoPage="Network;IAM" -InfoPage="Network;Internet" -InfoPage="Network;Routes" -InfoPage="Network;IE Cookie" -InfoPage="Network;Browser History" -InfoPage="DirectX;DirectX Files" -InfoPage="DirectX;DirectX Video" -InfoPage="DirectX;DirectX Sound" -InfoPage="Devices;Windows Devices" -InfoPage="Devices;Physical Devices" -InfoPage="Devices;PCI Devices" -InfoPage="Devices;USB Devices" -InfoPage="Devices;Device Resources" -InfoPage="Devices;Input" -InfoPage="Devices;Printers" -InfoPage="Software;Auto Start" -InfoPage="Software;Scheduled" -InfoPage="Software;Installed Programs" -InfoPage="Software;Licenses" -InfoPage="Software;File Types" -InfoPage="Software;Desktop Gadgets" -InfoPage="Security;Windows Security" -InfoPage="Security;Windows Update" -InfoPage="Security;Anti-Virus" -InfoPage="Security;Firewall" -InfoPage="Security;Anti-Spyware" -InfoPage="Security;Anti-Trojan" -InfoPage="Config;Regional" -InfoPage="Config;Environment" -InfoPage="Config;Control Panel" -InfoPage="Config;Recycle Bin" -InfoPage="Config;System Files" -InfoPage="Config;System Folders" -InfoPage="Database;Database Software" -InfoPage="Database;BDE Drivers" -InfoPage="Database;ODBC Drivers" -InfoPage="Database;ODBC Data Sources" diff --git a/setup/windows/cbin/_include/AIDA64/installed_programs.rpf b/setup/windows/cbin/_include/AIDA64/installed_programs.rpf deleted file mode 100644 index 2d79cb30..00000000 --- a/setup/windows/cbin/_include/AIDA64/installed_programs.rpf +++ /dev/null @@ -1 +0,0 @@ -InfoPage="Software;Installed Programs" diff --git a/setup/windows/cbin/_include/AIDA64/licenses.rpf b/setup/windows/cbin/_include/AIDA64/licenses.rpf deleted file mode 100644 index 6ef298f1..00000000 --- a/setup/windows/cbin/_include/AIDA64/licenses.rpf +++ /dev/null @@ -1 +0,0 @@ -InfoPage="Software;Licenses" From 423cd343fbcd375e661327409c1d92f67ddc1e0d Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Tue, 28 Sep 2021 23:23:05 -0600 Subject: [PATCH 30/40] Add show_os_name() with support status checks --- scripts/auto_setup.py | 3 +-- scripts/wk/cfg/__init__.py | 1 + scripts/wk/cfg/windows_builds.py | 36 ++++++++++++++++++++++++++++++++ scripts/wk/os/win.py | 33 +++++++++++++++++++++++++++++ scripts/wk/repairs/win.py | 5 ++--- scripts/wk/setup/win.py | 12 ++++++++--- 6 files changed, 82 insertions(+), 8 deletions(-) create mode 100644 scripts/wk/cfg/windows_builds.py diff --git a/scripts/auto_setup.py b/scripts/auto_setup.py index 79f23de5..e30b39e7 100644 --- a/scripts/auto_setup.py +++ b/scripts/auto_setup.py @@ -135,10 +135,9 @@ BASE_MENUS = { 'System Information': ( MenuEntry('AIDA64 Report', 'auto_export_aida64_report'), MenuEntry('Backup Registry', 'auto_backup_registry'), - MenuEntry('Everything (File List)', no_op), ), 'System Summary': ( - MenuEntry('Operating System', no_op), + MenuEntry('Operating System', 'auto_show_os_name'), MenuEntry('Windows Activation', no_op), MenuEntry('Secure Boot', no_op), MenuEntry('Installed RAM', no_op), diff --git a/scripts/wk/cfg/__init__.py b/scripts/wk/cfg/__init__.py index bb77be75..f79d77ef 100644 --- a/scripts/wk/cfg/__init__.py +++ b/scripts/wk/cfg/__init__.py @@ -7,3 +7,4 @@ from . import main from . import net from . import sources from . import ufd +from . import windows_builds diff --git a/scripts/wk/cfg/windows_builds.py b/scripts/wk/cfg/windows_builds.py new file mode 100644 index 00000000..580564b4 --- /dev/null +++ b/scripts/wk/cfg/windows_builds.py @@ -0,0 +1,36 @@ +"""WizardKit: Config - Windows Builds""" +# vim: sts=2 sw=2 ts=2 + + +OLDEST_SUPPORTED_BUILD = 19041 # Windows 10 20H1 +OUTDATED_BUILD_NUMBERS = ( + 9600, # Windows 8.1 Update + 18363, # Windows 10 19H2 + ) +WINDOWS_BUILDS = { + # Windows 7 + '6.1.7600': 'RTM "Vienna"', + '6.1.7601': 'SP1 "Vienna"', + + # Windows 8 + '6.2.9200': 'RTM', + + # Widnows 8.1 + '6.3.9200': '"Blue"', + '6.3.9600': '"Update"', + + # Windows 10 + '10.0.10240': '1507 "Threshold 1"', + '10.0.10586': '1511 "Threshold 2"', + '10.0.14393': '1607 "Redstone 1"', + '10.0.15063': '1703 "Redstone 2"', + '10.0.16299': '1709 "Redstone 3"', + '10.0.17134': '1803 "Redstone 4"', + '10.0.17763': '1809 "Redstone 5"', + '10.0.18362': '1903 / 19H1', + '10.0.18363': '1909 / 19H2', + '10.0.19041': '2004 / 20H1', + '10.0.19042': '20H2', + '10.0.19043': '21H1', + '10.0.19044': '21H2', +} diff --git a/scripts/wk/os/win.py b/scripts/wk/os/win.py index b32866ca..4fa96574 100644 --- a/scripts/wk/os/win.py +++ b/scripts/wk/os/win.py @@ -16,12 +16,18 @@ except ImportError as err: raise err from wk.borrowed import acpi +from wk.cfg.windows_builds import ( + OLDEST_SUPPORTED_BUILD, + OUTDATED_BUILD_NUMBERS, + WINDOWS_BUILDS, + ) from wk.exe import run_program from wk.std import GenericError, GenericWarning, sleep # STATIC VARIABLES LOG = logging.getLogger(__name__) +ARCH = '64' if platform.architecture()[0] == '64bit' else '32' CONEMU = 'ConEmuPID' in os.environ KNOWN_DATA_TYPES = { 'BINARY': winreg.REG_BINARY, @@ -120,6 +126,33 @@ def is_activated(): return act_str and 'permanent' in act_str +# System Info Functions +def show_os_name(check=True): + """Build OS display name and print it to screen. + + NOTE: If check=True then an exception is raised if the OS version is + outdated or unsupported. + """ + key = r'SOFTWARE\Microsoft\Windows NT\CurrentVersion' + build_version = int(reg_read_value("HKLM", key, "CurrentBuild")) + build_version_full = platform.win32_ver()[1] + details = WINDOWS_BUILDS.get(build_version_full, f'Build {build_version}') + display_name = ( + f'{reg_read_value("HKLM", key, "ProductName")} {ARCH}-bit {details}' + ) + + # Check for support issues + if check: + if build_version in OUTDATED_BUILD_NUMBERS: + raise GenericWarning(f'{display_name} (outdated)') + + if build_version < OLDEST_SUPPORTED_BUILD: + raise GenericError(f'{display_name} (unsupported)') + + # Done + print(display_name) + + # Registry Functions def reg_delete_key(hive, key, recurse=False): # pylint: disable=raise-missing-from diff --git a/scripts/wk/repairs/win.py b/scripts/wk/repairs/win.py index 910768c1..07f87bb9 100644 --- a/scripts/wk/repairs/win.py +++ b/scripts/wk/repairs/win.py @@ -52,6 +52,7 @@ from wk.std import ( ) if platform.system() == 'Windows': from wk.os.win import ( + OS_VERSION, get_timezone, set_timezone, reg_delete_value, @@ -64,6 +65,7 @@ if platform.system() == 'Windows': ) else: # Workaround to allow basic testing under non-Windows environments + OS_VERSION = -1 def no_op(*args, **kwargs): # pylint: disable=unused-argument """No-op function.""" # wk.os.win @@ -133,9 +135,6 @@ PROGRAMFILES_32 = os.environ.get( 'PROGRAMFILES', r'C:\Program Files (x86)', ), ) -OS_VERSION = -1 -if platform.system() == 'Windows': - OS_VERSION = float(platform.win32_ver()[0]) POWER_PLANS = { 'Balanced': '381b4222-f694-41f0-9685-ff5bb260df2e', 'Custom': '01189998-8199-9119-725c-ccccccccccc3', diff --git a/scripts/wk/setup/win.py b/scripts/wk/setup/win.py index 786d4371..c5621a3c 100644 --- a/scripts/wk/setup/win.py +++ b/scripts/wk/setup/win.py @@ -42,10 +42,12 @@ from wk.std import ( ) if platform.system() == 'Windows': from wk.os.win import ( + OS_VERSION, activate_with_bios, reg_read_value, reg_set_value, reg_write_settings, + show_os_name, ) from wk.repairs.win import ( backup_all_browser_profiles, @@ -59,6 +61,7 @@ if platform.system() == 'Windows': ) else: # Workaround to allow basic testing under non-Windows environments + OS_VERSION = -1 def no_op(*args, **kwargs): # pylint: disable=unused-argument """No-op function.""" # wk.os.win @@ -66,6 +69,7 @@ else: reg_read_value = no_op reg_set_value = no_op reg_write_settings = no_op + show_os_name = no_op # wk.repairs.win backup_all_browser_profiles = no_op backup_registry = no_op @@ -97,9 +101,6 @@ LIBREOFFICE_XCU_DATA = ''' ''' MENU_PRESETS = Menu() -OS_VERSION = -1 -if platform.system() == 'Windows': - OS_VERSION = float(platform.win32_ver()[0]) PROGRAMFILES_32 = os.environ.get( 'PROGRAMFILES(X86)', os.environ.get( 'PROGRAMFILES', r'C:\Program Files (x86)', @@ -558,6 +559,11 @@ def auto_restore_default_uac(): TRY_PRINT.run('User Account Control...', restore_default_uac) +def auto_show_os_name(): + """Display OS Name.""" + TRY_PRINT.run('Operating System...', show_os_name) + + def auto_windows_temp_fix(): """Restore default ACLs for Windows\\Temp.""" TRY_PRINT.run(r'Windows\Temp fix...', fix_windows_temp) From 337b6d95e1b5b978ec71c8a177b38649c883051b Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Wed, 29 Sep 2021 00:59:06 -0600 Subject: [PATCH 31/40] Add activation and Secure Boot sections --- scripts/auto_setup.py | 4 +- scripts/wk/os/win.py | 128 ++++++++++++++++++++++++++++++++++------ scripts/wk/setup/win.py | 25 ++++++-- 3 files changed, 132 insertions(+), 25 deletions(-) diff --git a/scripts/auto_setup.py b/scripts/auto_setup.py index e30b39e7..5d614f33 100644 --- a/scripts/auto_setup.py +++ b/scripts/auto_setup.py @@ -138,8 +138,8 @@ BASE_MENUS = { ), 'System Summary': ( MenuEntry('Operating System', 'auto_show_os_name'), - MenuEntry('Windows Activation', no_op), - MenuEntry('Secure Boot', no_op), + MenuEntry('Windows Activation', 'auto_show_activation'), + MenuEntry('Secure Boot', 'auto_show_secure_boot_status'), MenuEntry('Installed RAM', no_op), MenuEntry('Storage Volumes', no_op), MenuEntry('Virus Protection', no_op), diff --git a/scripts/wk/os/win.py b/scripts/wk/os/win.py index 4fa96574..41b52a26 100644 --- a/scripts/wk/os/win.py +++ b/scripts/wk/os/win.py @@ -1,6 +1,7 @@ """WizardKit: Windows Functions""" # vim: sts=2 sw=2 ts=2 +import ctypes import logging import os import pathlib @@ -16,6 +17,7 @@ except ImportError as err: raise err from wk.borrowed import acpi +from wk.cfg.main import KIT_NAME_FULL from wk.cfg.windows_builds import ( OLDEST_SUPPORTED_BUILD, OUTDATED_BUILD_NUMBERS, @@ -126,9 +128,40 @@ def is_activated(): return act_str and 'permanent' in act_str -# System Info Functions -def show_os_name(check=True): - """Build OS display name and print it to screen. +# Date / Time functions +def get_timezone(): + """Get current timezone using tzutil, returns str.""" + cmd = ['tzutil', '/g'] + proc = run_program(cmd, check=False) + return proc.stdout + + +def set_timezone(zone): + """Set current timezone using tzutil.""" + cmd = ['tzutil', '/s', zone] + run_program(cmd, check=False) + + +# Info Functions +def get_os_activation(as_list=False, check=True): + """Get OS activation status, returns str. + + NOTE: If check=True then raise an exception if OS isn't activated. + """ + act_str = get_activation_string() + + if check and not is_activated(): + if 'unavailable' in act_str.lower(): + raise GenericWarning(act_str) + # Else + raise GenericError(act_str) + + # Done + return [act_str] if as_list else act_str + + +def get_os_name(as_list=False, check=True): + """Build OS display name, returns str. NOTE: If check=True then an exception is raised if the OS version is outdated or unsupported. @@ -150,7 +183,14 @@ def show_os_name(check=True): raise GenericError(f'{display_name} (unsupported)') # Done - print(display_name) + return [display_name] if as_list else display_name + + +def show_alert_box(message, title=None): + """Show Windows alert box with message.""" + title = title if title else f'{KIT_NAME_FULL} Warning' + message_box = ctypes.windll.user32.MessageBoxW + message_box(None, message, title, 0x00001030) # Registry Functions @@ -381,6 +421,72 @@ def enable_safemode_msi(): run_program(cmd) +# Secure Boot Functions +def is_booted_uefi(): + """Check if booted UEFI or legacy, returns bool.""" + kernel = ctypes.windll.kernel32 + firmware_type = ctypes.c_uint() + + # Get value from kernel32 API (firmware_type is updated by the call) + try: + kernel.GetFirmwareType(ctypes.byref(firmware_type)) + except Exception: # pylint: disable=broad-except + # Ignore and set firmware_type back to zero + firmware_type = ctypes.c_uint(0) + + # Check result + return firmware_type.value == 2 + + +def is_secure_boot_enabled(raise_exceptions=False, show_alert=False): + """Check if Secure Boot is enabled, returns bool. + + If raise_exceptions is True then an exception is raised with details. + If show_alert is True a popup alert box is shown if it's not enabled. + """ + booted_uefi = is_booted_uefi() + cmd = ['PowerShell', '-Command', 'Confirm-SecureBootUEFI'] + enabled = False + msg_error = None + msg_warning = None + + # Bail early + if OS_VERSION < 8: + if raise_exceptions: + raise GenericWarning(f'Secure Boot not available for {OS_VERSION}') + return False + + # Check results + proc = run_program(cmd, check=False) + if proc.returncode: + # Something went wrong + if booted_uefi: + msg_warning = 'UNKNOWN' + else: + msg_warning = 'DISABLED\n\nOS installed LEGACY' + else: + # Command completed + enabled = 'True' in proc.stdout + if 'False' in proc.stdout: + msg_error = 'ERROR' + else: + msg_warning = 'UNKNOWN' + + # Show popup and/or raise exceptions as necessary + for msg, exc in ((msg_error, GenericError), (msg_warning, GenericWarning)): + if not msg: + continue + msg = f'Secure Boot {msg}' + if show_alert: + show_alert_box(msg) + if raise_exceptions: + raise exc(msg) + break + + # Done + return enabled + + # Service Functions def disable_service(service_name): """Set service startup to disabled.""" @@ -451,19 +557,5 @@ def stop_service(service_name): raise GenericError(f'Failed to stop service {service_name}') -# Date / Time functions -def get_timezone(): - """Get current timezone using tzutil, returns str.""" - cmd = ['tzutil', '/g'] - proc = run_program(cmd, check=False) - return proc.stdout - - -def set_timezone(zone): - """Set current timezone using tzutil.""" - cmd = ['tzutil', '/s', zone] - run_program(cmd, check=False) - - if __name__ == '__main__': print("This file is not meant to be called directly.") diff --git a/scripts/wk/setup/win.py b/scripts/wk/setup/win.py index c5621a3c..c0d9f6b2 100644 --- a/scripts/wk/setup/win.py +++ b/scripts/wk/setup/win.py @@ -44,10 +44,12 @@ if platform.system() == 'Windows': from wk.os.win import ( OS_VERSION, activate_with_bios, + get_os_activation, + get_os_name, + is_secure_boot_enabled, reg_read_value, reg_set_value, reg_write_settings, - show_os_name, ) from wk.repairs.win import ( backup_all_browser_profiles, @@ -66,10 +68,12 @@ else: """No-op function.""" # wk.os.win activate_with_bios = no_op + get_os_activation = no_op + get_os_name = no_op + is_secure_boot_enabled = no_op reg_read_value = no_op reg_set_value = no_op reg_write_settings = no_op - show_os_name = no_op # wk.repairs.win backup_all_browser_profiles = no_op backup_registry = no_op @@ -559,9 +563,22 @@ def auto_restore_default_uac(): TRY_PRINT.run('User Account Control...', restore_default_uac) +def auto_show_os_activation(): + """Display OS Name.""" + TRY_PRINT.run('Activation...', get_os_activation, as_list=True) + + def auto_show_os_name(): """Display OS Name.""" - TRY_PRINT.run('Operating System...', show_os_name) + TRY_PRINT.run('Operating System...', get_os_name, as_list=True) + + +def auto_show_secure_boot_status(): + """Display Secure Boot status.""" + TRY_PRINT.run( + 'Secure Boot...', is_secure_boot_enabled, + raise_exceptions=True, show_alert=True, + ) def auto_windows_temp_fix(): @@ -569,8 +586,6 @@ def auto_windows_temp_fix(): TRY_PRINT.run(r'Windows\Temp fix...', fix_windows_temp) - - # Configure Functions def config_explorer(): """Configure Windows Explorer and restart the process.""" From 526f6e26ebcdd43939b5a527cb35587cadc10f08 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Wed, 29 Sep 2021 01:24:07 -0600 Subject: [PATCH 32/40] Add installed RAM sections --- scripts/auto_setup.py | 2 +- scripts/wk/os/win.py | 20 +++++++++++++++++++- scripts/wk/setup/win.py | 11 ++++++++++- 3 files changed, 30 insertions(+), 3 deletions(-) diff --git a/scripts/auto_setup.py b/scripts/auto_setup.py index 5d614f33..7d2c1f42 100644 --- a/scripts/auto_setup.py +++ b/scripts/auto_setup.py @@ -140,7 +140,7 @@ BASE_MENUS = { MenuEntry('Operating System', 'auto_show_os_name'), MenuEntry('Windows Activation', 'auto_show_activation'), MenuEntry('Secure Boot', 'auto_show_secure_boot_status'), - MenuEntry('Installed RAM', no_op), + MenuEntry('Installed RAM', 'auto_show_installed_ram'), MenuEntry('Storage Volumes', no_op), MenuEntry('Virus Protection', no_op), MenuEntry('Partitions 4K Aligned', no_op), diff --git a/scripts/wk/os/win.py b/scripts/wk/os/win.py index 41b52a26..b5efeaa7 100644 --- a/scripts/wk/os/win.py +++ b/scripts/wk/os/win.py @@ -24,7 +24,7 @@ from wk.cfg.windows_builds import ( WINDOWS_BUILDS, ) from wk.exe import run_program -from wk.std import GenericError, GenericWarning, sleep +from wk.std import GenericError, GenericWarning, bytes_to_string, sleep # STATIC VARIABLES @@ -65,6 +65,8 @@ KNOWN_HIVE_NAMES = { winreg.HKEY_USERS: 'HKEY_USERS', } OS_VERSION = float(platform.win32_ver()[0]) +RAM_OK = 5.5 * 1024**3 # ~6 GiB assuming a bit of shared memory +RAM_WARNING = 3.5 * 1024**3 # ~4 GiB assuming a bit of shared memory REG_MSISERVER = r'HKLM\SYSTEM\CurrentControlSet\Control\SafeBoot\Network\MSIServer' SLMGR = pathlib.Path(f'{os.environ.get("SYSTEMROOT")}/System32/slmgr.vbs') @@ -143,6 +145,22 @@ def set_timezone(zone): # Info Functions +def get_installed_ram(as_list=False, raise_exceptions=False): + """Get installed RAM.""" + mem = psutil.virtual_memory() + mem_str = bytes_to_string(mem.total, decimals=1) + + # Raise exception if necessary + if raise_exceptions: + if RAM_OK > mem.total >= RAM_WARNING: + raise GenericWarning(mem_str) + if mem.total > RAM_WARNING: + raise GenericError(mem_str) + + # Done + return [mem_str] if as_list else mem_str + + def get_os_activation(as_list=False, check=True): """Get OS activation status, returns str. diff --git a/scripts/wk/setup/win.py b/scripts/wk/setup/win.py index c0d9f6b2..acda54b1 100644 --- a/scripts/wk/setup/win.py +++ b/scripts/wk/setup/win.py @@ -44,6 +44,7 @@ if platform.system() == 'Windows': from wk.os.win import ( OS_VERSION, activate_with_bios, + get_installed_ram, get_os_activation, get_os_name, is_secure_boot_enabled, @@ -68,6 +69,7 @@ else: """No-op function.""" # wk.os.win activate_with_bios = no_op + get_installed_ram = no_op get_os_activation = no_op get_os_name = no_op is_secure_boot_enabled = no_op @@ -563,8 +565,15 @@ def auto_restore_default_uac(): TRY_PRINT.run('User Account Control...', restore_default_uac) +def auto_show_installed_ram(): + """Display installed RAM.""" + TRY_PRINT.run('Installed RAM...', get_installed_ram, + as_list=True, raise_exceptions=True, + ) + + def auto_show_os_activation(): - """Display OS Name.""" + """Display OS activation status.""" TRY_PRINT.run('Activation...', get_os_activation, as_list=True) From 30e43b9814f6947e7d9503e9f0b12e97e008099a Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Wed, 29 Sep 2021 19:56:49 -0600 Subject: [PATCH 33/40] Add storage status sections --- scripts/auto_setup.py | 4 +-- scripts/get_raw_disks.ps1 | 3 +++ scripts/wk/os/win.py | 55 +++++++++++++++++++++++++++++++++++++-- scripts/wk/setup/win.py | 19 ++++++++++++++ 4 files changed, 77 insertions(+), 4 deletions(-) create mode 100644 scripts/get_raw_disks.ps1 diff --git a/scripts/auto_setup.py b/scripts/auto_setup.py index 7d2c1f42..3728c53d 100644 --- a/scripts/auto_setup.py +++ b/scripts/auto_setup.py @@ -138,10 +138,10 @@ BASE_MENUS = { ), 'System Summary': ( MenuEntry('Operating System', 'auto_show_os_name'), - MenuEntry('Windows Activation', 'auto_show_activation'), + MenuEntry('Windows Activation', 'auto_show_os_activation'), MenuEntry('Secure Boot', 'auto_show_secure_boot_status'), MenuEntry('Installed RAM', 'auto_show_installed_ram'), - MenuEntry('Storage Volumes', no_op), + MenuEntry('Storage Status', 'auto_show_storage_status'), MenuEntry('Virus Protection', no_op), MenuEntry('Partitions 4K Aligned', no_op), ), diff --git a/scripts/get_raw_disks.ps1 b/scripts/get_raw_disks.ps1 new file mode 100644 index 00000000..afdb9300 --- /dev/null +++ b/scripts/get_raw_disks.ps1 @@ -0,0 +1,3 @@ +# Wizard Kit: Get RAW disks + +Get-Disk | Where-Object {$_.PartitionStyle -eq "RAW"} | Select FriendlyName,Size,PartitionStyle | ConvertTo-JSON \ No newline at end of file diff --git a/scripts/wk/os/win.py b/scripts/wk/os/win.py index b5efeaa7..e3a7bc7c 100644 --- a/scripts/wk/os/win.py +++ b/scripts/wk/os/win.py @@ -23,8 +23,15 @@ from wk.cfg.windows_builds import ( OUTDATED_BUILD_NUMBERS, WINDOWS_BUILDS, ) -from wk.exe import run_program -from wk.std import GenericError, GenericWarning, bytes_to_string, sleep +from wk.exe import get_json_from_command, run_program +from wk.kit.tools import find_kit_dir +from wk.std import ( + GenericError, + GenericWarning, + bytes_to_string, + color_string, + sleep, + ) # STATIC VARIABLES @@ -204,6 +211,50 @@ def get_os_name(as_list=False, check=True): return [display_name] if as_list else display_name +def get_raw_disks(): + """Get all disks without a partiton table, returns list.""" + script_path = find_kit_dir('Scripts').joinpath('get_raw_disks.ps1') + cmd = ['PowerShell', '-ExecutionPolicy', 'Bypass', '-File', script_path] + json_data = get_json_from_command(cmd) + raw_disks = [] + + # Fix JSON if only one disk was detected + if isinstance(json_data, dict): + json_data = [json_data] + + # Parse JSON + for disk in json_data: + size_str = bytes_to_string(int(disk["Size"]), use_binary=False) + raw_disks.append(f'{disk["FriendlyName"]} ({size_str})') + + # Done + return raw_disks + + +def get_volume_usage(use_colors=False): + """Get space usage info for all fixed volumes, returns list.""" + report = [] + for disk in psutil.disk_partitions(): + if 'fixed' not in disk.opts: + continue + total, _, free, percent = psutil.disk_usage(disk.device) + color = None + if percent > 85: + color = 'RED' + elif percent > 75: + color = 'YELLOW' + display_str = ( + f'{free/total:>5.2f}% Free' + f' ({bytes_to_string(free, 2):>10} / {bytes_to_string(total, 2):>10})' + ) + if use_colors: + display_str = color_string(display_str, color) + report.append(f'{disk.device} {display_str}') + + # Done + return report + + def show_alert_box(message, title=None): """Show Windows alert box with message.""" title = title if title else f'{KIT_NAME_FULL} Warning' diff --git a/scripts/wk/setup/win.py b/scripts/wk/setup/win.py index acda54b1..a1c75c6d 100644 --- a/scripts/wk/setup/win.py +++ b/scripts/wk/setup/win.py @@ -47,6 +47,8 @@ if platform.system() == 'Windows': get_installed_ram, get_os_activation, get_os_name, + get_raw_disks, + get_volume_usage, is_secure_boot_enabled, reg_read_value, reg_set_value, @@ -72,6 +74,8 @@ else: get_installed_ram = no_op get_os_activation = no_op get_os_name = no_op + get_raw_disks = no_op + get_volume_usage = no_op is_secure_boot_enabled = no_op reg_read_value = no_op reg_set_value = no_op @@ -590,6 +594,11 @@ def auto_show_secure_boot_status(): ) +def auto_show_storage_status(): + """Display storage status.""" + TRY_PRINT.run('Storage Status...', get_storage_status) + + def auto_windows_temp_fix(): """Restore default ACLs for Windows\\Temp.""" TRY_PRINT.run(r'Windows\Temp fix...', fix_windows_temp) @@ -924,6 +933,16 @@ def get_firefox_default_profile(profiles_ini): return default_profile +def get_storage_status(): + """Get storage status for fixed disks, returns list.""" + report = get_volume_usage(use_colors=True) + for disk in get_raw_disks(): + report.append(color_string(f'Uninitialized Disk: {disk}', 'RED')) + + # Done + return report + + # Tool Functions def export_aida64_report(): """Export AIDA64 report.""" From f1645f80e6d5544ed23dc0a7d4cfab4de338c7a4 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Wed, 29 Sep 2021 20:27:35 -0600 Subject: [PATCH 34/40] Add AV check to Auto Setup --- scripts/auto_setup.py | 2 +- scripts/wk/os/win.py | 41 +++++++++++++++++++++++++++++++++++++++++ scripts/wk/setup/win.py | 8 +++++++- 3 files changed, 49 insertions(+), 2 deletions(-) diff --git a/scripts/auto_setup.py b/scripts/auto_setup.py index 3728c53d..2d75585c 100644 --- a/scripts/auto_setup.py +++ b/scripts/auto_setup.py @@ -142,7 +142,7 @@ BASE_MENUS = { MenuEntry('Secure Boot', 'auto_show_secure_boot_status'), MenuEntry('Installed RAM', 'auto_show_installed_ram'), MenuEntry('Storage Status', 'auto_show_storage_status'), - MenuEntry('Virus Protection', no_op), + MenuEntry('Virus Protection', 'auto_show_installed_antivirus'), MenuEntry('Partitions 4K Aligned', no_op), ), 'Run Programs': ( diff --git a/scripts/wk/os/win.py b/scripts/wk/os/win.py index e3a7bc7c..50ea654e 100644 --- a/scripts/wk/os/win.py +++ b/scripts/wk/os/win.py @@ -152,6 +152,47 @@ def set_timezone(zone): # Info Functions +def get_installed_antivirus(): + """Get list of installed antivirus programs, returns list.""" + cmd = [ + 'WMIC', r'/namespace:\\root\SecurityCenter2', + 'path', 'AntivirusProduct', + 'get', 'displayName', '/value', + ] + products = [] + report = [] + + # Get list of products + proc = run_program(cmd) + for line in proc.stdout.splitlines(): + line = line.strip() + if '=' in line: + products.append(line.split('=')[1]) + + # Check product(s) status + for product in sorted(products): + cmd = [ + 'WMIC', r'/namespace:\\root\SecurityCenter2', + 'path', 'AntivirusProduct', + 'where', f'displayName="{product}"', + 'get', 'productState', '/value', + ] + proc = run_program(cmd) + state = proc.stdout.split('=')[1] + state = hex(int(state)) + if str(state)[3:5] not in ['10', '11']: + report.append(color_string(f'[Disabled] {product}', 'YELLOW')) + else: + report.append(product) + + # Final check + if not report: + report.append(color_string('No products detected', 'RED')) + + # Done + return report + + def get_installed_ram(as_list=False, raise_exceptions=False): """Get installed RAM.""" mem = psutil.virtual_memory() diff --git a/scripts/wk/setup/win.py b/scripts/wk/setup/win.py index a1c75c6d..a10b2ec0 100644 --- a/scripts/wk/setup/win.py +++ b/scripts/wk/setup/win.py @@ -44,13 +44,13 @@ if platform.system() == 'Windows': from wk.os.win import ( OS_VERSION, activate_with_bios, + get_installed_antivirus, get_installed_ram, get_os_activation, get_os_name, get_raw_disks, get_volume_usage, is_secure_boot_enabled, - reg_read_value, reg_set_value, reg_write_settings, ) @@ -71,6 +71,7 @@ else: """No-op function.""" # wk.os.win activate_with_bios = no_op + get_installed_antivirus = no_op get_installed_ram = no_op get_os_activation = no_op get_os_name = no_op @@ -569,6 +570,11 @@ def auto_restore_default_uac(): TRY_PRINT.run('User Account Control...', restore_default_uac) +def auto_show_installed_antivirus(): + """Display installed antivirus.""" + TRY_PRINT.run('Virus Protection...', get_installed_antivirus) + + def auto_show_installed_ram(): """Display installed RAM.""" TRY_PRINT.run('Installed RAM...', get_installed_ram, From eacab48c1e14d7684e4b0cf1e42ecf7342c65b8a Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Wed, 29 Sep 2021 20:28:07 -0600 Subject: [PATCH 35/40] Add 4K alignment checks to Auto Setup --- scripts/auto_setup.py | 2 +- scripts/wk/os/win.py | 17 +++++++++++++++++ scripts/wk/setup/win.py | 7 +++++++ 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/scripts/auto_setup.py b/scripts/auto_setup.py index 2d75585c..458d39c0 100644 --- a/scripts/auto_setup.py +++ b/scripts/auto_setup.py @@ -143,7 +143,7 @@ BASE_MENUS = { MenuEntry('Installed RAM', 'auto_show_installed_ram'), MenuEntry('Storage Status', 'auto_show_storage_status'), MenuEntry('Virus Protection', 'auto_show_installed_antivirus'), - MenuEntry('Partitions 4K Aligned', no_op), + MenuEntry('Partitions 4K Aligned', 'auto_show_4k_alignment_check'), ), 'Run Programs': ( MenuEntry('Device Manager', no_op), diff --git a/scripts/wk/os/win.py b/scripts/wk/os/win.py index 50ea654e..4d73c21e 100644 --- a/scripts/wk/os/win.py +++ b/scripts/wk/os/win.py @@ -152,6 +152,23 @@ def set_timezone(zone): # Info Functions +def check_4k_alignment(show_alert=False): + """Check if all partitions are 4K aligned, returns book.""" + cmd = ['WMIC', 'partition', 'get', 'StartingOffset'] + + # Check offsets + proc = run_program(cmd) + for offset in proc.stdout.splitlines(): + offset = offset.strip() + if not offset.isnumeric(): + continue + if int(offset) % 4096 != 0: + # Not aligned + if show_alert: + show_alert_box('One or more partitions are not 4K aligned') + raise GenericError('One or more partitions are not 4K aligned') + + def get_installed_antivirus(): """Get list of installed antivirus programs, returns list.""" cmd = [ diff --git a/scripts/wk/setup/win.py b/scripts/wk/setup/win.py index a10b2ec0..3cb1ff18 100644 --- a/scripts/wk/setup/win.py +++ b/scripts/wk/setup/win.py @@ -44,6 +44,7 @@ if platform.system() == 'Windows': from wk.os.win import ( OS_VERSION, activate_with_bios, + check_4k_alignment, get_installed_antivirus, get_installed_ram, get_os_activation, @@ -71,6 +72,7 @@ else: """No-op function.""" # wk.os.win activate_with_bios = no_op + check_4k_alignment = no_op get_installed_antivirus = no_op get_installed_ram = no_op get_os_activation = no_op @@ -570,6 +572,11 @@ def auto_restore_default_uac(): TRY_PRINT.run('User Account Control...', restore_default_uac) +def auto_show_4k_alignment_check(): + """Display 4K alignment check.""" + TRY_PRINT.run('4K alignment Check...', check_4k_alignment, show_alert=True) + + def auto_show_installed_antivirus(): """Display installed antivirus.""" TRY_PRINT.run('Virus Protection...', get_installed_antivirus) From bd0a03e2834774a988f83b9a9019ac542f7c01e9 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Wed, 29 Sep 2021 20:44:50 -0600 Subject: [PATCH 36/40] Combine browser configuration menu options --- scripts/auto_setup.py | 5 ++--- scripts/wk/setup/win.py | 41 +++++++++++++++++++++++------------------ 2 files changed, 25 insertions(+), 21 deletions(-) diff --git a/scripts/auto_setup.py b/scripts/auto_setup.py index 458d39c0..b390a450 100644 --- a/scripts/auto_setup.py +++ b/scripts/auto_setup.py @@ -118,19 +118,18 @@ BASE_MENUS = { MenuEntry('Software Bundle', 'auto_install_software_bundle'), ), 'Configure System': ( - MenuEntry('Chrome Notifications', 'auto_disable_chrome_notifications'), + MenuEntry('Configure Browsers', 'auto_config_browsers'), MenuEntry('Open Shell', 'auto_config_open_shell'), - MenuEntry('uBlock Origin', 'auto_enable_ublock_origin'), MenuEntry('Enable BSoD MiniDumps', 'auto_enable_bsod_minidumps'), MenuEntry('Enable RegBack', 'auto_enable_regback'), MenuEntry('Enable System Restore', 'auto_system_restore_enable'), MenuEntry('Set System Restore Size', 'auto_system_restore_set_size'), - MenuEntry('Create System Restore', 'auto_system_restore_create'), MenuEntry('Enable Windows Updates', 'auto_windows_updates_enable'), MenuEntry('User Account Control', 'auto_restore_default_uac'), MenuEntry('Windows Activation', 'auto_activate_windows'), MenuEntry('Windows Explorer', 'auto_config_explorer'), MenuEntry(r'Windows\Temp Fix', 'auto_windows_temp_fix'), + MenuEntry('Create System Restore', 'auto_system_restore_create'), ), 'System Information': ( MenuEntry('AIDA64 Report', 'auto_export_aida64_report'), diff --git a/scripts/wk/setup/win.py b/scripts/wk/setup/win.py index 3cb1ff18..6b1b4b80 100644 --- a/scripts/wk/setup/win.py +++ b/scripts/wk/setup/win.py @@ -505,6 +505,23 @@ def auto_activate_windows(): TRY_PRINT.run('Windows Activation...', activate_with_bios) +def auto_config_browsers(): + """Configure Browsers.""" + prompt = ' Press Enter to continue...' + TRY_PRINT.run('Chrome Notifications...', disable_chrome_notifications) + TRY_PRINT.run( + 'uBlock Origin...', enable_ublock_origin, msg_good='STARTED', + ) + TRY_PRINT.run( + 'Set default browser...', set_default_browser, msg_good='STARTED', + ) + print(prompt, end='', flush=True) + pause('') + + # Move cursor to beginning of the previous line and clear prompt + print(f'\033[F\r{" "*len(prompt)}\r', end='', flush=True) + + def auto_config_explorer(): """Configure Windows Explorer and restart the process.""" TRY_PRINT.run('Windows Explorer...', config_explorer) @@ -515,24 +532,6 @@ def auto_config_open_shell(): TRY_PRINT.run('Open Shell...', reg_write_settings, REG_OPEN_SHELL_SETTINGS) -def auto_disable_chrome_notifications(): - """Disable notifications in Google Chrome.""" - TRY_PRINT.run('Chrome Notifications...', disable_chrome_notifications) - - -def auto_enable_ublock_origin(): - """Enable uBlock Origin in supported browsers.""" - prompt = ' Press Enter to continue...' - TRY_PRINT.run( - 'uBlock Origin...', enable_ublock_origin, msg_good='STARTED', - ) - print(prompt, end='', flush=True) - pause('') - - # Move cursor to beginning of the previous line and clear prompt - print(f'\033[F\r{" "*len(prompt)}\r', end='', flush=True) - - def auto_export_aida64_report(): """Export AIDA64 reports.""" TRY_PRINT.run('AIDA64 Report...', export_aida64_report) @@ -956,6 +955,12 @@ def get_storage_status(): return report +def set_default_browser(): + """Open Windows Settings to the default apps section.""" + cmd = ['start', '', 'ms-settings:defaultapps'] + popen_program(cmd, shell=True) + + # Tool Functions def export_aida64_report(): """Export AIDA64 report.""" From 02055c5b30d36641038749d5743f0399ff82a2f3 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Thu, 30 Sep 2021 02:00:16 -0600 Subject: [PATCH 37/40] Add open programs sections to Auto Setup --- scripts/auto_setup.py | 10 +++---- scripts/wk/setup/win.py | 65 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+), 5 deletions(-) diff --git a/scripts/auto_setup.py b/scripts/auto_setup.py index b390a450..406abab3 100644 --- a/scripts/auto_setup.py +++ b/scripts/auto_setup.py @@ -145,11 +145,11 @@ BASE_MENUS = { MenuEntry('Partitions 4K Aligned', 'auto_show_4k_alignment_check'), ), 'Run Programs': ( - MenuEntry('Device Manager', no_op), - MenuEntry('HWiNFO Sensors', no_op), - MenuEntry('Windows Updates', no_op), - MenuEntry('Windows Activation', no_op), - MenuEntry('XMPlay', no_op), + MenuEntry('Device Manager', 'auto_open_device_manager'), + MenuEntry('HWiNFO Sensors', 'auto_open_hwinfo_sensors'), + MenuEntry('Windows Activation', 'auto_open_windows_activation'), + MenuEntry('Windows Updates', 'auto_open_windows_updates'), + MenuEntry('XMPlay', 'auto_open_xmplay'), ), }, 'Actions': ( diff --git a/scripts/wk/setup/win.py b/scripts/wk/setup/win.py index 6b1b4b80..c20cdd9c 100644 --- a/scripts/wk/setup/win.py +++ b/scripts/wk/setup/win.py @@ -1,4 +1,5 @@ """WizardKit: Setup - Windows""" +# pylint: disable=too-many-lines # vim: sts=2 sw=2 ts=2 import configparser @@ -51,6 +52,7 @@ if platform.system() == 'Windows': get_os_name, get_raw_disks, get_volume_usage, + is_activated, is_secure_boot_enabled, reg_set_value, reg_write_settings, @@ -79,6 +81,7 @@ else: get_os_name = no_op get_raw_disks = no_op get_volume_usage = no_op + is_activated = no_op is_secure_boot_enabled = no_op reg_read_value = no_op reg_set_value = no_op @@ -566,6 +569,32 @@ def auto_install_vcredists(): TRY_PRINT.run('Visual C++ Runtimes...', install_vcredists) +def auto_open_device_manager(): + """Open Device Manager.""" + TRY_PRINT.run('Device Manager...', open_device_manager) + + +def auto_open_hwinfo_sensors(): + """Open HWiNFO Sensors.""" + TRY_PRINT.run('HWiNFO Sensors...', open_hwinfo_sensors) + + +def auto_open_windows_activation(): + """Open Windows Activation.""" + if not is_activated(): + TRY_PRINT.run('Windows Activation...', open_windows_activation) + + +def auto_open_windows_updates(): + """Open Windows Updates.""" + TRY_PRINT.run('Windows Updates...', open_windows_updates) + + +def auto_open_xmplay(): + """Open XMPlay.""" + TRY_PRINT.run('XMPlay...', open_xmplay) + + def auto_restore_default_uac(): """Restore default UAC settings.""" TRY_PRINT.run('User Account Control...', restore_default_uac) @@ -982,5 +1011,41 @@ def export_aida64_report(): raise GenericError('Error(s) encountered exporting report.') +def open_device_manager(): + """Open Device Manager.""" + popen_program(['mmc', 'devmgmt.msc']) + + +def open_hwinfo_sensors(): + """Open HWiNFO sensors.""" + hwinfo_path = get_tool_path('HWiNFO', 'HWiNFO') + base_config = hwinfo_path.with_name('general.ini') + + # Write new config to disk + with open(hwinfo_path.with_suffix('.ini'), 'w', encoding='utf-8') as _f: + _f.write( + f'{base_config.read_text(encoding="utf-8")}\n' + 'SensorsOnly=1\nSummaryOnly=0\n' + ) + + # Open HWiNFO + run_tool('HWiNFO', 'HWiNFO', popen=True) + + +def open_windows_activation(): + """Open Windows Activation.""" + popen_program(['slui']) + + +def open_windows_updates(): + """Open Windows Updates.""" + popen_program(['control', '/name', 'Microsoft.WindowsUpdate']) + + +def open_xmplay(): + """Open XMPlay.""" + run_tool('XMPlay', 'XMPlay', 'music.7z', cbin=True, cwd=True, popen=True) + + if __name__ == '__main__': print("This file is not meant to be called directly.") From 0fc5c4b14686e922cd4bb8f06647b337af80fbb9 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Thu, 30 Sep 2021 03:38:25 -0600 Subject: [PATCH 38/40] Add initial questions to Auto Setup --- scripts/auto_setup.py | 17 +++++------ scripts/wk/setup/win.py | 63 ++++++++++++++++++++++++++++++++++------- 2 files changed, 60 insertions(+), 20 deletions(-) diff --git a/scripts/auto_setup.py b/scripts/auto_setup.py index 406abab3..fa4cd114 100644 --- a/scripts/auto_setup.py +++ b/scripts/auto_setup.py @@ -11,6 +11,7 @@ import wk # pylint: disable=wrong-import-position # STATIC VARIABLES PRESETS = { + 'Default': {}, # Will be built at runtime using BASE_MENUS 'Additional User': { 'Configure System': ( 'Chrome Notifications', @@ -31,7 +32,7 @@ PRESETS = { 'Windows Activation', 'Secure Boot', 'Installed RAM', - 'Storage Volumes', + 'Storage Status', 'Virus Protection', 'Partitions 4K Aligned', ), @@ -52,7 +53,7 @@ PRESETS = { 'Windows Activation', 'Secure Boot', 'Installed RAM', - 'Storage Volumes', + 'Storage Status', 'Virus Protection', 'Partitions 4K Aligned', ), @@ -76,7 +77,7 @@ PRESETS = { 'Windows Activation', 'Secure Boot', 'Installed RAM', - 'Storage Volumes', + 'Storage Status', 'Virus Protection', 'Installed Office', 'Partitions 4K Aligned', @@ -88,19 +89,15 @@ PRESETS = { class MenuEntry(): # pylint: disable=too-few-public-methods """Simple class to allow cleaner code below.""" - def __init__(self, name, function=None, **kwargs): + def __init__(self, name, function=None, selected=True, **kwargs): self.name = name self.details = { 'Function': function, - 'Selected': True, + 'Selected': selected, **kwargs, } -# TODO: DELETEME -def no_op(*args): - """No Op""" - # STATIC VARIABLES BASE_MENUS = { 'Groups': { @@ -113,7 +110,7 @@ BASE_MENUS = { 'Install Software': ( MenuEntry('Visual C++ Runtimes', 'auto_install_vcredists'), MenuEntry('Firefox', 'auto_install_firefox'), - MenuEntry('LibreOffice', 'auto_install_libreoffice'), + MenuEntry('LibreOffice', 'auto_install_libreoffice', selected=False), MenuEntry('Open Shell', 'auto_install_open_shell'), MenuEntry('Software Bundle', 'auto_install_software_bundle'), ), diff --git a/scripts/wk/setup/win.py b/scripts/wk/setup/win.py index c20cdd9c..ef6e36c0 100644 --- a/scripts/wk/setup/win.py +++ b/scripts/wk/setup/win.py @@ -33,6 +33,7 @@ from wk.std import ( clear_screen, color_string, pause, + print_error, print_info, print_standard, print_warning, @@ -299,6 +300,12 @@ def build_menus(base_menus, title, presets): sys.modules[__name__], _function, ) + # Update presets + for group, entries in base_menus['Groups'].items(): + presets['Default'][group] = tuple( + entry.name for entry in entries if entry.details['Selected'] + ) + # Update presets Menu MENU_PRESETS.title = f'{title}\n{color_string("Load Preset", "GREEN")}' MENU_PRESETS.add_option('Default') @@ -312,23 +319,42 @@ def build_menus(base_menus, title, presets): return menus +def check_os_and_set_menu_title(title): + """Check OS version and update title for menus, returns str.""" + color = None + os_name = get_os_name(check=False) + print_standard(f'Operating System: {os_name}') + + # Check support status and set color + try: + get_os_name() + except GenericWarning: + # Outdated version + print_warning('OS version is outdated, updating is recommended.') + if not ask('Continue anyway?'): + abort() + color = 'YELLOW' + except GenericError: + # Unsupported version + print_error('OS version is unsupported, updating is recommended.') + if not ask('Continue anyway? (NOT RECOMMENDED)'): + abort() + color = 'RED' + + # Done + return f'{title} ({color_string(os_name, color)})' + + def load_preset(menus, presets): - """Load menu settings from preset.""" + """Load menu settings from preset, returns selection (str).""" selection = MENU_PRESETS.simple_select() # Exit early if 'Main Menu' in selection: - return + return None if 'Quit' in selection: raise SystemExit - # Default case - if 'Default' in selection: - for menu in menus.values(): - for name in menu.options: - menu.options[name]['Selected'] = True - return - # Load preset preset = presets[selection[0]] for group, menu in menus.items(): @@ -337,6 +363,9 @@ def load_preset(menus, presets): value = group_enabled and name in preset[group] menu.options[name]['Selected'] = value + # Done + return selection[0] + def run_auto_setup(base_menus, presets): """Run Auto Setup.""" @@ -346,11 +375,24 @@ def run_auto_setup(base_menus, presets): set_title(title) print_info(title) print('') + print_standard('Initializing...') + + # Check OS and update title for menus + title = check_os_and_set_menu_title(title) # Generate menus - print_standard('Initializing...') menus = build_menus(base_menus, title, presets) + # Get setup preset and ask initial questions + MENU_PRESETS.actions['Main Menu'].update({'Disabled':True, 'Hidden':True}) + selection = load_preset(menus, presets) + MENU_PRESETS.actions['Main Menu'].update({'Disabled':False, 'Hidden':False}) + clear_screen() + print_standard(f'{title}') + print('') + if selection == 'Default' and ask('Install LibreOffice?'): + menus['Install Software'].options['LibreOffice']['Selected'] = True + # Show Menu show_main_menu(base_menus, menus, presets) @@ -1044,6 +1086,7 @@ def open_windows_updates(): def open_xmplay(): """Open XMPlay.""" + sleep(2) run_tool('XMPlay', 'XMPlay', 'music.7z', cbin=True, cwd=True, popen=True) From 7391c863f99fa6610b45de5bc042fb812c860322 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Thu, 30 Sep 2021 04:20:39 -0600 Subject: [PATCH 39/40] Old code cleanup --- scripts/check_disk.py | 4 +- scripts/ddrescue-tui.py | 5 +- scripts/hw-diags.py | 5 +- scripts/outer_scripts_to_review/check_disk.py | 57 --- scripts/outer_scripts_to_review/dism.py | 58 --- .../install_sw_bundle.py | 63 ---- .../install_vcredists.py | 35 -- .../system_diagnostics.py | 173 --------- .../outer_scripts_to_review/system_setup.py | 355 ------------------ .../transferred_keys.py | 29 -- scripts/outer_scripts_to_review/update_kit.py | 143 ------- .../user_data_transfer.py | 67 ---- .../windows_updates.py | 46 --- .../winpe_root_menu.py | 23 -- scripts/sfc_scan.py | 2 +- 15 files changed, 9 insertions(+), 1056 deletions(-) delete mode 100644 scripts/outer_scripts_to_review/check_disk.py delete mode 100644 scripts/outer_scripts_to_review/dism.py delete mode 100644 scripts/outer_scripts_to_review/install_sw_bundle.py delete mode 100644 scripts/outer_scripts_to_review/install_vcredists.py delete mode 100644 scripts/outer_scripts_to_review/system_diagnostics.py delete mode 100644 scripts/outer_scripts_to_review/system_setup.py delete mode 100644 scripts/outer_scripts_to_review/transferred_keys.py delete mode 100644 scripts/outer_scripts_to_review/update_kit.py delete mode 100644 scripts/outer_scripts_to_review/user_data_transfer.py delete mode 100644 scripts/outer_scripts_to_review/windows_updates.py delete mode 100644 scripts/outer_scripts_to_review/winpe_root_menu.py diff --git a/scripts/check_disk.py b/scripts/check_disk.py index 7e6810c9..1682d94f 100644 --- a/scripts/check_disk.py +++ b/scripts/check_disk.py @@ -23,10 +23,10 @@ def main(): # Run or schedule scan if 'Offline' in selection[0]: - function = wk.os.win.run_chkdsk_offline + function = wk.repairs.win.run_chkdsk_offline msg_good = 'Scheduled' else: - function = wk.os.win.run_chkdsk_online + function = wk.repairs.win.run_chkdsk_online msg_good = 'No issues detected' try_print.run( message=f'CHKDSK ({os.environ.get("SYSTEMDRIVE")})...', diff --git a/scripts/ddrescue-tui.py b/scripts/ddrescue-tui.py index 289b49d9..413e81e6 100755 --- a/scripts/ddrescue-tui.py +++ b/scripts/ddrescue-tui.py @@ -1,11 +1,12 @@ #!/usr/bin/env python3 """Wizard Kit: ddrescue TUI""" +# pylint: disable=invalid-name # vim: sts=2 sw=2 ts=2 -import wk - from docopt import docopt +import wk + if __name__ == '__main__': try: diff --git a/scripts/hw-diags.py b/scripts/hw-diags.py index 1dc17294..c72fd91f 100755 --- a/scripts/hw-diags.py +++ b/scripts/hw-diags.py @@ -1,11 +1,12 @@ #!/usr/bin/env python3 """Wizard Kit: Hardware Diagnostics""" +# pylint: disable=invalid-name # vim: sts=2 sw=2 ts=2 -import wk - from docopt import docopt +import wk + if __name__ == '__main__': try: diff --git a/scripts/outer_scripts_to_review/check_disk.py b/scripts/outer_scripts_to_review/check_disk.py deleted file mode 100644 index fe18650b..00000000 --- a/scripts/outer_scripts_to_review/check_disk.py +++ /dev/null @@ -1,57 +0,0 @@ -# Wizard Kit: Check or repair the %SYSTEMDRIVE% filesystem via CHKDSK - -import os -import sys - -# Init -sys.path.append(os.path.dirname(os.path.realpath(__file__))) -from functions.repairs import * -init_global_vars() -os.system('title {}: Check Disk Tool'.format(KIT_NAME_FULL)) -set_log_file('Check Disk.log') - -if __name__ == '__main__': - try: - stay_awake() - clear_screen() - other_results = { - 'Error': { - 'CalledProcessError': 'Unknown Error', - }, - 'Warning': { - 'GenericRepair': 'Repaired', - 'UnsupportedOSError': 'Unsupported OS', - }} - options = [ - {'Name': 'Run CHKDSK scan (read-only)', 'Repair': False}, - {'Name': 'Schedule CHKDSK scan (offline repair)', 'Repair': True}] - actions = [{'Name': 'Quit', 'Letter': 'Q'}] - selection = menu_select( - '{}: Check Disk Menu\n'.format(KIT_NAME_FULL), - main_entries=options, - action_entries=actions) - print_info('{}: Check Disk Menu\n'.format(KIT_NAME_FULL)) - if selection == 'Q': - abort() - elif selection.isnumeric(): - repair = options[int(selection)-1]['Repair'] - if repair: - cs = 'Scheduled' - else: - cs = 'No issues' - message = 'CHKDSK ({SYSTEMDRIVE})...'.format(**global_vars['Env']) - try_and_print(message=message, function=run_chkdsk, - cs=cs, other_results=other_results, repair=repair) - else: - abort() - - # Done - print_success('Done.') - pause("Press Enter to exit...") - exit_script() - except SystemExit as sys_exit: - exit_script(sys_exit.code) - except: - major_exception() - -# vim: sts=2 sw=2 ts=2 diff --git a/scripts/outer_scripts_to_review/dism.py b/scripts/outer_scripts_to_review/dism.py deleted file mode 100644 index 4de5b788..00000000 --- a/scripts/outer_scripts_to_review/dism.py +++ /dev/null @@ -1,58 +0,0 @@ -# Wizard Kit: Check or repair component store health via DISM - -import os -import sys - -# Init -sys.path.append(os.path.dirname(os.path.realpath(__file__))) -from functions.repairs import * -init_global_vars() -os.system('title {}: DISM helper Tool'.format(KIT_NAME_FULL)) -set_log_file('DISM Helper.log') - -if __name__ == '__main__': - try: - stay_awake() - clear_screen() - other_results = { - 'Error': { - 'CalledProcessError': 'Unknown Error', - }, - 'Warning': { - 'GenericRepair': 'Repaired', - 'UnsupportedOSError': 'Unsupported OS', - }} - disabled = bool(global_vars['OS']['Version'] not in ('8', '8.1', '10')) - options = [ - {'Name': 'Check Health', 'Repair': False, 'Disabled': disabled}, - {'Name': 'Restore Health', 'Repair': True, 'Disabled': disabled}] - actions = [{'Name': 'Quit', 'Letter': 'Q'}] - selection = menu_select( - '{}: DISM Menu\n'.format(KIT_NAME_FULL), - main_entries=options, - action_entries=actions) - print_info('{}: DISM Menu\n'.format(KIT_NAME_FULL)) - if selection == 'Q': - abort() - elif selection.isnumeric(): - repair = options[int(selection)-1]['Repair'] - if repair: - message='DISM RestoreHealth...' - else: - message='DISM ScanHealth...' - try_and_print(message=message, function=run_dism, - cs='No corruption', ns='Corruption detected', - other_results=other_results, repair=repair) - else: - abort() - - # Done - print_success('Done.') - pause("Press Enter to exit...") - exit_script() - except SystemExit as sys_exit: - exit_script(sys_exit.code) - except: - major_exception() - -# vim: sts=2 sw=2 ts=2 diff --git a/scripts/outer_scripts_to_review/install_sw_bundle.py b/scripts/outer_scripts_to_review/install_sw_bundle.py deleted file mode 100644 index 2979362e..00000000 --- a/scripts/outer_scripts_to_review/install_sw_bundle.py +++ /dev/null @@ -1,63 +0,0 @@ -# Wizard Kit: Install the standard SW bundle based on the OS version - -import os -import sys - -# Init -sys.path.append(os.path.dirname(os.path.realpath(__file__))) -from functions.setup import * -init_global_vars() -os.system('title {}: SW Bundle Tool'.format(KIT_NAME_FULL)) -set_log_file('Install SW Bundle.log') - -if __name__ == '__main__': - try: - stay_awake() - clear_screen() - print_info('{}: SW Bundle Tool\n'.format(KIT_NAME_FULL)) - other_results = { - 'Error': { - 'CalledProcessError': 'Unknown Error', - 'FileNotFoundError': 'File not found', - }, - 'Warning': { - 'GenericRepair': 'Repaired', - 'UnsupportedOSError': 'Unsupported OS', - }} - answer_extensions = ask('Install Extensions?') - answer_vcr = ask('Install Visual C++ Runtimes?') - answer_ninite = ask('Install Ninite Bundle?') - if answer_ninite and global_vars['OS']['Version'] in ['7']: - # Vista is dead, not going to check for it - answer_mse = ask('Install MSE?') - else: - answer_mse = False - - print_info('Installing Programs') - if answer_vcr: - install_vcredists() - if answer_ninite: - result = try_and_print(message='Ninite bundle...', - function=install_ninite_bundle, cs='Started', - mse=answer_mse, other_results=other_results) - for proc in result['Out']: - # Wait for all processes to finish - proc.wait() - if answer_extensions: - print_info('Installing Extensions') - try_and_print(message='Classic Shell skin...', - function=install_classicstart_skin, - other_results=other_results) - try_and_print(message='Google Chrome extensions...', - function=install_chrome_extensions) - try_and_print(message='Mozilla Firefox extensions...', - function=install_firefox_extensions, - other_results=other_results) - print_standard('\nDone.') - exit_script() - except SystemExit as sys_exit: - exit_script(sys_exit.code) - except: - major_exception() - -# vim: sts=2 sw=2 ts=2 diff --git a/scripts/outer_scripts_to_review/install_vcredists.py b/scripts/outer_scripts_to_review/install_vcredists.py deleted file mode 100644 index 1cd31d95..00000000 --- a/scripts/outer_scripts_to_review/install_vcredists.py +++ /dev/null @@ -1,35 +0,0 @@ -# Wizard Kit: Install Visual C++ Runtimes - -import os -import sys - -# Init -sys.path.append(os.path.dirname(os.path.realpath(__file__))) -from functions.setup import * -init_global_vars() -os.system('title {}: Install Visual C++ Runtimes'.format(KIT_NAME_FULL)) -set_log_file('Install Visual C++ Runtimes.log') - -if __name__ == '__main__': - try: - stay_awake() - clear_screen() - print_info('{}: Install Visual C++ Runtimes\n'.format(KIT_NAME_FULL)) - other_results = { - 'Error': { - 'CalledProcessError': 'Unknown Error', - }} - - if ask('Install Visual C++ Runtimes?'): - install_vcredists() - else: - abort() - - print_standard('\nDone.') - exit_script() - except SystemExit as sys_exit: - exit_script(sys_exit.code) - except: - major_exception() - -# vim: sts=2 sw=2 ts=2 diff --git a/scripts/outer_scripts_to_review/system_diagnostics.py b/scripts/outer_scripts_to_review/system_diagnostics.py deleted file mode 100644 index b1a1848d..00000000 --- a/scripts/outer_scripts_to_review/system_diagnostics.py +++ /dev/null @@ -1,173 +0,0 @@ -# Wizard Kit: System Diagnostics - -import os -import sys - -# Init -sys.path.append(os.path.dirname(os.path.realpath(__file__))) -from functions.browsers import * -from functions.info import * -from functions.product_keys import * -from functions.repairs import * -from functions.sw_diags import * -init_global_vars() -os.system('title {}: System Diagnostics Tool'.format(KIT_NAME_FULL)) -set_log_file('System Diagnostics.log') - -# Static Variables -BLEACH_BIT_CLEANERS = { - 'Applications': ( - 'adobe_reader.cache', - 'adobe_reader.tmp', - 'amule.tmp', - 'flash.cache', - 'gimp.tmp', - 'hippo_opensim_viewer.cache', - 'java.cache', - 'libreoffice.cache', - 'liferea.cache', - 'miro.cache', - 'openofficeorg.cache', - 'pidgin.cache', - 'secondlife_viewer.Cache', - 'thunderbird.cache', - 'vuze.backup_files', - 'vuze.cache', - 'vuze.tmp', - 'yahoo_messenger.cache', - ), - 'Browsers': ( - 'chromium.cache', - 'chromium.current_session', - 'firefox.cache', - 'firefox.session_restore', - 'google_chrome.cache', - 'google_chrome.session', - 'google_earth.temporary_files', - 'internet_explorer.temporary_files', - 'opera.cache', - 'opera.current_session', - 'safari.cache', - 'seamonkey.cache', - ), - 'System': ( - 'system.clipboard', - 'system.tmp', - 'winapp2_windows.jump_lists', - 'winapp2_windows.ms_search', - 'windows_explorer.run', - 'windows_explorer.search_history', - 'windows_explorer.thumbnails', - ), -} - -if __name__ == '__main__': - try: - stay_awake() - clear_screen() - print_info('{}: System Diagnostics Tool\n'.format(KIT_NAME_FULL)) - ticket_number = get_ticket_number() - other_results = { - 'Error': { - 'CalledProcessError': 'Unknown Error', - 'FileNotFoundError': 'File not found', - }, - 'Warning': { - 'GenericRepair': 'Repaired', - 'UnsupportedOSError': 'Unsupported OS', - }} - if ENABLED_TICKET_NUMBERS: - print_info('Starting System Diagnostics for Ticket #{}\n'.format( - ticket_number)) - - # Sanitize Environment - print_info('Sanitizing Environment') - try_and_print(message='Running RKill...', - function=run_rkill, cs='Done', other_results=other_results) - try_and_print(message='Running TDSSKiller...', - function=run_tdsskiller, cs='Done', other_results=other_results) - - # Re-run if earlier process was stopped. - stay_awake() - - # Start diags - print_info('Starting Background Scans') - check_connection() - try_and_print(message='Running HitmanPro...', - function=run_hitmanpro, cs='Started', other_results=other_results) - try_and_print(message='Running Autoruns...', - function=run_autoruns, cs='Started', other_results=other_results) - - # OS Health Checks - print_info('OS Health Checks') - try_and_print( - message='CHKDSK ({SYSTEMDRIVE})...'.format(**global_vars['Env']), - function=run_chkdsk, other_results=other_results) - try_and_print(message='SFC scan...', - function=run_sfc_scan, other_results=other_results) - try_and_print(message='DISM CheckHealth...', - function=run_dism, other_results=other_results, repair=False) - - # Scan for supported browsers - print_info('Scanning for browsers') - scan_for_browsers() - - # Run BleachBit cleaners - print_info('BleachBit Cleanup') - for k, v in sorted(BLEACH_BIT_CLEANERS.items()): - try_and_print(message=' {}...'.format(k), - function=run_bleachbit, - cs='Done', other_results=other_results, - cleaners=v, preview=True) - - # Export system info - print_info('Backup System Information') - try_and_print(message='AIDA64 reports...', - function=run_aida64, cs='Done', other_results=other_results) - backup_browsers() - try_and_print(message='File listing...', - function=backup_file_list, cs='Done', other_results=other_results) - try_and_print(message='Power plans...', - function=backup_power_plans, cs='Done') - try_and_print(message='Product Keys...', - function=run_produkey, cs='Done', other_results=other_results) - try_and_print(message='Registry...', - function=backup_registry, cs='Done', other_results=other_results) - - # Summary - print_info('Summary') - try_and_print(message='Operating System:', - function=show_os_name, ns='Unknown', silent_function=False) - try_and_print(message='Activation:', - function=show_os_activation, ns='Unknown', silent_function=False) - try_and_print(message='Installed RAM:', - function=show_installed_ram, ns='Unknown', silent_function=False) - show_free_space() - try_and_print(message='Temp Size:', - function=show_temp_files_size, silent_function=False) - try_and_print(message='Installed Antivirus:', - function=get_installed_antivirus, ns='Unknown', - other_results=other_results, print_return=True) - try_and_print(message='Installed Office:', - function=get_installed_office, ns='Unknown', - other_results=other_results, print_return=True) - try_and_print(message='Product Keys:', - function=get_product_keys, ns='Unknown', print_return=True) - - # User data - print_info('User Data') - try: - show_user_data_summary() - except Exception: - print_error(' Unknown error.') - - # Done - print_standard('\nDone.') - pause('Press Enter to exit...') - exit_script() - except SystemExit as sys_exit: - exit_script(sys_exit.code) - except: - major_exception() - -# vim: sts=2 sw=2 ts=2 diff --git a/scripts/outer_scripts_to_review/system_setup.py b/scripts/outer_scripts_to_review/system_setup.py deleted file mode 100644 index 5fa239ab..00000000 --- a/scripts/outer_scripts_to_review/system_setup.py +++ /dev/null @@ -1,355 +0,0 @@ -'''Wizard Kit: System Setup''' -# pylint: disable=wildcard-import,wrong-import-position -# vim: sts=2 sw=2 ts=2 - -import os -import sys - -# Init -sys.path.append(os.path.dirname(os.path.realpath(__file__))) -from collections import OrderedDict -from functions.activation import * -from functions.browsers import * -from functions.cleanup import * -from functions.info import * -from functions.product_keys import * -from functions.setup import * -from functions.sw_diags import * -from functions.windows_updates import * -init_global_vars() -os.system('title {}: System Setup'.format(KIT_NAME_FULL)) -set_log_file('System Setup.log') - - -# STATIC VARIABLES -# pylint: disable=bad-whitespace,line-too-long -OTHER_RESULTS = { - 'Error': { - 'BIOSKeyNotFoundError': 'BIOS KEY NOT FOUND', - 'CalledProcessError': 'UNKNOWN ERROR', - 'FileNotFoundError': 'FILE NOT FOUND', - 'GenericError': 'UNKNOWN ERROR', - 'Not4KAlignedError': 'FALSE', - 'SecureBootDisabledError': 'DISABLED', - 'WindowsUnsupportedError': 'UNSUPPORTED', - }, - 'Warning': { - 'GenericRepair': 'REPAIRED', - 'NoProfilesError': 'NO PROFILES FOUND', - 'NotInstalledError': 'NOT INSTALLED', - 'OSInstalledLegacyError': 'OS INSTALLED LEGACY', - 'SecureBootNotAvailError': 'NOT AVAILABLE', - 'SecureBootUnknownError': 'UNKNOWN', - 'UnsupportedOSError': 'UNSUPPORTED OS', - 'WindowsOutdatedError': 'OUTDATED', - }, - } -SETUP_ACTIONS = OrderedDict({ - # Install software - 'Installing Programs': {'Info': True}, - 'VCR': {'New': True, 'Dat': True, 'Cur': True, 'HW': False, 'Function': install_vcredists, 'Just run': True,}, - 'LibreOffice': {'New': True, 'Dat': True, 'Cur': True, 'HW': False, 'Function': install_libreoffice, - 'If answer': 'LibreOffice', 'KWArgs': {'quickstart': False, 'register_mso_types': True, 'use_mso_formats': False, 'vcredist': False}, - }, - 'Ninite bundle': {'New': True, 'Dat': True, 'Cur': True, 'HW': False, 'Function': install_ninite_bundle, 'KWArgs': {'cs': 'STARTED'},}, - - # Browsers - 'Scanning for browsers': {'Info': True}, - 'Scan': {'New': True, 'Dat': True, 'Cur': True, 'HW': False, 'Function': scan_for_browsers, 'Just run': True, 'KWArgs': {'skip_ie': True},}, - 'Backing up browsers': {'Info': True}, - 'Backup browsers': {'New': False, 'Dat': True, 'Cur': True, 'HW': False, 'Function': backup_browsers, 'Just run': True,}, - - # Install extensions - 'Installing Extensions': {'Info': True}, - 'Classic Shell skin': {'New': True, 'Dat': True, 'Cur': False, 'HW': False, 'Function': install_classicstart_skin, 'Win10 only': True,}, - 'Chrome extensions': {'New': True, 'Dat': True, 'Cur': True, 'HW': False, 'Function': install_chrome_extensions,}, - 'Firefox extensions': {'New': True, 'Dat': True, 'Cur': True, 'HW': False, 'Function': install_firefox_extensions,}, - - # Configure software' - 'Configuring Programs': {'Info': True}, - 'Browser add-ons': {'New': True, 'Dat': True, 'Cur': True, 'HW': False, 'Function': install_adblock, 'Just run': True, - 'Pause': 'Please enable uBlock Origin for all browsers', - }, - 'Classic Start': {'New': True, 'Dat': True, 'Cur': False, 'HW': False, 'Function': config_classicstart, 'Win10 only': True,}, - 'Config Windows Updates': {'New': True, 'Dat': True, 'Cur': True, 'HW': True, 'Function': config_windows_updates, 'Win10 only': True,}, - 'Enable Windows Updates': {'New': True, 'Dat': True, 'Cur': True, 'HW': True, 'Function': enable_windows_updates, 'KWArgs': {'silent': True},}, - 'Explorer (system)': {'New': True, 'Dat': True, 'Cur': True, 'HW': False, 'Function': config_explorer_system, 'Win10 only': True,}, - 'Explorer (user)': {'New': True, 'Dat': True, 'Cur': True, 'HW': False, 'Function': config_explorer_user, 'Win10 only': True,}, - 'Restart Explorer': {'New': True, 'Dat': True, 'Cur': True, 'HW': False, 'Function': restart_explorer,}, - 'Restore default UAC': {'New': True, 'Dat': True, 'Cur': True, 'HW': False, 'Function': restore_default_uac,}, - 'Update Clock': {'New': True, 'Dat': True, 'Cur': True, 'HW': False, 'Function': update_clock,}, - - # Cleanup - 'Cleaning up': {'Info': True}, - 'AdwCleaner': {'New': True, 'Dat': True, 'Cur': True, 'HW': False, 'Function': cleanup_adwcleaner,}, - 'Desktop': {'New': True, 'Dat': True, 'Cur': True, 'HW': False, 'Function': cleanup_desktop,}, - 'KIT_NAME_FULL': {'New': True, 'Dat': True, 'Cur': True, 'HW': True, 'Function': delete_empty_folders,}, - - # System Info - 'Exporting system info': {'Info': True}, - 'AIDA64 Report': {'New': True, 'Dat': True, 'Cur': True, 'HW': False, 'Function': run_aida64,}, - 'File listing': {'New': True, 'Dat': True, 'Cur': True, 'HW': False, 'Function': backup_file_list,}, - 'Power plans': {'New': True, 'Dat': True, 'Cur': True, 'HW': True, 'Function': backup_power_plans,}, - 'Product Keys': {'New': True, 'Dat': True, 'Cur': True, 'HW': True, 'Function': run_produkey,}, - 'Registry': {'New': True, 'Dat': True, 'Cur': True, 'HW': True, 'Function': backup_registry,}, - - # Show Summary - 'Summary': {'Info': True}, - 'Operating System': {'New': True, 'Dat': True, 'Cur': True, 'HW': True, 'Function': show_os_name, 'KWArgs': {'ns': 'UNKNOWN', 'silent_function': False},}, - 'Activation': {'New': True, 'Dat': True, 'Cur': True, 'HW': True, 'Function': show_os_activation, 'KWArgs': {'ns': 'UNKNOWN', 'silent_function': False},}, - 'BIOS Activation': {'New': True, 'Dat': True, 'Cur': True, 'HW': False, 'Function': activate_with_bios, 'If not activated': True,}, - 'Secure Boot': {'New': True, 'Dat': True, 'Cur': True, 'HW': True, 'Function': check_secure_boot_status, 'KWArgs': {'show_alert': False},}, - 'Installed RAM': {'New': True, 'Dat': True, 'Cur': True, 'HW': True, 'Function': show_installed_ram, 'KWArgs': {'ns': 'UNKNOWN', 'silent_function': False},}, - 'Temp size': {'New': False, 'Dat': False, 'Cur': True, 'HW': False, 'Function': show_temp_files_size, 'KWArgs': {'ns': 'UNKNOWN', 'silent_function': False},}, - 'Show free space': {'New': True, 'Dat': True, 'Cur': True, 'HW': True, 'Function': show_free_space, 'Just run': True,}, - 'Installed AV': {'New': True, 'Dat': True, 'Cur': True, 'HW': True, 'Function': get_installed_antivirus, 'KWArgs': {'ns': 'UNKNOWN', 'print_return': True},}, - 'Installed Office': {'New': True, 'Dat': True, 'Cur': True, 'HW': False, 'Function': get_installed_office, 'KWArgs': {'ns': 'UNKNOWN', 'print_return': True},}, - 'Partitions 4K aligned': {'New': True, 'Dat': True, 'Cur': True, 'HW': True, 'Function': check_4k_alignment, 'KWArgs': {'cs': 'TRUE', 'ns': 'FALSE'},}, - - # Open things - 'Opening Programs': {'Info': True}, - 'Device Manager': {'New': True, 'Dat': True, 'Cur': True, 'HW': True, 'Function': open_device_manager, 'KWArgs': {'cs': 'STARTED'},}, - 'HWiNFO sensors': {'New': True, 'Dat': True, 'Cur': True, 'HW': True, 'Function': run_hwinfo_sensors, 'KWArgs': {'cs': 'STARTED'},}, - 'Speed test': {'New': True, 'Dat': True, 'Cur': True, 'HW': True, 'Function': open_speedtest, 'KWArgs': {'cs': 'STARTED'},}, - 'Windows Updates': {'New': True, 'Dat': True, 'Cur': True, 'HW': False, 'Function': open_windows_updates, 'KWArgs': {'cs': 'STARTED'},}, - 'Windows Activation': {'New': True, 'Dat': True, 'Cur': True, 'HW': False, 'Function': open_windows_activation, 'If not activated': True, 'KWArgs': {'cs': 'STARTED'},}, - 'Sleep': {'New': True, 'Dat': True, 'Cur': True, 'HW': True, 'Function': sleep, 'Just run': True, 'KWArgs': {'seconds': 3},}, - 'XMPlay': {'New': True, 'Dat': True, 'Cur': True, 'HW': True, 'Function': run_xmplay, 'KWArgs': {'cs': 'STARTED'},}, - }) -SETUP_ACTION_KEYS = ( - 'Function', - 'If not activated', - 'Info', - 'Just run', - 'KWArgs', - 'Pause', - ) -SETUP_QUESTIONS = { - # AV - 'MSE': {'New': None, 'Dat': None, 'Cur': None, 'HW': False, 'Ninite': True}, - - # LibreOffice - 'LibreOffice': {'New': None, 'Dat': None, 'Cur': None, 'HW': False, 'Ninite': True}, - - # Ninite - 'Base': {'New': True, 'Dat': True, 'Cur': True, 'HW': False, 'Ninite': True}, - 'Missing': {'New': False, 'Dat': True, 'Cur': False, 'HW': False, 'Ninite': True}, - 'Standard': {'New': True, 'Dat': True, 'Cur': False, 'HW': False, 'Ninite': True}, - } -# pylint: enable=bad-whitespace,line-too-long - - -# Functions -def check_os_and_abort(): - """Check OS and prompt to abort if not supported.""" - result = try_and_print( - message='OS support status...', - function=check_os_support_status, - cs='GOOD', - ) - if not result['CS'] and 'Unsupported' in result['Error']: - print_warning('OS version not supported by this script') - if not ask('Continue anyway? (NOT RECOMMENDED)'): - abort() - - -def get_actions(setup_mode, answers): - """Get actions to perform based on setup_mode, returns OrderedDict.""" - actions = OrderedDict({}) - for _key, _val in SETUP_ACTIONS.items(): - _action = {} - _if_answer = _val.get('If answer', False) - _win10_only = _val.get('Win10 only', False) - - # Set enabled status - _enabled = _val.get(setup_mode, False) - if _if_answer: - _enabled = _enabled and answers[_if_answer] - if _win10_only: - _enabled = _enabled and global_vars['OS']['Version'] == '10' - _action['Enabled'] = _enabled - - # Set other keys - for _sub_key in SETUP_ACTION_KEYS: - _action[_sub_key] = _val.get(_sub_key, None) - - # Fix KWArgs - if _action.get('KWArgs', {}) is None: - _action['KWArgs'] = {} - - # Handle "special" actions - if _key == 'KIT_NAME_FULL': - # Cleanup WK folders - _key = KIT_NAME_FULL - _action['KWArgs'] = {'folder_path': global_vars['ClientDir']} - elif _key == 'Ninite bundle': - # Add install_ninite_bundle() kwargs - _action['KWArgs'].update({ - kw.lower(): kv for kw, kv in answers.items() - if SETUP_QUESTIONS.get(kw, {}).get('Ninite', False) - }) - elif _key == 'Explorer (user)': - # Explorer settings (user) - _action['KWArgs'] = {'setup_mode': setup_mode} - - # Add to dict - actions[_key] = _action - - return actions - - -def get_answers(setup_mode): - """Get setup answers based on setup_mode and user input, returns dict.""" - answers = {k: v.get(setup_mode, False) for k, v in SETUP_QUESTIONS.items()} - - # Answer setup questions as needed - if answers['MSE'] is None and global_vars['OS']['Version'] == '7': - answers.update(get_av_selection()) - - if answers['LibreOffice'] is None: - answers['LibreOffice'] = ask('Install LibreOffice?') - - return answers - - -def get_av_selection(): - """Get AV selection.""" - av_answers = { - 'MSE': False, - } - av_options = [ - { - 'Name': 'Microsoft Security Essentials', - 'Disabled': global_vars['OS']['Version'] not in ['7'], - }, - ] - actions = [ - {'Name': 'None', 'Letter': 'N'}, - {'Name': 'Quit', 'Letter': 'Q'}, - ] - - # Show menu - selection = menu_select( - 'Please select an option to install', - main_entries=av_options, - action_entries=actions) - if selection.isnumeric(): - index = int(selection) - 1 - if 'Microsoft' in av_options[index]['Name']: - av_answers['MSE'] = True - elif selection == 'Q': - abort() - - return av_answers - - -def get_mode(): - """Get mode via menu_select, returns str.""" - setup_mode = None - mode_options = [ - {'Name': 'New', 'Display Name': 'New / Clean install (no data)'}, - {'Name': 'Dat', 'Display Name': 'Clean install with data migration'}, - {'Name': 'Cur', 'Display Name': 'Original OS (post-repair or overinstall)'}, - {'Name': 'HW', 'Display Name': 'Hardware service (i.e. no software work)'}, - ] - actions = [ - {'Name': 'Quit', 'Letter': 'Q'}, - ] - - # Get selection - selection = menu_select( - 'Please select a setup mode', - main_entries=mode_options, - action_entries=actions) - if selection.isnumeric(): - index = int(selection) - 1 - setup_mode = mode_options[index]['Name'] - elif selection == 'Q': - abort() - - return setup_mode - - -def main(): - """Main function.""" - stay_awake() - clear_screen() - - # Check installed OS - check_os_and_abort() - - # Get setup mode - setup_mode = get_mode() - - # Get answers to setup questions - answers = get_answers(setup_mode) - - # Get actions to perform - actions = get_actions(setup_mode, answers) - - # Perform actions - for action, values in actions.items(): - kwargs = values.get('KWArgs', {}) - - # Print info lines - if values.get('Info', False): - print_info(action) - continue - - # Print disabled actions - if not values.get('Enabled', False): - show_data( - message='{}...'.format(action), - data='DISABLED', - warning=True, - ) - continue - - # Check Windows activation if requested - if values.get('If not activated', False) and windows_is_activated(): - # Skip - continue - - # Run function - if values.get('Just run', False): - values['Function'](**kwargs) - else: - result = try_and_print( - message='{}...'.format(action), - function=values['Function'], - other_results=OTHER_RESULTS, - **kwargs) - - # Wait for Ninite proc(s) - if action == 'Ninite bundle': - print_standard('Waiting for installations to finish...') - try: - for proc in result['Out']: - proc.wait() - except KeyboardInterrupt: - pass - - # Pause - if values.get('Pause', False): - print_standard(values['Pause']) - pause() - - # Show alert box for SecureBoot issues - try: - check_secure_boot_status(show_alert=True) - except Exception: # pylint: disable=broad-except - # Ignoring exceptions since we just want to show the popup - pass - - # Done - pause('Press Enter to exit... ') - - -if __name__ == '__main__': - try: - main() - exit_script() - except SystemExit as sys_exit: - exit_script(sys_exit.code) - except: # pylint: disable=bare-except - major_exception() diff --git a/scripts/outer_scripts_to_review/transferred_keys.py b/scripts/outer_scripts_to_review/transferred_keys.py deleted file mode 100644 index 216f2046..00000000 --- a/scripts/outer_scripts_to_review/transferred_keys.py +++ /dev/null @@ -1,29 +0,0 @@ -# Wizard Kit: Search for product keys in the transfer folder - -import os -import sys - -# Init -sys.path.append(os.path.dirname(os.path.realpath(__file__))) -from functions.product_keys import * -init_global_vars() -os.system('title {}: Transferred Key Finder'.format(KIT_NAME_FULL)) -set_log_file('Transferred Keys.log') - -if __name__ == '__main__': - try: - stay_awake() - clear_screen() - print_info('{}: Transferred Key Finder\n'.format(KIT_NAME_FULL)) - try_and_print(message='Searching for keys...', - function=list_clientdir_keys, print_return=True) - - # Done - print_standard('\nDone.') - exit_script() - except SystemExit as sys_exit: - exit_script(sys_exit.code) - except: - major_exception() - -# vim: sts=2 sw=2 ts=2 diff --git a/scripts/outer_scripts_to_review/update_kit.py b/scripts/outer_scripts_to_review/update_kit.py deleted file mode 100644 index 77f527aa..00000000 --- a/scripts/outer_scripts_to_review/update_kit.py +++ /dev/null @@ -1,143 +0,0 @@ -# Wizard Kit: Download the latest versions of the programs in the kit - -import os -import sys - -# Init -sys.path.append(os.path.dirname(os.path.realpath(__file__))) -from functions.update import * -init_global_vars() -os.system('title {}: Kit Update Tool'.format(KIT_NAME_FULL)) - -if __name__ == '__main__': - try: - clear_screen() - print_info('{}: Kit Update Tool\n'.format(KIT_NAME_FULL)) - other_results = { - 'Error': { - 'CalledProcessError': 'Unknown Error', - }} - - ## Prep ## - update_sdio = ask('Update SDI Origin?') - - ## Download ## - print_success('Downloading tools') - - # Data Recovery - print_info(' Data Recovery') - try_and_print(message='TestDisk / PhotoRec...', function=update_testdisk, other_results=other_results, width=40) - - # Data Transfers - print_info(' Data Transfers') - try_and_print(message='FastCopy...', function=update_fastcopy, other_results=other_results, width=40) - try_and_print(message='wimlib...', function=update_wimlib, other_results=other_results, width=40) - try_and_print(message='XYplorer...', function=update_xyplorer, other_results=other_results, width=40) - - # Diagnostics - print_info(' Diagnostics') - try_and_print(message='AIDA64...', function=update_aida64, other_results=other_results, width=40) - try_and_print(message='Autoruns...', function=update_autoruns, other_results=other_results, width=40) - try_and_print(message='BleachBit...', function=update_bleachbit, other_results=other_results, width=40) - try_and_print(message='Blue Screen View...', function=update_bluescreenview, other_results=other_results, width=40) - try_and_print(message='ERUNT...', function=update_erunt, other_results=other_results, width=40) - try_and_print(message='Hitman Pro...', function=update_hitmanpro, other_results=other_results, width=40) - try_and_print(message='HWiNFO...', function=update_hwinfo, other_results=other_results, width=40) - try_and_print(message='NirCmd...', function=update_nircmd, other_results=other_results, width=40) - try_and_print(message='ProduKey...', function=update_produkey, other_results=other_results, width=40) - - # Drivers - print_info(' Drivers') - try_and_print(message='Intel RST...', function=update_intel_rst, other_results=other_results, width=40) - try_and_print(message='Intel SSD Toolbox...', function=update_intel_ssd_toolbox, other_results=other_results, width=40) - try_and_print(message='Samsing Magician...', function=update_samsung_magician, other_results=other_results, width=40) - if update_sdio: - try_and_print(message='Snappy Driver Installer Origin...', function=update_sdi_origin, other_results=other_results, width=40) - - # Installers - print_info(' Installers') - try_and_print(message='Adobe Reader DC...', function=update_adobe_reader_dc, other_results=other_results, width=40) - try_and_print(message='LibreOffice...', function=update_libreoffice, other_results=other_results, width=40) - try_and_print(message='Macs Fan Control...', function=update_macs_fan_control, other_results=other_results, width=40) - try_and_print(message='MS Office...', function=update_office, other_results=other_results, width=40) - try_and_print(message='Visual C++ Runtimes...', function=update_vcredists, other_results=other_results, width=40) - try_and_print(message='Windows Updates...', function=download_windows_updates, other_results=other_results, width=40) - update_all_ninite(other_results=other_results, width=40) - - # Misc - print_info(' Misc') - try_and_print(message='Caffeine...', function=update_caffeine, other_results=other_results, width=40) - try_and_print(message='Classic Start Skin...', function=update_classic_start_skin, other_results=other_results, width=40) - try_and_print(message='Du...', function=update_du, other_results=other_results, width=40) - try_and_print(message='Everything...', function=update_everything, other_results=other_results, width=40) - try_and_print(message='Firefox Extensions...', function=update_firefox_ublock_origin, other_results=other_results, width=40) - try_and_print(message='PuTTY...', function=update_putty, other_results=other_results, width=40) - try_and_print(message='Notepad++...', function=update_notepadplusplus, other_results=other_results, width=40) - try_and_print(message='WizTree...', function=update_wiztree, other_results=other_results, width=40) - try_and_print(message='XMPlay...', function=update_xmplay, other_results=other_results, width=40) - - # Repairs - print_info(' Repairs') - try_and_print(message='AdwCleaner...', function=update_adwcleaner, other_results=other_results, width=40) - try_and_print(message='KVRT...', function=update_kvrt, other_results=other_results, width=40) - try_and_print(message='RKill...', function=update_rkill, other_results=other_results, width=40) - try_and_print(message='TDSS Killer...', function=update_tdsskiller, other_results=other_results, width=40) - - # Uninstallers - print_info(' Uninstallers') - try_and_print(message='IObit Uninstaller...', function=update_iobit_uninstaller, other_results=other_results, width=40) - - ## Review ## - print_standard('Please review the results and download/extract any missing items to .cbin') - pause('Press Enter to compress the .cbin items') - - ## Compress ## - print_success('Compressing tools') - print_info(' _Drivers') - for item in os.scandir(r'{}\_Drivers'.format(global_vars['CBinDir'])): - if not re.search(r'^(_Drivers|.*7z)$', item.name, re.IGNORECASE): - try_and_print( - message='{}...'.format(item.name), - function=compress_and_remove_item, - other_results = other_results, - width=40, - item = item) - print_info(' .cbin') - for item in os.scandir(global_vars['CBinDir']): - if not re.search(r'^(_Drivers|_include|.*7z)$', item.name, re.IGNORECASE): - try_and_print( - message='{}...'.format(item.name), - function=compress_and_remove_item, - other_results = other_results, - width=40, - item = item) - - ## Generate Launchers - print_success('Generating launchers') - for section in sorted(LAUNCHERS.keys()): - print_info(' {}'.format(section)) - for name, options in sorted(LAUNCHERS[section].items()): - try_and_print(message=name, function=generate_launcher, - section=section, name=name, options=options, - other_results=other_results, width=40) - - # Rename "Copy WizardKit.cmd" (if necessary) - source = r'{}\Scripts\Copy WizardKit.cmd'.format(global_vars['BinDir']) - dest = r'{}\Copy {}.cmd'.format(global_vars['BaseDir'], KIT_NAME_FULL) - if os.path.exists(source): - try: - shutil.move(source, dest) - except Exception: - print_error(' Failed to rename "{}.cmd" to "{}.cmd"'.format( - 'Copy WizardKit', KIT_NAME_FULL)) - - # Done - print_standard('\nDone.') - pause("Press Enter to exit...") - exit_script() - except SystemExit as sys_exit: - exit_script(sys_exit.code) - except: - major_exception() - -# vim: sts=2 sw=2 ts=2 diff --git a/scripts/outer_scripts_to_review/user_data_transfer.py b/scripts/outer_scripts_to_review/user_data_transfer.py deleted file mode 100644 index 60b3c464..00000000 --- a/scripts/outer_scripts_to_review/user_data_transfer.py +++ /dev/null @@ -1,67 +0,0 @@ -# Wizard Kit: Copy user data to the system from a local or network source - -import os -import sys - -# Init -sys.path.append(os.path.dirname(os.path.realpath(__file__))) -from functions.data import * -from functions.repairs import * -init_global_vars() -os.system('title {}: User Data Transfer Tool'.format(KIT_NAME_FULL)) -set_log_file('User Data Transfer.log') - -if __name__ == '__main__': - try: - # Prep - stay_awake() - clear_screen() - print_info('{}: User Data Transfer Tool\n'.format(KIT_NAME_FULL)) - - # Get backup name prefix - ticket_number = get_ticket_number() - if ENABLED_TICKET_NUMBERS: - backup_prefix = ticket_number - else: - backup_prefix = get_simple_string(prompt='Enter backup name prefix') - backup_prefix = backup_prefix.replace(' ', '_') - - # Set destination - folder_path = r'{}\Transfer'.format(KIT_NAME_SHORT) - dest = select_destination(folder_path=folder_path, - prompt='Which disk are we transferring to?') - - # Set source items - source = select_source(backup_prefix) - items = scan_source(source, dest) - - # Transfer - clear_screen() - print_info('Transfer Details:\n') - if ENABLED_TICKET_NUMBERS: - show_data('Ticket:', ticket_number) - show_data('Source:', source.path) - show_data('Destination:', dest) - - if (not ask('Proceed with transfer?')): - umount_backup_shares() - abort() - - print_info('Transferring Data') - transfer_source(source, dest, items) - try_and_print(message='Removing extra files...', - function=cleanup_transfer, cs='Done', dest_path=dest) - umount_backup_shares() - - # Done - try_and_print(message='Running KVRT...', - function=run_kvrt, cs='Started') - print_standard('\nDone.') - pause("Press Enter to exit...") - exit_script() - except SystemExit as sys_exit: - exit_script(sys_exit.code) - except: - major_exception() - -# vim: sts=2 sw=2 ts=2 diff --git a/scripts/outer_scripts_to_review/windows_updates.py b/scripts/outer_scripts_to_review/windows_updates.py deleted file mode 100644 index e29f8c48..00000000 --- a/scripts/outer_scripts_to_review/windows_updates.py +++ /dev/null @@ -1,46 +0,0 @@ -# Wizard Kit: Windows updates - -import os -import sys - -# Init -sys.path.append(os.path.dirname(os.path.realpath(__file__))) -from functions.windows_updates import * -init_global_vars() -os.system('title {}: Windows Updates Tool'.format(KIT_NAME_FULL)) -set_log_file('Windows Updates Tool.log') - -if __name__ == '__main__': - try: - clear_screen() - print_info('{}: Windows Updates Tool\n'.format(KIT_NAME_FULL)) - - # Check args - if '--disable' in sys.argv: - disable_windows_updates() - elif '--enable' in sys.argv: - enable_windows_updates() - else: - print_error('Bad mode.') - abort() - - # Done - exit_script() - except GenericError as err: - # Failed to complete request, show error(s) and prompt tech - print_standard(' ') - for line in str(err).splitlines(): - print_warning(line) - print_standard(' ') - print_error('Error(s) encountered, see above.') - print_standard(' ') - if '--disable' in sys.argv: - print_standard('Please reboot and try again.') - pause('Press Enter to exit... ') - exit_script(1) - except SystemExit as sys_exit: - exit_script(sys_exit.code) - except: - major_exception() - -# vim: sts=2 sw=2 ts=2 diff --git a/scripts/outer_scripts_to_review/winpe_root_menu.py b/scripts/outer_scripts_to_review/winpe_root_menu.py deleted file mode 100644 index 94669609..00000000 --- a/scripts/outer_scripts_to_review/winpe_root_menu.py +++ /dev/null @@ -1,23 +0,0 @@ -# Wizard Kit: WinPE Root Menu - -import os -import sys - -# Init -sys.path.append(os.path.dirname(os.path.realpath(__file__))) -from functions.winpe_menus import * -# Fix 7-Zip name -TOOLS['SevenZip'].pop('64') -init_global_vars() -set_title('{}: Root Menu'.format(KIT_NAME_FULL)) -set_log_file('WinPE.log') - -if __name__ == '__main__': - try: - menu_root() - except SystemExit as sys_exit: - exit_script(sys_exit.code) - except: - major_exception() - -# vim: sts=2 sw=2 ts=2 diff --git a/scripts/sfc_scan.py b/scripts/sfc_scan.py index 02d84f77..b3132f1a 100644 --- a/scripts/sfc_scan.py +++ b/scripts/sfc_scan.py @@ -19,7 +19,7 @@ def main(): print('') # Run - try_print.run('SFC scan...', wk.os.win.run_sfc_scan) + try_print.run('SFC scan...', wk.repairs.win.run_sfc_scan) # Done print('Done') From 625539c786c72fdfc25f424410ce674c5be32111 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Thu, 30 Sep 2021 15:37:06 -0600 Subject: [PATCH 40/40] Avoid crash when downloading files --- scripts/wk/kit/tools.py | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/scripts/wk/kit/tools.py b/scripts/wk/kit/tools.py index 50a98059..da3e69c4 100644 --- a/scripts/wk/kit/tools.py +++ b/scripts/wk/kit/tools.py @@ -27,7 +27,9 @@ CACHED_DIRS = {} def download_file(out_path, source_url, as_new=False, overwrite=False): """Download a file using requests, returns pathlib.Path.""" out_path = pathlib.Path(out_path).resolve() - download_msg = f'Downloading {out_path.name}...' + name = out_path.name + download_failed = None + download_msg = f'Downloading {name}...' if as_new: out_path = out_path.with_suffix(f'{out_path.suffix}.new') print(download_msg, end='', flush=True) @@ -40,15 +42,17 @@ def download_file(out_path, source_url, as_new=False, overwrite=False): out_path.parent.mkdir(parents=True, exist_ok=True) # Request download - response = requests.get(source_url, stream=True) - if not response.ok: - name = out_path.name - if as_new: - name = name[:-4] - LOG.error( - 'Failed to download file (status %s): %s', - response.status_code, name, - ) + try: + response = requests.get(source_url, stream=True) + except requests.RequestException as _err: + download_failed = _err + else: + if not response.ok: + download_failed = response + + # Download failed + if download_failed: + LOG.error('Failed to download file: %s', download_failed) raise GenericError(f'Failed to download file: {name}') # Write to file