diff --git a/Scripts/functions.py b/Scripts/functions.py index f7aea8f2..3f69b408 100644 --- a/Scripts/functions.py +++ b/Scripts/functions.py @@ -150,13 +150,13 @@ def assign_volume_letters(): except: pass -def remove_volume_letters(): +def remove_volume_letters(keep=None): with open(diskpart_script, 'w') as script: script.write('list volume\n') process_return = run_program('diskpart /s {script}'.format(script=diskpart_script)) with open(diskpart_script, 'w') as script: for tmp in re.findall(r'Volume (\d+)\s+([A-Za-z]?)\s+', process_return.stdout.decode()): - if tmp[1] != '': + if tmp[1] != '' and tmp[1] != keep: script.write('select volume {number}\n'.format(number=tmp[0])) script.write('remove\n') try: @@ -192,7 +192,7 @@ def select_minidump_path(): def find_windows_image(filename=None): """Search for a Windows source image file on local drives and network drives (in that order)""" - image_file = None + image = {} # Bail early if filename is None: @@ -203,19 +203,30 @@ def find_windows_image(filename=None): for tmp in re.findall(r'.*([A-Za-z]):\\', process_return.stdout.decode()): for ext in ['esd', 'wim', 'swm']: if os.path.isfile('{drive}:\\images\\{filename}.{ext}'.format(drive=tmp[0], ext=ext, filename=filename)): - image_file = '{drive}:\\images\\{filename}.{ext}'.format(drive=tmp[0], ext=ext, filename=filename) + image['Ext'] = ext + image['File'] = '{drive}:\\images\\{filename}'.format(drive=tmp[0], filename=filename) + image['Glob'] = '--ref="{File}*.swm"'.format(**image) if ext == 'swm' else '' + image['Source'] = tmp[0] break # Check for network source (if necessary) - if image_file is None: + if not any(image): if not WINDOWS_SERVER['Mounted']: mount_windows_share() - for ext in ['esd', 'wim']: + for ext in ['esd', 'wim', 'swm']: if os.path.isfile('\\\\{IP}\\{Share}\\images\\{filename}.{ext}'.format(ext=ext, filename=filename, **WINDOWS_SERVER)): - image_file = '\\\\{IP}\\{Share}\\images\\{filename}.{ext}'.format(ext=ext, filename=filename, **WINDOWS_SERVER) + image['Ext'] = ext + image['File'] = '\\\\{IP}\\{Share}\\images\\{filename}'.format(filename=filename, **WINDOWS_SERVER) + image['Glob'] = '--ref="{File}*.swm"'.format(**image) if ext == 'swm' else '' + image['Source'] = None break - - return image_file + + # Display image to be used (if any) and return + if any(image): + print_info('Using image: {File}.{Ext}'.format(**image)) + return image + else: + return None def format_gpt(disk=None, windows_family=None): """Format disk for use as a Windows OS drive using the GPT (UEFI) layout.""" @@ -431,16 +442,42 @@ def select_disk(prompt='Which disk?'): def select_windows_version(): versions = [ - {'Name': 'Windows 7 Home Basic', 'ImageFile': 'Win7', 'ImageName': 'Windows 7 HOMEBASIC', 'Family': '7'}, - {'Name': 'Windows 7 Home Premium', 'ImageFile': 'Win7', 'ImageName': 'Windows 7 HOMEPREMIUM', 'Family': '7'}, - {'Name': 'Windows 7 Professional', 'ImageFile': 'Win7', 'ImageName': 'Windows 7 PROFESSIONAL', 'Family': '7'}, - {'Name': 'Windows 7 Ultimate', 'ImageFile': 'Win7', 'ImageName': 'Windows 7 ULTIMATE', 'Family': '7'}, + {'Name': 'Windows 7 Home Basic', + 'ImageFile': 'Win7', + 'ImageName': 'Windows 7 HOMEBASIC', + 'Family': '7'}, + {'Name': 'Windows 7 Home Premium', + 'ImageFile': 'Win7', + 'ImageName': 'Windows 7 HOMEPREMIUM', + 'Family': '7'}, + {'Name': 'Windows 7 Professional', + 'ImageFile': 'Win7', + 'ImageName': 'Windows 7 PROFESSIONAL', + 'Family': '7'}, + {'Name': 'Windows 7 Ultimate', + 'ImageFile': 'Win7', + 'ImageName': 'Windows 7 ULTIMATE', + 'Family': '7'}, - {'Name': 'Windows 8.1', 'ImageFile': 'Win8', 'ImageName': 'Windows 8.1', 'Family': '8', 'CRLF': True}, - {'Name': 'Windows 8.1 Pro', 'ImageFile': 'Win8', 'ImageName': 'Windows 8.1 Pro', 'Family': '8'}, + {'Name': 'Windows 8.1', + 'ImageFile': 'Win8', + 'ImageName': 'Windows 8.1', + 'Family': '8', + 'CRLF': True}, + {'Name': 'Windows 8.1 Pro', + 'ImageFile': 'Win8', + 'ImageName': 'Windows 8.1 Pro', + 'Family': '8'}, - {'Name': 'Windows 10 Home', 'ImageFile': 'Win10', 'ImageName': 'Windows 10 Home', 'Family': '10', 'CRLF': True}, - {'Name': 'Windows 10 Pro', 'ImageFile': 'Win10', 'ImageName': 'Windows 10 Pro', 'Family': '10'}, + {'Name': 'Windows 10 Home', + 'ImageFile': 'Win10', + 'ImageName': 'Windows 10 Home', + 'Family': '10', + 'CRLF': True}, + {'Name': 'Windows 10 Pro', + 'ImageFile': 'Win10', + 'ImageName': 'Windows 10 Pro', + 'Family': '10'}, ] actions = [ {'Name': 'Main Menu', 'Letter': 'M'}, diff --git a/Scripts/menu.py b/Scripts/menu.py index e5adc729..3c58bd93 100644 --- a/Scripts/menu.py +++ b/Scripts/menu.py @@ -64,7 +64,7 @@ def menu_backup_imaging(): # List (and update) partition details for selected drive os.system('cls') - print('Details for selected drive:\n') + print('Create Backup - Details:\n') print(' Drive: {Size}\t[{Table}] ({Type}) {Name}\n'.format(**disk)) clobber_risk = 0 width=len(str(len(disk['Partitions']))) @@ -84,7 +84,8 @@ def menu_backup_imaging(): par['ImagePath'] = '\\\\{IP}\\{Share}\\{ticket}'.format(ticket=ticket, **dest) else: par['ImagePath'] = '{Letter}:\\{ticket}'.format(ticket=ticket, **dest) - par['ImageFile'] = '{Number}_{ImageName}.wim'.format(**par) + par['ImageFile'] = '{Number}_{ImageName}'.format(**par) + par['ImageFile'] = '{fixed_name}.wim'.format(fixed_name=re.sub(r'\W', '_', par['ImageFile'])) # Check for existing backups par['ImageExists'] = False @@ -108,9 +109,9 @@ def menu_backup_imaging(): elif len(bad_parts) == 1: print_warning(' * Unable to backup this partition') if clobber_risk > 1: - print_info(' + These partitions already have backup images on {TrueName}:'.format(**dest)) + print_info(' + These partitions already have backup images on {Display Name}:'.format(**dest)) elif clobber_risk == 1: - print_info(' + This partition already has a backup image on {TrueName}:'.format(**dest)) + print_info(' + This partition already has a backup image on {Display Name}:'.format(**dest)) if clobber_risk + len(bad_parts) > 1: print_warning('\nIf you continue the partitions marked above will NOT be backed up.\n') if clobber_risk + len(bad_parts) == 1: @@ -131,7 +132,7 @@ def menu_backup_imaging(): if par['Number'] in bad_parts: print_warning('Skipped.') else: - cmd = '{bin}\\wimlib\\wimlib-imagex capture {Letter}:\\ "{ImagePath}\\{ImageFile}" "{ImageName}" "{ImageName}" --check --compress=fast'.format(bin=bin, **par) + cmd = '{bin}\\wimlib\\wimlib-imagex capture {Letter}:\\ "{ImagePath}\\{ImageFile}" "{ImageName}" "{ImageName}" --compress=fast'.format(bin=bin, **par) if par['ImageExists']: print_warning('Skipped.') else: @@ -144,9 +145,29 @@ def menu_backup_imaging(): errors = True par['Error'] = err.stderr.decode().splitlines() + # Verify backup(s) + if len(par) - len(bad_parts) > 1: + print('\n\n Verifying backups\n') + else: + print('\n\n Verifying backup\n') + for par in disk['Partitions']: + if par['Number'] not in bad_parts: + print(' Partition {Number} Image...\t\t'.format(**par), end='', flush=True) + cmd = '{bin}\\wimlib\\wimlib-imagex verify "{ImagePath}\\{ImageFile}" --nocheck'.format(bin=bin, **par) + if not os.path.exists('{ImagePath}\\{ImageFile}'.format(**par)): + print_error('Missing.') + else: + try: + run_program(cmd) + print_success('OK.') + except subprocess.CalledProcessError as err: + print_error('Damaged.') + errors = True + par['Error'] = par.get('Error', []) + err.stderr.decode().splitlines() + # Print summary if errors: - print_warning('\nErrors were encountered during imaging and are detailed below.') + print_warning('\nErrors were encountered and are detailed below.') for par in [p for p in disk['Partitions'] if 'Error' in p]: print(' Partition {Number} Error:'.format(**par)) for line in par['Error']: @@ -169,8 +190,8 @@ def menu_windows_setup(): abort_to_main_menu('Aborting Windows setup') # Find Windows image - image_file = find_windows_image(selected_windows_version['ImageFile']) - if image_file is None: + image = find_windows_image(selected_windows_version['ImageFile']) + if not any(image): print_error('Failed to find Windows source image for {winver}'.format(winver=selected_windows_version['Name'])) abort_to_main_menu('Aborting Windows setup') @@ -221,7 +242,7 @@ def menu_windows_setup(): abort_to_main_menu('Aborting Windows setup') # Release currently used volume letters (ensures that the drives will get S, T, & W as needed below) - remove_volume_letters() + remove_volume_letters(keep=image['Source']) # Format and partition drive if (use_gpt): @@ -232,7 +253,7 @@ def menu_windows_setup(): # Apply Windows image errors = False print(' Applying image...') - cmd = '{bin}\\wimlib\\wimlib-imagex apply "{image_file}" "{ImageName}" W:\\'.format(bin=bin, image_file=image_file, **selected_windows_version) + cmd = '{bin}\\wimlib\\wimlib-imagex apply "{File}.{Ext}" "{ImageName}" W:\\ {Glob}'.format(bin=bin, **image, **selected_windows_version) try: run_program(cmd) except subprocess.CalledProcessError: @@ -251,8 +272,8 @@ def menu_windows_setup(): try: run_program('W:\\Windows\\System32\\reagentc /setreimage /path T:\\Recovery\\WindowsRE /target W:\\Windows') except subprocess.CalledProcessError: - errors = True - print_error('Failed to setup WindowsRE files.') + # errors = True # Changed to warning. + print_warning('Failed to setup WindowsRE files.') # Print summary if errors: diff --git a/WK/amd64/conemu-maximus5/ConEmu.xml b/WK/amd64/conemu-maximus5/ConEmu.xml index 4d75ab86..9752d747 100644 --- a/WK/amd64/conemu-maximus5/ConEmu.xml +++ b/WK/amd64/conemu-maximus5/ConEmu.xml @@ -1,7 +1,7 @@ - + @@ -112,7 +112,7 @@ - + @@ -123,7 +123,7 @@ - + @@ -134,10 +134,10 @@ - + - + @@ -483,9 +483,9 @@ - + - + @@ -494,7 +494,7 @@ - + @@ -503,7 +503,7 @@ - + @@ -512,7 +512,7 @@ - + @@ -523,11 +523,11 @@ - + - - + + @@ -628,7 +628,7 @@ - + diff --git a/WK/x86/conemu-maximus5/ConEmu.xml b/WK/x86/conemu-maximus5/ConEmu.xml index 4d75ab86..a54f9ab5 100644 --- a/WK/x86/conemu-maximus5/ConEmu.xml +++ b/WK/x86/conemu-maximus5/ConEmu.xml @@ -112,7 +112,7 @@ - +