diff --git a/.bin/Scripts/functions/browsers.py b/.bin/Scripts/functions/browsers.py index 777c9dc6..73d062d6 100644 --- a/.bin/Scripts/functions/browsers.py +++ b/.bin/Scripts/functions/browsers.py @@ -9,11 +9,11 @@ from settings.browsers import * browser_data = {} other_results = { 'Error': { - 'MultipleInstallationsError': 'Multiple installations detected', + 'MultipleInstallationsError': 'MULTIPLE INSTALLATIONS DETECTED', }, 'Warning': { - 'NotInstalledError': 'Not installed', - 'NoProfilesError': 'No profiles found', + 'NotInstalledError': 'NOT INSTALLED', + 'NoProfilesError': 'NO PROFILES FOUND', } } @@ -385,7 +385,7 @@ def install_adblock( # installation status. try_and_print(message='{}...'.format(browser), indent=indent, width=width, - cs='Done', function=popen_program, + cs='STARTED', function=popen_program, cmd=[exe_path, *urls], check=False) @@ -426,6 +426,12 @@ def list_homepages(indent=8, width=32): indent=' '*indent, width=width, name=name, page=page)) +def profile_present(browser_name): + """Checks if a profile was detected for browser, returns bool.""" + browser_name = browser_name.replace(' Chromium', '') + return bool(browser_data.get(browser_name, {}).get('profiles', False)) + + def reset_browsers(indent=8, width=32): """Reset all detected browsers to safe defaults.""" browser_list = [k for k, v in sorted(browser_data.items()) if v['profiles']] @@ -459,7 +465,7 @@ def scan_for_browsers(just_firefox=False, silent=False, skip_ie=False): pass else: try_and_print(message='{}...'.format(name), - function=get_browser_details, cs='Detected', + function=get_browser_details, cs='DETECTED', other_results=other_results, name=name) diff --git a/.bin/Scripts/functions/common.py b/.bin/Scripts/functions/common.py index cdf948fe..841d17e7 100644 --- a/.bin/Scripts/functions/common.py +++ b/.bin/Scripts/functions/common.py @@ -64,10 +64,13 @@ class GenericRepair(Exception): class MultipleInstallationsError(Exception): pass -class NotInstalledError(Exception): +class NoProfilesError(Exception): pass -class NoProfilesError(Exception): +class Not4KAlignedError(Exception): + pass + +class NotInstalledError(Exception): pass class OSInstalledLegacyError(Exception): @@ -88,6 +91,12 @@ class SecureBootNotAvailError(Exception): class SecureBootUnknownError(Exception): pass +class WindowsOutdatedError(Exception): + pass + +class WindowsUnsupportedError(Exception): + pass + # General functions def abort(show_prompt=True): diff --git a/.bin/Scripts/functions/info.py b/.bin/Scripts/functions/info.py index 84d92663..a08ad071 100644 --- a/.bin/Scripts/functions/info.py +++ b/.bin/Scripts/functions/info.py @@ -95,7 +95,7 @@ def get_installed_antivirus(): out = out.stdout.decode().strip() state = out.split('=')[1] state = hex(int(state)) - if str(state)[3:5] != '10': + if str(state)[3:5] not in ['10', '11']: programs.append('[Disabled] {}'.format(prod)) else: programs.append(prod) diff --git a/.bin/Scripts/functions/setup.py b/.bin/Scripts/functions/setup.py index e6472f00..51e2f3bc 100644 --- a/.bin/Scripts/functions/setup.py +++ b/.bin/Scripts/functions/setup.py @@ -85,6 +85,11 @@ def create_system_restore_point(): run_program(cmd) +def disable_fast_startup(): + """Disable Fast Startup.""" + write_registry_settings(SETTINGS_FAST_STARTUP, all_users=True) + + def disable_windows_telemetry(): """Disable Windows 10 telemetry settings with O&O ShutUp10.""" extract_item('ShutUp10', silent=True) @@ -95,6 +100,12 @@ def disable_windows_telemetry(): run_program(cmd) +def enable_hibernation(): + """Enable hibernation.""" + cmd = ['powercfg', '/hibernation', 'on'] + run_program(cmd) + + def enable_regback(): """Enable RegBack.""" write_registry_settings(SETTINGS_REGBACK, all_users=True) @@ -126,7 +137,7 @@ def enable_system_restore(): def update_clock(): """Set Timezone and sync clock.""" - run_program(['tzutil' ,'/s', WINDOWS_TIME_ZONE], check=False) + run_program(['tzutil', '/s', WINDOWS_TIME_ZONE], check=False) run_program(['net', 'stop', 'w32ime'], check=False) run_program( ['w32tm', '/config', '/syncfromflags:manual', @@ -158,6 +169,39 @@ def write_registry_settings(settings, all_users=False): # Installations +def find_current_software(): + """Find currently installed software, returns list.""" + ninite_extras_path = r'{BaseDir}\Installers\Extras'.format(**global_vars) + installers = [] + + # Browsers + scan_for_browsers(skip_ie=True, silent=True) + for browser in ('Google Chrome', 'Mozilla Firefox', 'Opera Chromium'): + if is_installed(browser): + installers.append( + r'{}\Web Browsers\{}.exe'.format(ninite_extras_path, browser)) + + # TODO: Add more sections + + return installers + +def find_missing_software(): + """Find missing software based on dirs/files present, returns list.""" + ninite_extras_path = r'{BaseDir}\Installers\Extras'.format(**global_vars) + installers = [] + + # Browsers + scan_for_browsers(skip_ie=True, silent=True) + for browser in ('Google Chrome', 'Mozilla Firefox', 'Opera Chromium'): + if profile_present(browser): + installers.append( + r'{}\Web Browsers\{}.exe'.format(ninite_extras_path, browser)) + + # TODO: Add more sections + + return installers + + def install_adobe_reader(): """Install Adobe Reader.""" cmd = [ @@ -207,8 +251,7 @@ def install_eset_nod32_av(scan_pups=True): 'PRODUCTTYPE=eav', 'PRODUCT_LANG=1033', 'PRODUCT_LANG_CODE=en-US', 'ADMINCFG="{}"'.format(config_file), ] - try_and_print(message='Installing ESET NOD32 AV...', - other_results=OTHER_RESULTS, function=run_program, cmd=cmd) + run_program(cmd) def install_firefox_extensions(): """Install Firefox extensions for all users.""" @@ -236,10 +279,9 @@ def install_libreoffice( use_mso_formats=False, vcredist=False): """Install LibreOffice using specified settings.""" cmd = [ - r'{}\Installers\Extras\Office\LibreOffice.msi'.format( + 'msiexec', '/passive', '/norestart', + '/i', r'{}\Installers\Extras\Office\LibreOffice.msi'.format( global_vars['BaseDir']), - '/qn', - '/norestart', 'REBOOTYESNO=No', 'ISCHECKFORPRODUCTUPDATES=0', 'QUICKSTART={}'.format(1 if quickstart else 0), @@ -250,21 +292,31 @@ def install_libreoffice( cmd.append('REGISTER_ALL_MSO_TYPES=1') else: cmd.append('REGISTER_NO_MSO_TYPES=1') - xcu_file = r'{APPDATA}LibreOffice\4\user\registrymodifications.xcu'.format( - **global_vars) + xcu_dir = r'{APPDATA}\LibreOffice\4\user'.format(**global_vars['Env']) + xcu_file = r'{}\registrymodifications.xcu'.format(xcu_dir) # Set default save format if use_mso_formats and not os.path.exists(xcu_file): + os.makedirs(xcu_dir, exist_ok=True) with open(xcu_file, 'w', encoding='utf-8', newline='\n') as f: f.write(LIBREOFFICE_XCU_DATA) # Install LibreOffice run_program(cmd, check=True) -def install_ninite_bundle(browsers_only=False, mse=False, libreoffice=False): +def install_ninite_bundle( + # pylint: disable=too-many-arguments,too-many-branches + base=True, + browsers_only=False, + libreoffice=False, + missing=False, + mse=False, + standard=True, + ): """Run Ninite installer(s), returns list of Popen objects.""" popen_objects = [] if browsers_only: + # This option is deprecated installer_path = r'{BaseDir}\Installers\Extras\Web Browsers'.format( **global_vars) scan_for_browsers(skip_ie=True, silent=True) @@ -272,26 +324,63 @@ def install_ninite_bundle(browsers_only=False, mse=False, libreoffice=False): if is_installed(browser): cmd = r'{}\{}.exe'.format(installer_path, browser) popen_objects.append(popen_program(cmd)) - elif global_vars['OS']['Version'] in ('8', '8.1', '10'): - # Modern selection - popen_objects.append( - popen_program(r'{BaseDir}\Installers\Extras\Bundles\Modern.exe'.format( - **global_vars))) - else: - # Legacy selection - if mse: - cmd = r'{BaseDir}\Installers\Extras\Security'.format(**global_vars) - cmd += r'\Microsoft Security Essentials.exe' - popen_objects.append(popen_program(cmd)) - popen_objects.append( - popen_program(r'{BaseDir}\Installers\Extras\Bundles\Legacy.exe'.format( - **global_vars))) + + # Bail + return popen_objects + + # Main selections + main_selections = [] + if base: + main_selections.append('base') + if standard: + if global_vars['OS']['Version'] in ('8', '8.1', '10'): + main_selections.append('standard') + else: + main_selections.append('standard7') + cmd = r'{}\Installers\Extras\Bundles\{}.exe'.format( + global_vars['BaseDir'], + '-'.join(main_selections), + ) + popen_objects.append(popen_program([cmd])) + + # Extra selections + extra_selections = {} + for cmd in find_current_software(): + extra_selections[cmd] = True + if missing: + for cmd in find_missing_software(): + extra_selections[cmd] = True + + # Remove overlapping selections + regex = [] + for n_name, n_group in NINITE_REGEX.items(): + if n_name in main_selections: + regex.extend(n_group) + regex = '({})'.format('|'.join(regex)) + extra_selections = { + cmd: True for cmd in extra_selections + if not re.search(regex, cmd, re.IGNORECASE) + } + + # Start extra selections + for cmd in extra_selections: + popen_objects.append(popen_program([cmd])) + + # Microsoft Security Essentials + if mse: + cmd = r'{}\Installers\Extras\Security\{}'.format( + global_vars['BaseDir'], + 'Microsoft Security Essentials.exe', + ) + popen_objects.append(popen_program([cmd])) # LibreOffice if libreoffice: - cmd = r'{BaseDir}\Installers\Extras\Office'.format(**global_vars) - cmd += r'\LibreOffice.exe' - popen_objects.append(popen_program(cmd)) + cmd = r'{}\Installers\Extras\Office\{}'.format( + global_vars['BaseDir'], + 'LibreOffice.exe', + ) + popen_objects.append(popen_program([cmd])) # Done return popen_objects @@ -324,6 +413,10 @@ def open_snappy_driver_origin(): popen_program(cmd, cwd=cwd, pipe=True) +def open_speedtest(): + popen_program(['start', '', 'https://fast.com'], shell=True) + + def open_windows_activation(): popen_program(['slui']) diff --git a/.bin/Scripts/functions/sw_diags.py b/.bin/Scripts/functions/sw_diags.py index 0e73195e..3432adab 100644 --- a/.bin/Scripts/functions/sw_diags.py +++ b/.bin/Scripts/functions/sw_diags.py @@ -6,10 +6,6 @@ from functions.common import * from settings.sw_diags import * -class Not4KAlignedError(Exception): - pass - - def check_4k_alignment(show_alert=False): """Check that all partitions are 4K aligned.""" aligned = True @@ -52,6 +48,37 @@ def check_connection(): abort() +def check_os_support_status(): + """Check if current OS is supported.""" + msg = '' + outdated = False + unsupported = False + + # Check OS version/notes + os_info = global_vars['OS'].copy() + if os_info['Notes'] == 'unsupported': + msg = 'The installed version of Windows is no longer supported' + unsupported = True + elif os_info['Notes'] == 'preview build': + msg = 'Preview builds are not officially supported' + unsupported = True + elif os_info['Version'] == '10' and os_info['Notes'] == 'outdated': + msg = 'The installed version of Windows is outdated' + outdated = True + if 'Preview' not in msg: + msg += '\n\nPlease consider upgrading before continuing setup.' + + # Show alert + if outdated or unsupported: + show_alert_box(msg) + + # Raise exception if necessary + if outdated: + raise WindowsOutdatedError + if unsupported: + raise WindowsUnsupportedError + + def check_secure_boot_status(show_alert=False): """Checks UEFI Secure Boot status via PowerShell.""" boot_mode = get_boot_mode() @@ -114,33 +141,6 @@ def get_boot_mode(): return type_str -def os_is_unsupported(show_alert=False): - """Checks if the current OS is unsupported, returns bool.""" - msg = '' - unsupported = False - - # Check OS version/notes - os_info = global_vars['OS'].copy() - if os_info['Notes'] == 'unsupported': - msg = 'The installed version of Windows is no longer supported' - unsupported = True - elif os_info['Notes'] == 'preview build': - msg = 'Preview builds are not officially supported' - unsupported = True - elif os_info['Version'] == '10' and os_info['Notes'] == 'outdated': - msg = 'The installed version of Windows is outdated' - unsupported = True - if 'Preview' not in msg: - msg += '\n\nPlease consider upgrading before continuing setup.' - - # Show alert - if unsupported and show_alert: - show_alert_box(msg) - - # Done - return unsupported - - def run_autoruns(): """Run AutoRuns in the background with VirusTotal checks enabled.""" extract_item('Autoruns', filter='autoruns*', silent=True) diff --git a/.bin/Scripts/settings/launchers.py b/.bin/Scripts/settings/launchers.py index 76dbd7d9..516f50ed 100644 --- a/.bin/Scripts/settings/launchers.py +++ b/.bin/Scripts/settings/launchers.py @@ -13,10 +13,10 @@ LAUNCHERS = { 'L_PATH': 'd7II', 'L_ITEM': 'd7II.exe', }, - 'New System Setup': { + 'System Setup': { 'L_TYPE': 'PyScript', 'L_PATH': 'Scripts', - 'L_ITEM': 'new_system_setup.py', + 'L_ITEM': 'system_setup.py', 'L_ELEV': 'True', }, 'Post-d7II Work': { @@ -25,23 +25,6 @@ LAUNCHERS = { 'L_ITEM': 'post_d7.py', 'L_ELEV': 'True', }, - 'System Checklist': { - 'L_TYPE': 'PyScript', - 'L_PATH': 'Scripts', - 'L_ITEM': 'system_checklist.py', - 'L_ELEV': 'True', - }, - 'System Checklist (HW)': { - 'L_TYPE': 'PyScript', - 'L_PATH': 'Scripts', - 'L_ITEM': 'system_checklist_hw.py', - 'L_ELEV': 'True', - }, - 'User Checklist': { - 'L_TYPE': 'PyScript', - 'L_PATH': 'Scripts', - 'L_ITEM': 'user_checklist.py', - }, }, r'.bin\Scripts\launchers_for_d7': { 'Browser Reset': { @@ -608,6 +591,31 @@ LAUNCHERS = { 'L_ARGS': '"%bin%\XMPlay\music.7z"', }, }, + r'Misc\Deprecated': { + 'New System Setup': { + 'L_TYPE': 'PyScript', + 'L_PATH': 'Scripts', + 'L_ITEM': 'new_system_setup.py', + 'L_ELEV': 'True', + }, + 'System Checklist': { + 'L_TYPE': 'PyScript', + 'L_PATH': 'Scripts', + 'L_ITEM': 'system_checklist.py', + 'L_ELEV': 'True', + }, + 'System Checklist (HW)': { + 'L_TYPE': 'PyScript', + 'L_PATH': 'Scripts', + 'L_ITEM': 'system_checklist_hw.py', + 'L_ELEV': 'True', + }, + 'User Checklist': { + 'L_TYPE': 'PyScript', + 'L_PATH': 'Scripts', + 'L_ITEM': 'user_checklist.py', + }, + }, r'Repairs': { 'AdwCleaner': { 'L_TYPE': 'Executable', diff --git a/.bin/Scripts/settings/setup.py b/.bin/Scripts/settings/setup.py index 72d6a56f..8fd6a5c4 100644 --- a/.bin/Scripts/settings/setup.py +++ b/.bin/Scripts/settings/setup.py @@ -155,6 +155,14 @@ SETTINGS_EXPLORER_USER = { }, } +# Fast Startup +SETTINGS_FAST_STARTUP = { + # Disable Fast Startup + r'SOFTWARE\Policies\Microsoft\Windows\System': { + 'DWORD Items': {'HiberbootEnabled': 0}, + }, + } + # LibreOffice LIBREOFFICE_XCU_DATA = ''' diff --git a/.bin/Scripts/settings/sources.py b/.bin/Scripts/settings/sources.py index e3ac0753..5474cb2b 100644 --- a/.bin/Scripts/settings/sources.py +++ b/.bin/Scripts/settings/sources.py @@ -73,10 +73,18 @@ VCREDIST_SOURCES = { '64': 'https://aka.ms/vs/15/release/vc_redist.x64.exe', }, } +NINITE_REGEX = { + 'base': ['7-Zip', 'VLC'], + 'standard': ['Google Chrome', 'Mozilla Firefox', 'SumatraPDF'], + 'standard7': ['Google Chrome', 'Mozilla Firefox', 'SumatraPDF'], + } NINITE_SOURCES = { 'Bundles': { - 'Legacy.exe': '.net4.7.2-7zip-chrome-firefox-sumatrapdf-vlc', - 'Modern.exe': '.net4.7.2-7zip-chrome-classicstart-firefox-sumatrapdf-vlc', + 'base.exe': '.net4.7.2-7zip-vlc', + 'base-standard.exe': '.net4.7.2-7zip-chrome-classicstart-firefox-sumatrapdf-vlc', + 'base-standard7.exe': '.net4.7.2-7zip-chrome-firefox-sumatrapdf-vlc', + 'standard.exe': 'chrome-classicstart-firefox-sumatrapdf', + 'standard7.exe': 'chrome-firefox-sumatrapdf', }, 'Audio-Video': { 'AIMP.exe': 'aimp', diff --git a/.bin/Scripts/system_setup.py b/.bin/Scripts/system_setup.py new file mode 100644 index 00000000..a9185da8 --- /dev/null +++ b/.bin/Scripts/system_setup.py @@ -0,0 +1,361 @@ +'''Wizard Kit: System Setup''' +# pylint: disable=wildcard-import +# 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 * +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, 'Fab': True, 'Cur': True, 'HW': False, 'Function': install_vcredists, 'Just run': True,}, + 'ESET NOD32 AV': {'New': True, 'Fab': True, 'Cur': True, 'HW': False, 'Function': install_eset_nod32_av, 'If answer': 'ESET', 'KWArgs': {'scan_pups': False},}, + 'LibreOffice': {'New': True, 'Fab': True, 'Cur': True, 'HW': False, 'Function': install_libreoffice, + 'If answer': 'LibreOffice', 'KWArgs': {'quickstart': False, 'register_mso_types': True, 'use_mso_formats': True, 'vcredist': False}, + }, + 'Ninite bundle': {'New': True, 'Fab': True, 'Cur': True, 'HW': False, 'Function': install_ninite_bundle, 'KWArgs': {'cs': 'STARTED'},}, + + # Browsers + 'Scanning for browsers': {'Info': True}, + 'Scan': {'New': True, 'Fab': 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, 'Fab': True, 'Cur': True, 'HW': False, 'Function': backup_browsers, 'Just run': True,}, + + # Install extensions + 'Installing Extensions': {'Info': True}, + 'Classic Shell skin': {'New': True, 'Fab': True, 'Cur': False, 'HW': False, 'Function': install_classicstart_skin, 'Win10 only': True,}, + 'Chrome extensions': {'New': True, 'Fab': True, 'Cur': True, 'HW': False, 'Function': install_chrome_extensions,}, + 'Firefox extensions': {'New': True, 'Fab': True, 'Cur': True, 'HW': False, 'Function': install_firefox_extensions,}, + + # Configure software' + 'Configuring Programs': {'Info': True}, + 'Browser add-ons': {'New': True, 'Fab': True, 'Cur': True, 'HW': False, 'Function': install_adblock, 'Just run': True, + 'Pause': 'Please enable uBlock Origin for all browsers', + }, + 'Classic Start': {'New': True, 'Fab': True, 'Cur': False, 'HW': False, 'Function': config_classicstart, 'Win10 only': True,}, + 'Explorer (user)': {'New': True, 'Fab': True, 'Cur': True, 'HW': False, 'Function': config_explorer_user, 'Win10 only': True,}, + 'Explorer (system)': {'New': True, 'Fab': True, 'Cur': True, 'HW': False, 'Function': config_explorer_system, 'Win10 only': True,}, + 'Disable telemetry': {'New': True, 'Fab': True, 'Cur': True, 'HW': False, 'Function': disable_windows_telemetry, 'Win10 only': True,}, + 'Disable Fast Startup': {'New': True, 'Fab': True, 'Cur': True, 'HW': False, 'Function': disable_fast_startup, 'If answer': 'Fast-Hiber', 'Win10 only': True,}, + 'Enable Hibernation': {'New': True, 'Fab': True, 'Cur': True, 'HW': False, 'Function': enable_hibernation, 'If answer': 'Fast-Hiber', 'Win10 only': True,}, + 'Enable RegBack': {'New': True, 'Fab': True, 'Cur': True, 'HW': True, 'Function': enable_regback, 'Win10 only': True,}, + 'Windows 10 Updates': {'New': True, 'Fab': True, 'Cur': True, 'HW': True, 'Function': config_windows_updates, 'Win10 only': True,}, + 'Enable BSoD mini dumps': {'New': True, 'Fab': True, 'Cur': True, 'HW': True, 'Function': enable_mini_dumps,}, + 'Enable System Restore': {'New': True, 'Fab': True, 'Cur': True, 'HW': True, 'Function': enable_system_restore,}, + 'Create System Restore': {'New': True, 'Fab': True, 'Cur': True, 'HW': True, 'Function': create_system_restore_point,}, + 'Update Clock': {'New': True, 'Fab': True, 'Cur': True, 'HW': False, 'Function': update_clock,}, + 'Restart Explorer': {'New': True, 'Fab': True, 'Cur': True, 'HW': False, 'Function': restart_explorer,}, + + # Cleanup + 'Cleaning up': {'Info': True}, + 'AdwCleaner': {'New': True, 'Fab': True, 'Cur': True, 'HW': False, 'Function': cleanup_adwcleaner,}, + 'Desktop': {'New': True, 'Fab': True, 'Cur': True, 'HW': False, 'Function': cleanup_desktop,}, + 'Emsisoft s2cmd': {'New': True, 'Fab': True, 'Cur': True, 'HW': False, 'Function': cleanup_emsisoft,}, + 'Registry Backup(s)': {'New': True, 'Fab': True, 'Cur': True, 'HW': False, 'Function': cleanup_regbackups,}, + 'KIT_NAME_FULL': {'New': True, 'Fab': True, 'Cur': True, 'HW': False, 'Function': delete_empty_folders,}, + + # System Info + 'Exporting system info': {'Info': True}, + 'AIDA64 Report': {'New': True, 'Fab': True, 'Cur': True, 'HW': False, 'Function': run_aida64,}, + 'File listing': {'New': True, 'Fab': True, 'Cur': True, 'HW': False, 'Function': backup_file_list,}, + 'Power plans': {'New': True, 'Fab': True, 'Cur': True, 'HW': True, 'Function': backup_power_plans,}, + 'Product Keys': {'New': True, 'Fab': True, 'Cur': True, 'HW': True, 'Function': run_produkey,}, + 'Registry': {'New': True, 'Fab': True, 'Cur': True, 'HW': True, 'Function': backup_registry,}, + + # Show Summary + 'Summary': {'Info': True}, + 'Operating System': {'New': True, 'Fab': True, 'Cur': True, 'HW': True, 'Function': show_os_name, 'KWArgs': {'ns': 'Unknown', 'silent_function': False},}, + 'Activation': {'New': True, 'Fab': True, 'Cur': True, 'HW': True, 'Function': show_os_activation, 'KWArgs': {'ns': 'Unknown', 'silent_function': False},}, + 'BIOS Activation': {'New': True, 'Fab': True, 'Cur': True, 'HW': False, 'Function': activate_with_bios, 'If not activated': True,}, + 'Secure Boot': {'New': True, 'Fab': True, 'Cur': True, 'HW': True, 'Function': check_secure_boot_status, 'KWArgs': {'show_alert': True},}, + 'Installed RAM': {'New': True, 'Fab': True, 'Cur': True, 'HW': True, 'Function': show_installed_ram, 'KWArgs': {'ns': 'Unknown', 'silent_function': False},}, + 'Show free space': {'New': True, 'Fab': True, 'Cur': True, 'HW': True, 'Function': show_free_space, 'Just run': True,}, + 'Installed AV': {'New': True, 'Fab': True, 'Cur': True, 'HW': True, 'Function': get_installed_antivirus, 'KWArgs': {'ns': 'Unknown', 'print_return': True},}, + 'Installed Office': {'New': True, 'Fab': True, 'Cur': True, 'HW': False, 'Function': get_installed_office, 'KWArgs': {'ns': 'Unknown', 'print_return': True},}, + 'Partitions 4K aligned': {'New': True, 'Fab': True, 'Cur': True, 'HW': True, 'Function': check_4k_alignment, 'KWArgs': {'cs': 'True', 'ns': 'False'},}, + + # Open things + 'Opening Programs': {'Info': True}, + 'Device Manager': {'New': True, 'Fab': True, 'Cur': True, 'HW': True, 'Function': open_device_manager, 'KWArgs': {'cs': 'STARTED'},}, + 'HWiNFO sensors': {'New': True, 'Fab': True, 'Cur': True, 'HW': True, 'Function': run_hwinfo_sensors, 'KWArgs': {'cs': 'STARTED'},}, + 'Snappy': {'New': True, 'Fab': True, 'Cur': True, 'HW': True, 'Function': open_snappy_driver_origin, 'KWArgs': {'cs': 'STARTED'},}, + 'Speed test': {'New': True, 'Fab': True, 'Cur': True, 'HW': True, 'Function': open_speedtest, 'KWArgs': {'cs': 'STARTED'},}, + 'Windows Updates': {'New': True, 'Fab': True, 'Cur': True, 'HW': False, 'Function': open_windows_updates, 'KWArgs': {'cs': 'STARTED'},}, + 'Windows Activation': {'New': True, 'Fab': True, 'Cur': True, 'HW': False, 'Function': open_windows_activation, 'If not activated': True, 'KWArgs': {'cs': 'STARTED'},}, + 'Sleep': {'New': True, 'Fab': True, 'Cur': True, 'HW': True, 'Function': sleep, 'Just run': True, 'KWArgs': {'seconds': 3},}, + 'XMPlay': {'New': True, 'Fab': 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 + 'ESET': {'New': None, 'Fab': None, 'Cur': None, 'HW': False}, + 'MSE': {'New': None, 'Fab': None, 'Cur': None, 'HW': False}, + + # Fast Startup / Hibernation + 'Fast-Hiber': {'New': None, 'Fab': None, 'Cur': None, 'HW': False}, + + # LibreOffice + 'LibreOffice': {'New': None, 'Fab': None, 'Cur': None, 'HW': False}, + + # Ninite + 'Base': {'New': True, 'Fab': True, 'Cur': True, 'HW': False}, + 'Missing': {'New': False, 'Fab': True, 'Cur': False, 'HW': False}, + 'Standard': {'New': True, 'Fab': True, 'Cur': False, 'HW': False}, + } +# pylint: enable=bad-whitespace,line-too-long + + +# Functions +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 + _action['Enabled'] = _val.get(setup_mode, False) + if _if_answer: + _action['Enabled'] &= answers[_if_answer] + if _win10_only: + _action['Enabled'] &= global_vars['OS']['Version'] == '10' + + # 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': + _key = KIT_NAME_FULL + _action['KWArgs'] = {'folder_path': global_vars['ClientDir']} + elif _key == 'Ninite bundle': + _action['KWArgs'] = {kw.lower(): kv for kw, kv in answers.items()} + _action['KWArgs'].pop('eset', None) + + # 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['ESET'] is None or answers['MSE'] is None: + answers.update(get_av_selection()) + + if answers['LibreOffice'] is None: + answers['LibreOffice'] = ask('Install LibreOffice?') + + if answers['Fast-Hiber'] is None: + if global_vars['OS']['Version'] == '10': + print_standard(' ') + print_standard('Disable Fast Startup and enable Hibernation?') + print_standard(' Recommended for SSDs, optional for HDDs') + answers['Fast-Hiber'] = ask(' Proceed?') + else: + answers['Fast-Hiber'] = False + + return answers + + +def get_av_selection(): + """Get AV selection.""" + av_answers = { + 'ESET': False, + 'MSE': False, + } + av_options = [ + {'Name': 'ESET NOD32 AV'}, + { + '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 'ESET' in av_options[index]['Name']: + av_answers['ESET'] = True + av_answers['MSE'] = False + elif 'Microsoft' in av_options[index]['Name']: + av_answers['ESET'] = False + 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': 'Fab', 'Display Name': 'Clean install with data migration'}, + {'Name': 'Cur', 'Display Name': 'Original OS (post-d7II 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 + 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() + + # 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() + + # 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()