## MAJOR refactoring in progress ##
# BROKEN SCRIPTS #
(These scripts need updated to use the new global_vars & try_and_print)
* user_data_transfer.py
* install_sw_bundle.py
* All Python scripts
* PLAN: Replace vars_wk with global_vars
* functions.py
* PLAN: Will hold (nearly?) all functions going forward
* Should simplify the remaining scripts
* (e.g. reset_browsers and sw_diagnostics both had a backup_browsers())
* PLAN: Move all program definitions to functions.py
* (e.g. vars_wk['SevenZip'] --> global_vars['Programs']['SevenZip'])
* Added major_exception()
* Should be called if anything goes wrong to alert user and provide info
* Added non_clobber_rename()
* Appends a number (if necessary) to avoid overwriting data
* Added popen_program()
* Removes subprocess req for sw_checklist
* Added try_and_print()
* Run a function and show CS/NS/etc
* Can add additional "result" strings via Exception classes
* Passes unrecognized args/kwargs to the function
* Used by scripts to standardize message formatting and error handling
* exit_script() now handles opening the log (if set) and killing caffeine.exe
* Refactored init_vars_wk/os code to work with global_vars
* Uses the try_and_print function for better formatting and error handling
* BREAKING: 'OS' vars now located in global_vars['OS'] (including 'Arch')
* OS labeled as 'outdated', 'very outdated', and 'unrecognized' as needed
* BREAKING: renamed PROGRAMS to TOOLS
* Expanded TOOLS
* Removed log_file as a required argument from all functions
* Removed vars_wk/global_vars as a required argument from all functions
* Removed unused WinPE functions
* Sorted functions
* user_checklist() (formerly reset_browsers())
* Most functions moved to functions.py (see above)
* Browsers
* Work has been split into backup, reset, and config sections
* Script now asks all questions before starting backup/reset/config
* Script now forces the homepage to DEFAULT_HOMEPAGE (set in functions.py)
* (i.e. it no longer asks first, it just does it)
* Current homepages are listed where possible before backup/reset/config
* Launch/Launchers
* Added QuickBooks support
* Removed launchers
* CPU-Z
* HWMonitor
* PerfMonitor2
* SanDisk Express Cache
* Shortcut Cleaner
* SuperAntiSpyware (SAS)
* Replaced Notepad2-Mod with Notepad++
198 lines
8.1 KiB
Python
198 lines
8.1 KiB
Python
# Wizard Kit: Copy user data to the system over the network
|
|
|
|
import os
|
|
import re
|
|
from operator import itemgetter
|
|
|
|
# Init
|
|
os.chdir(os.path.dirname(os.path.realpath(__file__)))
|
|
os.system('title Wizard Kit: Data 1')
|
|
from functions import *
|
|
init_global_vars()
|
|
set_global_vars(LogFile='{LogDir}\\Data 1.log'.format(**global_vars))
|
|
set_global_vars(TransferDir='{ClientDir}\\Transfer'.format(**global_vars))
|
|
|
|
def abort():
|
|
print_warning('Aborted.')
|
|
exit_script(global_vars)
|
|
|
|
def transfer_file_based(source_path, subdir=None):
|
|
# Set Destination
|
|
if subdir is None:
|
|
dest_path = global_vars['TransferDir']
|
|
else:
|
|
dest_path = '{TransferDir}\\{subdir}'.format(subdir=subdir, **global_vars)
|
|
os.makedirs(dest_path, exist_ok=True)
|
|
|
|
# Main copy
|
|
selected_items = []
|
|
for item in os.scandir(source_path):
|
|
if REGEX_INCL_ROOT_ITEMS.search(item.name):
|
|
selected_items.append(item.path)
|
|
elif not REGEX_EXCL_ROOT_ITEMS.search(item.name):
|
|
if ask('Copy: "{name}" item?'.format(name=item.name)):
|
|
selected_items.append(item.path)
|
|
if len(selected_items) > 0:
|
|
_args = global_vars['FastCopyArgs'].copy() + selected_items
|
|
_args.append('/to={dest_path}\\'.format(dest_path=dest_path))
|
|
try:
|
|
print_standard('Copying main user data...')
|
|
run_program(global_vars['FastCopy'], _args, check=True)
|
|
except subprocess.CalledProcessError:
|
|
print_warning('WARNING: Errors encountered while copying main user data')
|
|
else:
|
|
print_error('ERROR: No files selected for transfer?')
|
|
abort()
|
|
|
|
# Fonts
|
|
selected_items = []
|
|
if os.path.exists('{source}\\Windows\\Fonts'.format(source=source_path)):
|
|
selected_items.append('{source}\\Windows\\Fonts'.format(source=source_path))
|
|
if len(selected_items) > 0:
|
|
_args = global_vars['FastCopyArgs'].copy() + selected_items
|
|
_args.append('/to={dest_path}\\Windows\\'.format(dest_path=dest_path))
|
|
try:
|
|
print_standard('Copying Fonts...')
|
|
run_program(global_vars['FastCopy'], _args, check=True)
|
|
except subprocess.CalledProcessError:
|
|
print_warning('WARNING: Errors encountered while copying Fonts')
|
|
|
|
# Registry
|
|
selected_items = []
|
|
if os.path.exists('{source}\\Windows\\System32\\config'.format(source=source_path)):
|
|
selected_items.append('{source}\\Windows\\System32\\config'.format(source=source_path))
|
|
if os.path.exists('{source}\\Windows\\System32\\OEM'.format(source=source_path)):
|
|
selected_items.append('{source}\\Windows\\System32\\OEM'.format(source=source_path))
|
|
if len(selected_items) > 0:
|
|
_args = global_vars['FastCopyArgs'].copy() + selected_items
|
|
_args.append('/to={dest_path}\\Windows\\System32\\'.format(dest_path=dest_path))
|
|
try:
|
|
print_standard('Copying Registry...')
|
|
run_program(global_vars['FastCopy'], _args, check=True)
|
|
except subprocess.CalledProcessError:
|
|
print_warning('WARNING: Errors encountered while copying registry')
|
|
|
|
def transfer_image_based(source_path):
|
|
print_standard('Assessing image...')
|
|
os.makedirs(global_vars['TransferDir'], exist_ok=True)
|
|
|
|
# Scan source
|
|
_args = [
|
|
'dir',
|
|
'{source}'.format(source=source_path), '1']
|
|
try:
|
|
_list = run_program(global_vars['Tools']['wimlib-imagex'], _args, check=True)
|
|
except subprocess.CalledProcessError as err:
|
|
print_error('ERROR: Failed to get file list.')
|
|
print(err)
|
|
abort()
|
|
|
|
# Add items to list
|
|
selected_items = []
|
|
root_items = [i.strip() for i in _list.stdout.decode('utf-8', 'ignore').splitlines() if i.count('\\') == 1 and i.strip() != '\\']
|
|
for item in root_items:
|
|
if REGEX_INCL_ROOT_ITEMS.search(item):
|
|
selected_items.append(item)
|
|
elif not REGEX_EXCL_ROOT_ITEMS.search(item):
|
|
if ask('Extract: "{name}" item?'.format(name=item)):
|
|
selected_items.append(item)
|
|
|
|
# Extract files
|
|
if len(selected_items) > 0:
|
|
# Write files.txt
|
|
with open('{TmpDir}\\wim_files.txt'.format(**global_vars), 'w') as f:
|
|
# Defaults
|
|
for item in EXTRA_INCL_WIM_ITEMS:
|
|
f.write('{item}\n'.format(item=item))
|
|
for item in selected_items:
|
|
f.write('{item}\n'.format(item=item))
|
|
try:
|
|
print_standard('Extracting user data...')
|
|
_args = [
|
|
'extract',
|
|
'{source}'.format(source=source_path), '1',
|
|
'@{TmpDir}\\wim_files.txt'.format(**global_vars),
|
|
'--dest-dir={TransferDir}\\'.format(**global_vars),
|
|
'--no-acls',
|
|
'--nullglob']
|
|
run_program(global_vars['Tools']['wimlib-imagex'], _args, check=True)
|
|
except subprocess.CalledProcessError:
|
|
print_warning('WARNING: Errors encountered while extracting user data')
|
|
else:
|
|
print_error('ERROR: No files selected for extraction?')
|
|
abort()
|
|
|
|
if __name__ == '__main__':
|
|
stay_awake(global_vars)
|
|
# Check for existing TransferDir
|
|
if os.path.exists(global_vars['TransferDir']):
|
|
print_warning('Folder "{TransferDir}" exists. This script will rename the existing folder in order to avoid overwriting data.'.format(**global_vars))
|
|
if (ask('Rename existing folder and proceed?')):
|
|
_old_transfer = '{TransferDir}.old'.format(**global_vars)
|
|
_i = 1;
|
|
while os.path.exists(_old_transfer):
|
|
_old_transfer = '{TransferDir}.old{i}'.format(i=_i, **global_vars)
|
|
_i += 1
|
|
print_info('Renaming "{TransferDir}" to "{old_transfer}"'.format(old_transfer=_old_transfer, **global_vars))
|
|
os.rename(global_vars['TransferDir'], _old_transfer)
|
|
else:
|
|
abort()
|
|
|
|
# Set ticket number
|
|
ticket = None
|
|
while ticket is None:
|
|
tmp = input('Enter ticket number: ')
|
|
if re.match(r'^([0-9]+([-_]?\w+|))$', tmp):
|
|
ticket = tmp
|
|
|
|
# Get backup
|
|
backup_source = select_backup(ticket)
|
|
if backup_source is None:
|
|
abort()
|
|
|
|
# Determine restore method
|
|
extract_item('wimlib', global_vars, silent=True)
|
|
restore_source = None
|
|
restore_options = []
|
|
_file_based = False
|
|
for item in os.scandir(backup_source.path):
|
|
if item.is_dir():
|
|
_file_based = True
|
|
restore_options.append({'Name': 'File-Based:\t{source}'.format(source=item.name), 'Source': item})
|
|
for _subitem in os.scandir(item.path):
|
|
if is_valid_wim_image(_subitem):
|
|
restore_options.append({'Name': 'Image-Based: {dir}\\{source}'.format(dir=item.name, source=_subitem.name), 'Source': _subitem})
|
|
elif is_valid_wim_image(item):
|
|
restore_options.append({'Name': 'Image-Based:\t{source}'.format(source=item.name), 'Source': item})
|
|
if _file_based:
|
|
restore_options.append({'Name': 'File-Based:\t.', 'Source': backup_source})
|
|
restore_options = sorted(restore_options, key=itemgetter('Name'))
|
|
actions = [{'Name': 'Quit', 'Letter': 'Q'}]
|
|
if len(restore_options) > 0:
|
|
selection = menu_select('Which backup are we using? (Path: {path})'.format(path=backup_source.path), restore_options, actions)
|
|
if selection == 'Q':
|
|
abort()
|
|
else:
|
|
restore_source = restore_options[int(selection)-1]['Source']
|
|
else:
|
|
print_error('ERROR: No restoration options detected.')
|
|
abort()
|
|
|
|
# Start transfer
|
|
print_info('Using backup: {path}'.format(path=restore_source.path))
|
|
if restore_source.is_dir():
|
|
transfer_file_based(restore_source.path)
|
|
# Check for Windows.old*
|
|
for item in os.scandir(restore_source.path):
|
|
if item.is_dir() and re.search(r'^Windows.old', item.name, re.IGNORECASE):
|
|
transfer_file_based(item.path, subdir=item.name)
|
|
if restore_source.is_file():
|
|
transfer_image_based(restore_source.path)
|
|
cleanup_transfer()
|
|
|
|
# Done
|
|
umount_backup_shares()
|
|
print_success('Done.')
|
|
run_kvrt()
|
|
pause("Press Enter to exit...")
|
|
exit_script(global_vars)
|