bobomb Posted December 9, 2021 Share Posted December 9, 2021 (edited) I am trying to use the stuff Ive learned so far to put a USB burning tool together for WinXPE and SE ISO's (Or any WinPE ISO that is boot.wim/winre based that contains CdUsb.Y empty marker file in root of ISO) , I usually cmd my way though things and I dont know all the alternatives in AutoIT yet, diskpart and xcopy are both pretty solid 😜 but I do love your language, and i am understanding it faster than I thought, but do still need some guidance.. My progress bar is riddled all throughout the script, I do not see a better way off the top of my head, anyone have any suggestions? Also is there an easy way to show progress % in titlebar? Everything works fine I just want to make it better.. Or if you see anything that looks dumb please point it out to me. Is there a way to use stdout for xcopy other than using the process id? I am jumping around with it and reinstancing it.. Maybe use that entirely for my progress after format instead of what I'm doing now.. expandcollapse popup#NoTrayIcon #RequireAdmin #include <AutoItConstants.au3> #include <GUIConstantsEx.au3> #include <MsgBoxConstants.au3> #include <Constants.au3> #include <File.au3> #include <Array.au3> #include <String.au3> Global $DiskList, $Selection, $Burn, $Refresh, $MountedDrive = "" Global $IsoFile, $CachePath, $finalfiles, $finaldirs, $wimSize, $bootDrive, $dataDrive GetCachePath() ProperUse() MountIso() GetISODriveLetter() CheckWIM() Cleanup() DirCreate($CachePath) $listFile = FileOpen($CachePath & 'list.ini', 2) FileWrite($listFile, 'lis dis') FileClose($listFile) Opt("GUIOnEventMode", 1) MainMenu() Cleanup() Exit Func MainMenu() GUICreate('USBTool (PE) v2.0', 300, 298) GUISetOnEvent($GUI_EVENT_CLOSE, "SpecialEvents") GUISetOnEvent($GUI_EVENT_MINIMIZE, "SpecialEvents") GUISetOnEvent($GUI_EVENT_RESTORE, "SpecialEvents") GUISetIcon(@WorkingDir & '\USBTool.ico', 1) GUISetBkColor(0x797979) GUICtrlCreateLabel('1: Select a disk use...', 20, 10, 280) $DiskList = GUICtrlCreateList('', 20, 30, 260, 150) GUICtrlSetData(-1, DiskList()) $Refresh = GUICtrlCreateButton('Refresh List', 110, 185, 80, 25) GUICtrlSetOnEvent(-1, "_RefreshPressed") GUICtrlSetState(-1, $GUI_FOCUS) GUICtrlCreateLabel('________________________________________', 30, 210, 280, 30) $Burn = GUICtrlCreateButton('Burn', 90, 232, 120, 40) GUICtrlSetOnEvent(-1, "BurnPressed") GUICtrlCreateLabel('( * ) Disk is Currently GPT', 160, 278, 130, 30) GUISetState() ; Just idle around While 1 Sleep(10) WEnd EndFunc ;==>MainMenu Func RefreshPressed() GUICtrlSetData($DiskList, "") GUICtrlSetData($DiskList, DiskList()) EndFunc ;==>RefreshPressed Func BurnPressed() Local $Disk = StringRegExpReplace(GUICtrlRead($DiskList), '(?i)^.*(Disk [\d]+).*$', '$1') Local $DiskN = StringSplit($Disk, "") Local $AreYouSure If $Disk = "" Then MsgBox($MB_ICONERROR, "Notice: ", "No disk has been selected") Else $AreYouSure = MsgBox(262452, 'This will FORMAT Disk ' & $DiskN[6], 'ALL DATA WILL BE ERASED FROM DISK ' & $DiskN[6] & @CRLF & 'Are you sure you want to proceed?') Select Case $AreYouSure = 6 ;Yes GUISetState(@SW_HIDE) ProgressOn("Applying ISO...", "Creating Bootable Media... ", "0%") PrepFormat($DiskN[6]) ProgressSet(5 & "%", "Formatting Disk " & $DiskN[6]) Format() ProgressSet(25 & "%", "Analyzing ISO Structure ") CleanDirList() CleanFileList() ProgressSet(26 & "%", "Copying Boot Partition ") CopyBootFiles() ;Progress in function; start at 55% CopyDataFilesF() ;Progress in function; start at 65% CopyDataFilesD() ProgressSet(100, "Finished", "ISO Applied!!") Sleep(2750) ProgressOff() Cleanup() UnmountIso() MsgBox($MB_ICONINFORMATION, "", " Enjoy! ") Exit Case $AreYouSure = 7 ;No EndSelect EndIf EndFunc ;==>BurnPressed Func SpecialEvents() Select Case @GUI_CtrlId = $GUI_EVENT_CLOSE ; Code below for actions on Close Cleanup() UnmountIso() Exit Case @GUI_CtrlId = $GUI_EVENT_MINIMIZE ; Code below for actions on Minimize Case @GUI_CtrlId = $GUI_EVENT_RESTORE ; Code below for actions on Restore EndSelect EndFunc ;==>SpecialEvents Func ProperUse() If Not ($CmdLine[0]) = 0 Then ;Something was dropped on the EXE file or CLI was used with a flag(s) $IsoFile = ($CmdLine[1]) ;Sets $IsoFile var to the full path of whatever was dropped onto the EXE file or the 1st CLI flag that was used Else MsgBox($MB_ICONERROR, "Notice: ", "This program cannot be run directly!" & @CRLF & "Please drag an ISO onto" & @CRLF & "the program to begin...") Exit EndIf EndFunc ;==>ProperUse Func CheckWIM() Local $wimExists = FileExists($MountedDrive & ":\sources\boot.wim") If Not $wimExists Then MsgBox($MB_ICONERROR, "Notice: ", "BOOT.WIM NOT DETECTED!!!" & @CRLF & "This tool is designed for SE" & @CRLF & "and XPE projects only.") UnmountIso() Exit Else $wimSize = FileGetSize($MountedDrive & ":\sources\boot.wim") $wimSize = StringSplit(($wimSize + 200000000) / 1000000, ".") ; +200mb headroom on boot partition $wimSize = $wimSize[1] ;Get whole number after converting size from bytes to megabytes EndIf EndFunc ;==>CheckWIM Func MountIso() RunWait('cmd /c powershell.exe ' & '"Mount-DiskImage "' & '"' & $IsoFile & '"' & '"' & '"' & ' >nul', @WorkingDir, @SW_HIDE) EndFunc ;==>MountIso Func UnmountIso() RunWait('cmd /c powershell.exe ' & '"Dismount-DiskImage "' & '"' & $IsoFile & '"' & '"' & '"' & ' >nul', @WorkingDir, @SW_HIDE) EndFunc ;==>UnmountIso Func Cleanup() If FileExists($CachePath) Then DirRemove($CachePath, $DIR_REMOVE) EndIf EndFunc ;==>Cleanup Func GetISODriveLetter() Local $findiso = StringSplit("CDEFGHIJKLMNOPQRSTUVWXYZ", "", 1) For $i = 1 To $findiso[0] Step +1 $isoExists = FileExists($findiso[$i] & ":\CdUsb.Y") If $isoExists Then If PathIsWritable($findiso[$i] & ":\") = False Then $MountedDrive = ($findiso[$i]) EndIf EndIf Next If $MountedDrive = "" Then MsgBox($MB_ICONERROR, "Notice: ", "CdUsb.Y NOT DETECTED!!!" & @CRLF & "This tool is designed for SE" & @CRLF & "and XPE projects only.") Exit EndIf EndFunc ;==>GetISODriveLetter Func PathIsWritable($sFile) Local $aRet = DllCall('kernel32.dll', 'handle', 'CreateFileW', _ 'wstr', $sFile, _ 'dword', 2, _ 'dword', 7, _ 'struct*', 0, _ 'dword', 3, _ 'dword', 0x02000000, _ 'handle', 0) If @error Or $aRet[0] = Ptr(-1) Or $aRet[0] = 0 Then Return False DllCall('kernel32.dll', 'bool', 'CloseHandle', 'handle', $aRet[0]) Return True EndFunc ;==>PathIsWritable Func DiskList() RunWait('cmd /c diskpart /s ' & '"' & $CachePath & 'list.ini' & '"' & '>' & '"' & $CachePath & 'dpoutput.txt' & '"', @WorkingDir, @SW_HIDE) Local $Filtered = '', $Array = _StringExplode(FileRead($CachePath & 'dpoutput.txt'), @LF) For $rawlist = 0 To UBound($Array) - 1 If StringRegExp($Array[$rawlist], '(?i)Disk [\d]+') Then $Filtered &= $Array[$rawlist] & '|' Next $Filtered = StringRegExpReplace($Filtered, '[\s|]*$', '') Return $Filtered EndFunc ;==>DiskList Func GetCachePath() $CachePath = IniRead(@WorkingDir & '\USBTool.ini', "Settings", "CachePath", @WorkingDir & '\cache') $CachePath = ($CachePath & '\') EndFunc ;==>GetCachePath Func PrepFormat($Drive) GetDriveLetters() createDiskPartScriptFile($CachePath & 'clean.dat', 'Sel Dis ' & $Drive & @CRLF & 'clean' & @CRLF & 'Exit') createDiskPartScriptFile($CachePath & 'attrib.dat', 'Sel Dis ' & $Drive & @CRLF & 'attribute disk clear readonly' & @CRLF & 'Exit') createDiskPartScriptFile($CachePath & 'scrubber.dat', 'Sel Dis ' & $Drive & @CRLF & 'cre par pri' & @CRLF & 'format quick fs=NTFS label=scrubber' & @CRLF & 'Exit') createDiskPartScriptFile($CachePath & 'convert.dat', 'Sel Dis ' & $Drive & @CRLF & 'convert mbr' & @CRLF & 'Exit') createDiskPartScriptFile($CachePath & 'initdata.dat', 'Sel Dis ' & $Drive & @CRLF & 'cre par pri' & @CRLF & 'shrink minimum=' & $wimSize & @CRLF & 'format quick fs=ntfs label="WinPE Data"' & @CRLF & 'assign letter=' & $dataDrive & @CRLF & 'Exit') createDiskPartScriptFile($CachePath & 'initboot.dat', 'Sel Dis ' & $Drive & @CRLF & 'cre par pri' & @CRLF & 'format quick fs=fat32 label="BOOTFILES"' & @CRLF & 'assign letter=' & $bootDrive & @CRLF & 'Active' & @CRLF & 'Exit') EndFunc ;==>PrepFormat Func CopyBootFiles() Local $bmgrExists = FileExists($MountedDrive & ":\BOOTMGR.") Local $bmgrefiExists = FileExists($MountedDrive & ":\bootmgr.efi") Local $bmgrexeExists = FileExists($MountedDrive & ":\bootmgr.exe") Local $menulstExists = FileExists($MountedDrive & ":\menu.lst") RunWait('cmd /c xcopy ' & $MountedDrive & ':\BOOT ' & $bootDrive & ':\BOOT /i /s /e /h /r /v /y', @WorkingDir, @SW_HIDE) ProgressSet(27 & "%", "Copying Boot Partition ") RunWait('cmd /c xcopy ' & $MountedDrive & ':\EFI ' & $bootDrive & ':\EFI /i /s /e /h /r /v /y', @WorkingDir, @SW_HIDE) ProgressSet(40 & "%", "Copying Boot.wim, this may take a while... ") RunWait('cmd /c xcopy ' & $MountedDrive & ':\sources ' & $bootDrive & ':\sources /i /s /e /h /r /v /y', @WorkingDir, @SW_HIDE) ProgressSet(50 & "%", "Copying Boot Files ") If $bmgrExists Then RunWait('cmd /c xcopy ' & $MountedDrive & ':\BOOTMGR. ' & $bootDrive & ':\ /h /r /v /y', @WorkingDir, @SW_HIDE) EndIf If $bmgrefiExists Then RunWait('cmd /c xcopy ' & $MountedDrive & ':\bootmgr.efi ' & $bootDrive & ':\ /h /r /v /y', @WorkingDir, @SW_HIDE) EndIf If $bmgrexeExists Then RunWait('cmd /c xcopy ' & $MountedDrive & ':\bootmgr.exe ' & $bootDrive & ':\ /h /r /v /y', @WorkingDir, @SW_HIDE) EndIf If $menulstExists Then ;Need to add grub support etc later if this gets expanded beyond PE SE or XPE ISO's RunWait('cmd /c xcopy ' & $MountedDrive & ':\menu.lst ' & $bootDrive & ':\ /h /r /v /y', @WorkingDir, @SW_HIDE) EndIf EndFunc ;==>CopyBootFiles Func CopyDataFilesF() Local $GoFiles = ($CachePath & $finalfiles), $StartProgAt FileOpen($GoFiles, 0) Local $aArray[1000] ReDim $aArray[_FileCountLines($GoFiles) + 1] For $i = 1 To _FileCountLines($GoFiles) $newline = FileReadLine($GoFiles, $i) $aArray[$i] = $newline Next _ArraySort($aArray) $StartProgAt = 55 For $i = 1 To UBound($aArray) - 1 ProgressSet($StartProgAt & "%", "Copying " & $aArray[$i] & " ") RunWait('cmd /c xcopy ' & $MountedDrive & ':\' & $aArray[$i] & ' ' & $dataDrive & ':\' & ' /h /r /v /y', @WorkingDir, @SW_HIDE) $StartProgAt = ($StartProgAt + 1) Next EndFunc ;==>CopyDataFilesF Func CopyDataFilesD() Local $GoFiles = ($CachePath & $finaldirs), $StartProgAt FileOpen($GoFiles, 0) Local $aArray[1000] ReDim $aArray[_FileCountLines($GoFiles) + 1] For $i = 1 To _FileCountLines($GoFiles) $newline = FileReadLine($GoFiles, $i) $aArray[$i] = $newline Next _ArraySort($aArray) $StartProgAt = 65 For $i = 1 To UBound($aArray) - 1 If $aArray[$i] = "Programs" Then ProgressSet($StartProgAt & "%", "Copying Programs, this may take a while... ") RunWait('cmd /c xcopy ' & $MountedDrive & ':\' & $aArray[$i] & ' ' & $dataDrive & ':\' & $aArray[$i] & ' /i /s /e /h /r /v /y', @WorkingDir, @SW_HIDE) $StartProgAt = ($StartProgAt + 15) Else ProgressSet($StartProgAt & "%", "Copying " & $aArray[$i] &" Folder ") RunWait('cmd /c xcopy ' & $MountedDrive & ':\' & $aArray[$i] & ' ' & $dataDrive & ':\' & $aArray[$i] & ' /i /s /e /h /r /v /y', @WorkingDir, @SW_HIDE) $StartProgAt = ($StartProgAt + 1) EndIf Next EndFunc ;==>CopyDataFilesD Func createDiskPartScriptFile($fileName, $message) $CacheFile = '' $CacheFile = FileOpen($fileName, 2) FileWrite($CacheFile, $message) FileClose($CacheFile) EndFunc ;==>createDiskPartScriptFile Func GetDriveLetters() Local $allDriveLetters = "CDEFGHIJKLMNOPQRSTUVWXYZ", $AvailDriveLetters Local $aArray = DriveGetDrive($DT_ALL) If @error Then ; An error occurred when retrieving the drives. MsgBox($MB_SYSTEMMODAL, "", "An Error Occurred! Unable to retrieve " & @CRLF & "available drive letters! Exiting Program...") Cleanup() UnmountIso() Exit Else For $i = 1 To $aArray[0] $driveLetter = StringLeft(StringUpper($aArray[$i]), 1) $allDriveLetters = StringReplace($allDriveLetters, $driveLetter, "") Next EndIf $AvailDriveLetters = StringSplit($allDriveLetters, "") $bootDrive = $AvailDriveLetters[1] ;Get first available letter $dataDrive = $AvailDriveLetters[2] ;Get second available letter EndFunc ;==>GetDriveLetters Func CleanDirList() Local $rawlist = 'isod.dat' $finaldirs = 'isodirs.dat' RunWait('cmd /c DIR /B /A:D ' & $MountedDrive & ':\>' & '"' & $CachePath & $rawlist & '"', @WorkingDir, @SW_HIDE) RunWait('cmd /c FINDSTR /v /i /c:' & '"' & 'efi' & '"' & ' /c:' & '"' & 'boot' & '"' & ' /c:' & '"' & 'sources' & '"' & ' "' & $CachePath & $rawlist & '"' & '>>' & '"' & $CachePath & $finaldirs & '"', @WorkingDir, @SW_HIDE) EndFunc ;==>CleanDirList Func CleanFileList() Local $rawlist = 'isof.dat' $finalfiles = 'isofiles.dat' RunWait('cmd /c DIR /B /A-D ' & $MountedDrive & ':\>' & '"' & $CachePath & $rawlist & '"', @WorkingDir, @SW_HIDE) RunWait('cmd /c FINDSTR /v /i /c:' & '"' & 'bootmgr' & '"' & ' /c:' & '"' & 'menu' & '"' & ' "' & $CachePath & $rawlist & '"' & '>>' & '"' & $CachePath & $finalfiles & '"', @WorkingDir, @SW_HIDE) EndFunc ;==>CleanFileList Func Format() Local $aArray[7][3] = [ _ ["Cleaning Drive", 'cmd /c diskpart /s ' & '"' & $CachePath & 'clean.dat' & '"'], _ ["Cleaning Drive", 'cmd /c diskpart /s ' & '"' & $CachePath & 'scrub.dat' & '"'], _ ["Cleaning Drive", 'cmd /c diskpart /s ' & '"' & $CachePath & 'clean.dat' & '"'], _ ["Resetting Disk Attributes", 'cmd /c diskpart /s ' & '"' & $CachePath & 'attrib.dat' & '"'], _ ["Converting Layout to MBR", 'cmd /c diskpart /s ' & '"' & $CachePath & 'convert.dat' & '"'], _ ["Creating Data Partition", 'cmd /c diskpart /s ' & '"' & $CachePath & 'initdata.dat' & '"'], _ ["Creating Boot Partition", 'cmd /c diskpart /s ' & '"' & $CachePath & 'initboot.dat' & '"'] _ ] For $i = 0 To UBound($aArray) - 1 ProgressSet($i * 2 & "%", $aArray[$i][0]) ;MsgBox($MB_ICONINFORMATION, "Troubleshooting.. ", $aArray[$i][1]) ;Troubleshoot Array Data RunWait($aArray[$i][1], @WorkingDir, @SW_HIDE) Sleep(750) Next EndFunc ;==>Format Edited December 18, 2021 by bobomb Link to comment Share on other sites More sharing options...
Luke94 Posted December 9, 2021 Share Posted December 9, 2021 You could call the functions in a loop and use the variable to calculate the percentage? expandcollapse popup#NoTrayIcon #RequireAdmin #include <AutoItConstants.au3> #include <GUIConstantsEx.au3> #include <MsgBoxConstants.au3> #include <Constants.au3> #include <File.au3> #include <Array.au3> #include <String.au3> Global $DiskList, $Selection, $Burn, $Refresh, $MountedDrive = "" Global $IsoFile, $CachePath, $finalfiles, $finaldirs, $wimSize, $bootDrive, $dataDrive GetCachePath() ProperUse() MountIso() GetISODriveLetter() CheckWIM() Cleanup() DirCreate($CachePath) $listFile = FileOpen($CachePath & 'list.ini', 2) FileWrite($listFile, 'lis dis') FileClose($listFile) Opt("GUIOnEventMode", 1) MainMenu() Cleanup() Exit Func MainMenu() GUICreate('USBTool (PE) v2.0', 300, 298) GUISetOnEvent($GUI_EVENT_CLOSE, "SpecialEvents") GUISetOnEvent($GUI_EVENT_MINIMIZE, "SpecialEvents") GUISetOnEvent($GUI_EVENT_RESTORE, "SpecialEvents") GUISetIcon(@WorkingDir & '\USBTool.ico', 1) GUISetBkColor(0x797979) GUICtrlCreateLabel('1: Select a disk use...', 20, 10, 280) $DiskList = GUICtrlCreateList('', 20, 30, 260, 150) GUICtrlSetData(-1, DiskList()) $Refresh = GUICtrlCreateButton('Refresh List', 110, 185, 80, 25) GUICtrlSetOnEvent(-1, "_RefreshPressed") GUICtrlSetState(-1, $GUI_FOCUS) GUICtrlCreateLabel('________________________________________', 30, 210, 280, 30) $Burn = GUICtrlCreateButton('Burn', 90, 232, 120, 40) GUICtrlSetOnEvent(-1, "BurnPressed") GUICtrlCreateLabel('( * ) Disk is Currently GPT', 160, 278, 130, 30) GUISetState() ; Just idle around While 1 Sleep(10) WEnd EndFunc ;==>MainMenu Func RefreshPressed() GUICtrlSetData($DiskList, "") GUICtrlSetData($DiskList, DiskList()) EndFunc ;==>RefreshPressed Func BurnPressed() Local $Disk = StringRegExpReplace(GUICtrlRead($DiskList), '(?i)^.*(Disk [\d]+).*$', '$1') Local $DiskN = StringSplit($Disk, "") Local $AreYouSure If $Disk = "" Then MsgBox($MB_ICONERROR, "Notice: ", "No disk has been selected") Else $AreYouSure = MsgBox(262452, 'This will FORMAT Disk ' & $DiskN[6], 'ALL DATA WILL BE ERASED FROM DISK ' & $DiskN[6] & @CRLF & 'Are you sure you want to proceed?') Select Case $AreYouSure = 6 ;Yes GUISetState(@SW_HIDE) ; $aFunctions - 0 = Function Name, 1 = Task Description, 2 = Param 1 Local $aFunctions[7][3] = [ [ 'PrepFormat', 'Preparing Format..', $DiskN[6] ], _ [ 'Format', 'Formatting..', -1 ], _ [ 'CleanDirList', 'Cleaning Dir List..', -1 ], _ [ 'CleanFileList', ' Cleaning File List..', -1 ], _ [ 'CopyBootFiles', 'Copying Boot Files..', -1 ], _ [ 'CopyDataFilesF', 'Copying Boot Files F..', -1 ], _ [ 'CopyDataFilesD', 'Copying Boot Files D..', -1 ] ] ProgressOn("Applying ISO...", "Creating Bootable Media... ", "0%") For $i = 0 To (UBound($aFunctions) - 1) Step 1 If $aFunctions[$i][2] <> -1 Then Call($aFunctions[$i][0], $aFunctions[$i][2]) Else Call($aFunctions[$i][0]) EndIf Local $iPercentage = Int(((100 / UBound($aFunctions)) * ($i + 1))) ProgressSet($iPercentage, $aFunctions[$i][1], $iPercentage & '%') Sleep(1000) ; You might want to remove this sleep - I added it for visibility Next ProgressOff() Cleanup() UnmountIso() MsgBox($MB_ICONINFORMATION, "", " Enjoy! ") Exit Case $AreYouSure = 7 ;No EndSelect EndIf EndFunc ;==>BurnPressed Func SpecialEvents() Select Case @GUI_CtrlId = $GUI_EVENT_CLOSE ; Code below for actions on Close Cleanup() UnmountIso() Exit Case @GUI_CtrlId = $GUI_EVENT_MINIMIZE ; Code below for actions on Minimize Case @GUI_CtrlId = $GUI_EVENT_RESTORE ; Code below for actions on Restore EndSelect EndFunc ;==>SpecialEvents Func ProperUse() If Not ($CmdLine[0]) = 0 Then ;Something was dropped on the EXE file or CLI was used with a flag(s) $IsoFile = ($CmdLine[1]) ;Sets $IsoFile var to the full path of whatever was dropped onto the EXE file or the 1st CLI flag that was used Else MsgBox($MB_ICONERROR, "Notice: ", "This program cannot be run directly!" & @CRLF & "Please drag an ISO onto" & @CRLF & "the program to begin...") Exit EndIf EndFunc ;==>ProperUse Func CheckWIM() Local $wimExists = FileExists($MountedDrive & ":\sources\boot.wim") If Not $wimExists Then MsgBox($MB_ICONERROR, "Notice: ", "BOOT.WIM NOT DETECTED!!!" & @CRLF & "This tool is designed for SE" & @CRLF & "and XPE projects only.") UnmountIso() Exit Else $wimSize = FileGetSize($MountedDrive & ":\sources\boot.wim") $wimSize = StringSplit(($wimSize + 200000000) / 1000000, ".") ; +200mb headroom on boot partition $wimSize = $wimSize[1] ;Get whole number after converting size from bytes to megabytes EndIf EndFunc ;==>CheckWIM Func MountIso() RunWait('cmd /c powershell.exe ' & '"Mount-DiskImage "' & '"' & $IsoFile & '"' & '"' & '"' & ' >nul', @WorkingDir, @SW_HIDE) EndFunc ;==>MountIso Func UnmountIso() RunWait('cmd /c powershell.exe ' & '"Dismount-DiskImage "' & '"' & $IsoFile & '"' & '"' & '"' & ' >nul', @WorkingDir, @SW_HIDE) EndFunc ;==>UnmountIso Func Cleanup() If FileExists($CachePath) Then DirRemove($CachePath, $DIR_REMOVE) EndIf EndFunc ;==>Cleanup Func GetISODriveLetter() Local $findiso = StringSplit("CDEFGHIJKLMNOPQRSTUVWXYZ", "", 1) For $i = 1 To $findiso[0] Step +1 $isoExists = FileExists($findiso[$i] & ":\CdUsb.Y") If $isoExists Then If PathIsWritable($findiso[$i] & ":\") = False Then $MountedDrive = ($findiso[$i]) EndIf EndIf Next If $MountedDrive = "" Then MsgBox($MB_ICONERROR, "Notice: ", "CdUsb.Y NOT DETECTED!!!" & @CRLF & "This tool is designed for SE" & @CRLF & "and XPE projects only.") Exit EndIf EndFunc ;==>GetISODriveLetter Func PathIsWritable($sFile) Local $aRet = DllCall('kernel32.dll', 'handle', 'CreateFileW', _ 'wstr', $sFile, _ 'dword', 2, _ 'dword', 7, _ 'struct*', 0, _ 'dword', 3, _ 'dword', 0x02000000, _ 'handle', 0) If @error Or $aRet[0] = Ptr(-1) Or $aRet[0] = 0 Then Return False DllCall('kernel32.dll', 'bool', 'CloseHandle', 'handle', $aRet[0]) Return True EndFunc ;==>PathIsWritable Func DiskList() RunWait('cmd /c diskpart /s ' & '"' & $CachePath & 'list.ini' & '"' & '>' & '"' & $CachePath & 'dpoutput.txt' & '"', @WorkingDir, @SW_HIDE) Local $Filtered = '', $Array = _StringExplode(FileRead($CachePath & 'dpoutput.txt'), @LF) For $rawlist = 0 To UBound($Array) - 1 If StringRegExp($Array[$rawlist], '(?i)Disk [\d]+') Then $Filtered &= $Array[$rawlist] & '|' Next $Filtered = StringRegExpReplace($Filtered, '[\s|]*$', '') Return $Filtered EndFunc ;==>DiskList Func GetCachePath() $CachePath = IniRead(@WorkingDir & '\USBTool.ini', "Settings", "CachePath", @WorkingDir & '\cache') $CachePath = ($CachePath & '\') EndFunc ;==>GetCachePath Func PrepFormat($Drive) GetDriveLetters() createDiskPartScriptFile($CachePath & 'clean.dat', 'Sel Dis ' & $Drive & @CRLF & 'clean' & @CRLF & 'Exit') createDiskPartScriptFile($CachePath & 'attrib.dat', 'Sel Dis ' & $Drive & @CRLF & 'attribute disk clear readonly' & @CRLF & 'Exit') createDiskPartScriptFile($CachePath & 'scrubber.dat', 'Sel Dis ' & $Drive & @CRLF & 'cre par pri' & @CRLF & 'format quick fs=NTFS label=scrubber' & @CRLF & 'Exit') createDiskPartScriptFile($CachePath & 'convert.dat', 'Sel Dis ' & $Drive & @CRLF & 'convert mbr' & @CRLF & 'Exit') createDiskPartScriptFile($CachePath & 'initdata.dat', 'Sel Dis ' & $Drive & @CRLF & 'cre par pri' & @CRLF & 'shrink minimum=' & $wimSize & @CRLF & 'format quick fs=ntfs label="WinPE Data"' & @CRLF & 'assign letter=' & $dataDrive & @CRLF & 'Exit') createDiskPartScriptFile($CachePath & 'initboot.dat', 'Sel Dis ' & $Drive & @CRLF & 'cre par pri' & @CRLF & 'format quick fs=fat32 label="BOOTFILES"' & @CRLF & 'assign letter=' & $bootDrive & @CRLF & 'Active' & @CRLF & 'Exit') EndFunc ;==>PrepFormat Func CopyBootFiles() Local $bmgrExists = FileExists($MountedDrive & ":\BOOTMGR.") Local $bmgrefiExists = FileExists($MountedDrive & ":\bootmgr.efi") Local $bmgrexeExists = FileExists($MountedDrive & ":\bootmgr.exe") Local $menulstExists = FileExists($MountedDrive & ":\menu.lst") RunWait('cmd /c xcopy ' & $MountedDrive & ':\BOOT ' & $bootDrive & ':\BOOT /i /s /e /h /r /v /y', @WorkingDir, @SW_HIDE) ProgressSet(27 & "%", "Copying Boot Partition ") RunWait('cmd /c xcopy ' & $MountedDrive & ':\EFI ' & $bootDrive & ':\EFI /i /s /e /h /r /v /y', @WorkingDir, @SW_HIDE) ProgressSet(40 & "%", "Copying Boot.wim, this may take a while... ") RunWait('cmd /c xcopy ' & $MountedDrive & ':\sources ' & $bootDrive & ':\sources /i /s /e /h /r /v /y', @WorkingDir, @SW_HIDE) ProgressSet(50 & "%", "Copying Boot Files ") If $bmgrExists Then RunWait('cmd /c xcopy ' & $MountedDrive & ':\BOOTMGR. ' & $bootDrive & ':\ /h /r /v /y', @WorkingDir, @SW_HIDE) EndIf If $bmgrefiExists Then RunWait('cmd /c xcopy ' & $MountedDrive & ':\bootmgr.efi ' & $bootDrive & ':\ /h /r /v /y', @WorkingDir, @SW_HIDE) EndIf If $bmgrexeExists Then RunWait('cmd /c xcopy ' & $MountedDrive & ':\bootmgr.exe ' & $bootDrive & ':\ /h /r /v /y', @WorkingDir, @SW_HIDE) EndIf If $menulstExists Then ;Need to add grub support etc later if this gets expanded beyond PE SE or XPE ISO's RunWait('cmd /c xcopy ' & $MountedDrive & ':\menu.lst ' & $bootDrive & ':\ /h /r /v /y', @WorkingDir, @SW_HIDE) EndIf EndFunc ;==>CopyBootFiles Func CopyDataFilesF() Local $GoFiles = ($CachePath & $finalfiles), $StartProgAt FileOpen($GoFiles, 0) Local $aArray[1000] ReDim $aArray[_FileCountLines($GoFiles) + 1] For $i = 1 To _FileCountLines($GoFiles) $newline = FileReadLine($GoFiles, $i) $aArray[$i] = $newline Next _ArraySort($aArray) $StartProgAt = 55 For $i = 1 To UBound($aArray) - 1 ProgressSet($StartProgAt & "%", "Copying " & $aArray[$i] & " ") RunWait('cmd /c xcopy ' & $MountedDrive & ':\' & $aArray[$i] & ' ' & $dataDrive & ':\' & ' /h /r /v /y', @WorkingDir, @SW_HIDE) $StartProgAt = ($StartProgAt + 1) Next EndFunc ;==>CopyDataFilesF Func CopyDataFilesD() Local $GoFiles = ($CachePath & $finaldirs), $StartProgAt FileOpen($GoFiles, 0) Local $aArray[1000] ReDim $aArray[_FileCountLines($GoFiles) + 1] For $i = 1 To _FileCountLines($GoFiles) $newline = FileReadLine($GoFiles, $i) $aArray[$i] = $newline Next _ArraySort($aArray) $StartProgAt = 65 For $i = 1 To UBound($aArray) - 1 If $aArray[$i] = "Programs" Then ProgressSet($StartProgAt & "%", "Copying Programs, this may take a while... ") RunWait('cmd /c xcopy ' & $MountedDrive & ':\' & $aArray[$i] & ' ' & $dataDrive & ':\' & $aArray[$i] & ' /i /s /e /h /r /v /y', @WorkingDir, @SW_HIDE) $StartProgAt = ($StartProgAt + 15) Else ProgressSet($StartProgAt & "%", "Copying " & $aArray[$i] &" Folder ") RunWait('cmd /c xcopy ' & $MountedDrive & ':\' & $aArray[$i] & ' ' & $dataDrive & ':\' & $aArray[$i] & ' /i /s /e /h /r /v /y', @WorkingDir, @SW_HIDE) $StartProgAt = ($StartProgAt + 1) EndIf Next EndFunc ;==>CopyDataFilesD Func createDiskPartScriptFile($fileName, $message) $CacheFile = '' $CacheFile = FileOpen($fileName, 2) FileWrite($CacheFile, $message) FileClose($CacheFile) EndFunc ;==>createDiskPartScriptFile Func GetDriveLetters() Local $allDriveLetters = "CDEFGHIJKLMNOPQRSTUVWXYZ", $AvailDriveLetters Local $aArray = DriveGetDrive($DT_ALL) If @error Then ; An error occurred when retrieving the drives. MsgBox($MB_SYSTEMMODAL, "", "An Error Occurred! Unable to retrieve " & @CRLF & "available drive letters! Exiting Program...") Cleanup() UnmountIso() Exit Else For $i = 1 To $aArray[0] $driveLetter = StringLeft(StringUpper($aArray[$i]), 1) $allDriveLetters = StringReplace($allDriveLetters, $driveLetter, "") Next EndIf $AvailDriveLetters = StringSplit($allDriveLetters, "") $bootDrive = $AvailDriveLetters[1] ;Get first available letter $dataDrive = $AvailDriveLetters[2] ;Get second available letter EndFunc ;==>GetDriveLetters Func CleanDirList() Local $rawlist = 'isod.dat' $finaldirs = 'isodirs.dat' RunWait('cmd /c DIR /B /A:D ' & $MountedDrive & ':\>' & '"' & $CachePath & $rawlist & '"', @WorkingDir, @SW_HIDE) RunWait('cmd /c FINDSTR /v /i /c:' & '"' & 'efi' & '"' & ' /c:' & '"' & 'boot' & '"' & ' /c:' & '"' & 'sources' & '"' & ' "' & $CachePath & $rawlist & '"' & '>>' & '"' & $CachePath & $finaldirs & '"', @WorkingDir, @SW_HIDE) EndFunc ;==>CleanDirList Func CleanFileList() Local $rawlist = 'isof.dat' $finalfiles = 'isofiles.dat' RunWait('cmd /c DIR /B /A-D ' & $MountedDrive & ':\>' & '"' & $CachePath & $rawlist & '"', @WorkingDir, @SW_HIDE) RunWait('cmd /c FINDSTR /v /i /c:' & '"' & 'bootmgr' & '"' & ' /c:' & '"' & 'menu' & '"' & ' "' & $CachePath & $rawlist & '"' & '>>' & '"' & $CachePath & $finalfiles & '"', @WorkingDir, @SW_HIDE) EndFunc ;==>CleanFileList Func Format() Local $aArray[7][3] = [ _ ["Cleaning Drive", 'cmd /c diskpart /s ' & '"' & $CachePath & 'clean.dat' & '"'], _ ["Cleaning Drive", 'cmd /c diskpart /s ' & '"' & $CachePath & 'scrub.dat' & '"'], _ ["Cleaning Drive", 'cmd /c diskpart /s ' & '"' & $CachePath & 'clean.dat' & '"'], _ ["Resetting Disk Attributes", 'cmd /c diskpart /s ' & '"' & $CachePath & 'attrib.dat' & '"'], _ ["Converting Layout to MBR", 'cmd /c diskpart /s ' & '"' & $CachePath & 'convert.dat' & '"'], _ ["Creating Data Partition", 'cmd /c diskpart /s ' & '"' & $CachePath & 'initdata.dat' & '"'], _ ["Creating Boot Partition", 'cmd /c diskpart /s ' & '"' & $CachePath & 'initboot.dat' & '"'] _ ] For $i = 0 To UBound($aArray) - 1 ProgressSet($i * 2 & "%", $aArray[$i][0]) ;MsgBox($MB_ICONINFORMATION, "Troubleshooting.. ", $aArray[$i][1]) ;Troubleshoot Array Data RunWait($aArray[$i][1], @WorkingDir, @SW_HIDE) Sleep(750) Next EndFunc ;==>Format bobomb 1 Link to comment Share on other sites More sharing options...
benners Posted December 9, 2021 Share Posted December 9, 2021 You could create your own progress gui and have a total progress for the whole process and a current progress for each function. You can then also design it to have labels that identify which part of the process is currently running. A few suggestions after a quick glance :- You could lose the $Burn and $Refresh globals as they are for buttons which have an onevent and are only used once in the posted code. The $CachePath global can be dropped and the GetCachePath function altered to return the path. This can then be called directly. Func GetCachePath() Return IniRead(@WorkingDir & '\USBTool.ini', "Settings", "CachePath", @WorkingDir & '\cache') & '\' EndFunc ;==>GetCachePath In the CopyBootFiles function, the four local variables can go and replaced with the Fileexists call, i.e. If FileExists($MountedDrive & ":\BOOTMGR.") Then RunWait('cmd /c xcopy ' & $MountedDrive & ':\BOOTMGR. ' & $bootDrive & ':\ /h /r /v /y', @WorkingDir, @SW_HIDE) In the CopyDataFiles functions, you could try FileReadToArray to create the array instead of creating one then redimming to fit the line count and looping to read the line. bobomb 1 Link to comment Share on other sites More sharing options...
bobomb Posted December 10, 2021 Author Share Posted December 10, 2021 (edited) TL;DR Stuck on STDOUTRead, it appears there are issues with it working for xCopy with the /Y flag? The below bold highlighted functions contain loops with STDOUTRead commands I cannot display in the progress bar.. The copy process works.. I would like to use this for a more granular view of progress.. I added something I think should work but it's not... @Luke94 thank you for your advice and time. I will attempt to incorporate that beautiful looking array when I get the STDOUT capture down for xcopy, so I can get all the sections to report progress back to it properly. It appears a /Y flag used to cause issues with AutoIT back in the day (circa 2005) but idk if thats still the case. Maybe I'm doing something wrong. I have in the CopyDataFilesF() and CopyDataFilesD() funtions added SDTOUTREAD commands, they will copy the files but I am trying to display the filenames/paths xcopy outputs into the progress bar label as the loop runs.. Any ideas? The copy process completes fine I just can't get any output from the $line var in those functions for the progress bar. Getting it to work in there will be nice but it will also open the door for me to pin down how stdout works and make use of it in other functions and probably be able to get rid of some of my dir cmds and txt files im creating and use more arrays instead to hold the vars within the program itself. Seems like a very good path to take at this point. @benners I used the direct if fileexists and it looks a lot cleaner idk why i over clutter like that sometimes.. For cachepath im worried about hitting the ini file that many times the var is used all over the script I might leave it in ram instead of on disk. but thank you very much. I will check FileReadToArray now. I post what I come up with here. Over the weekend (maybe before) I think I will return the dir size of all names in the dir list and compare that against the iso size to break down the percentage of each section.. expandcollapse popup#NoTrayIcon #RequireAdmin #include <AutoItConstants.au3> #include <GUIConstantsEx.au3> #include <MsgBoxConstants.au3> #include <Constants.au3> #include <File.au3> #include <Array.au3> #include <String.au3> Global $DiskList, $Selection, $IsoFile, $CachePath, $MountedDrive = "" Global $finalfiles, $finaldirs, $wimSize, $bootDrive, $dataDrive GetCachePath() ProperUse() MountIso() GetISODriveLetter() CheckWIM() Cleanup() DirCreate($CachePath) $listFile = FileOpen($CachePath & 'list.ini', 2) FileWrite($listFile, 'lis dis') FileClose($listFile) Opt("GUIOnEventMode", 1) MainMenu() Cleanup() Exit Func MainMenu() GUICreate('Burn Tool (XPE/SE) v2.0', 300, 298) GUISetOnEvent($GUI_EVENT_CLOSE, "SpecialEvents") GUISetOnEvent($GUI_EVENT_MINIMIZE, "SpecialEvents") GUISetOnEvent($GUI_EVENT_RESTORE, "SpecialEvents") GUISetIcon(@WorkingDir & '\USBTool.ico', 1) GUISetBkColor(0x797979) GUICtrlCreateLabel('1: Select a disk use...', 20, 10, 280) $DiskList = GUICtrlCreateList('', 20, 30, 260, 150) GUICtrlSetData(-1, DiskList()) $Refresh = GUICtrlCreateButton('Refresh List', 110, 185, 80, 25) GUICtrlSetOnEvent(-1, "RefreshPressed") GUICtrlSetState(-1, $GUI_FOCUS) GUICtrlCreateLabel('________________________________________', 30, 210, 280, 30) $Burn = GUICtrlCreateButton('Burn', 90, 232, 120, 40) GUICtrlSetOnEvent(-1, "BurnPressed") GUICtrlCreateLabel('( * ) Disk is Currently GPT', 160, 278, 130, 30) GUISetState() ; Just idle around While 1 Sleep(10) WEnd EndFunc ;==>MainMenu Func RefreshPressed() GUICtrlSetData($DiskList, "") GUICtrlSetData($DiskList, DiskList()) EndFunc ;==>RefreshPressed Func BurnPressed() Local $Disk = StringRegExpReplace(GUICtrlRead($DiskList), '(?i)^.*(Disk [\d]+).*$', '$1') Local $DiskN = StringSplit($Disk, "") Local $AreYouSure If $Disk = "" Then MsgBox($MB_ICONERROR, "Notice: ", "No disk has been selected") Else $AreYouSure = MsgBox(262452, 'This will FORMAT Disk ' & $DiskN[6], 'ALL DATA WILL BE ERASED FROM DISK ' & $DiskN[6] & @CRLF & 'Are you sure you want to proceed?') Select Case $AreYouSure = 6 ;Yes GUISetState(@SW_HIDE) ProgressOn("Applying ISO...", "Creating Bootable Media... ", "0%") PrepFormat($DiskN[6]) ProgressSet(5 & "%", "Formatting Disk " & $DiskN[6]) Format() ProgressSet(25 & "%", "Analyzing ISO Structure ") CleanDirList() CleanFileList() ProgressSet(26 & "%", "Copying Boot Partition ") CopyBootFiles() ;Progress in function; start at 55% CopyDataFilesF() ;Progress in function; start at 65% CopyDataFilesD() ProgressSet(100, "Finished", "ISO Applied!!") Sleep(2750) ProgressOff() Cleanup() UnmountIso() MsgBox($MB_ICONINFORMATION, "Bootable Media Ready", " Enjoy! ") Exit Case $AreYouSure = 7 ;No EndSelect EndIf EndFunc ;==>BurnPressed Func SpecialEvents() Select Case @GUI_CtrlId = $GUI_EVENT_CLOSE ; Code below for actions on Close Cleanup() UnmountIso() Exit Case @GUI_CtrlId = $GUI_EVENT_MINIMIZE ; Code below for actions on Minimize Case @GUI_CtrlId = $GUI_EVENT_RESTORE ; Code below for actions on Restore EndSelect EndFunc ;==>SpecialEvents Func ProperUse() If Not ($CmdLine[0]) = 0 Then ;Something was dropped on the EXE file or CLI was used with a flag(s) $IsoFile = ($CmdLine[1]) ;Sets $IsoFile var to the full path of whatever was dropped onto the EXE file or the 1st CLI flag that was used Else MsgBox($MB_ICONERROR, "Notice: ", "This program cannot be run directly!" & @CRLF & "Please drag an ISO onto" & @CRLF & "the program to begin...") Exit EndIf EndFunc ;==>ProperUse Func CheckWIM() Local $wimExists = FileExists($MountedDrive & ":\sources\boot.wim") If Not $wimExists Then MsgBox($MB_ICONERROR, "Notice: ", "BOOT.WIM NOT DETECTED!!!" & @CRLF & "This tool is designed for SE" & @CRLF & "and XPE projects only.") UnmountIso() Exit Else $wimSize = FileGetSize($MountedDrive & ":\sources\boot.wim") $wimSize = StringSplit(($wimSize + 200000000) / 1000000, ".") ; +200mb headroom on boot partition $wimSize = $wimSize[1] ;Get whole number after converting size from bytes to megabytes EndIf EndFunc ;==>CheckWIM Func MountIso() RunWait('cmd /c powershell.exe ' & '"Mount-DiskImage "' & '"' & $IsoFile & '"' & '"' & '"' & ' >nul', @WorkingDir, @SW_HIDE) EndFunc ;==>MountIso Func UnmountIso() RunWait('cmd /c powershell.exe ' & '"Dismount-DiskImage "' & '"' & $IsoFile & '"' & '"' & '"' & ' >nul', @WorkingDir, @SW_HIDE) EndFunc ;==>UnmountIso Func Cleanup() If FileExists($CachePath) Then DirRemove($CachePath, $DIR_REMOVE) EndIf EndFunc ;==>Cleanup Func GetISODriveLetter() Local $findiso = StringSplit("CDEFGHIJKLMNOPQRSTUVWXYZ", "", 1) For $i = 1 To $findiso[0] Step +1 $isoExists = FileExists($findiso[$i] & ":\CdUsb.Y") If $isoExists Then If PathIsWritable($findiso[$i] & ":\") = False Then $MountedDrive = ($findiso[$i]) EndIf EndIf Next If $MountedDrive = "" Then MsgBox($MB_ICONERROR, "Notice: ", "CdUsb.Y NOT DETECTED!!!" & @CRLF & "This tool is designed for SE" & @CRLF & "and XPE projects only.") Exit EndIf EndFunc ;==>GetISODriveLetter Func PathIsWritable($sFile) Local $aRet = DllCall('kernel32.dll', 'handle', 'CreateFileW', _ 'wstr', $sFile, _ 'dword', 2, _ 'dword', 7, _ 'struct*', 0, _ 'dword', 3, _ 'dword', 0x02000000, _ 'handle', 0) If @error Or $aRet[0] = Ptr(-1) Or $aRet[0] = 0 Then Return False DllCall('kernel32.dll', 'bool', 'CloseHandle', 'handle', $aRet[0]) Return True EndFunc ;==>PathIsWritable Func DiskList() RunWait('cmd /c diskpart /s ' & '"' & $CachePath & 'list.ini' & '"' & '>' & '"' & $CachePath & 'dpoutput.txt' & '"', @WorkingDir, @SW_HIDE) Local $Filtered = '', $Array = _StringExplode(FileRead($CachePath & 'dpoutput.txt'), @LF) For $rawlist = 0 To UBound($Array) - 1 If StringRegExp($Array[$rawlist], '(?i)Disk [\d]+') Then $Filtered &= $Array[$rawlist] & '|' Next $Filtered = StringRegExpReplace($Filtered, '[\s|]*$', '') Return $Filtered EndFunc ;==>DiskList Func GetCachePath() $CachePath = IniRead(@WorkingDir & '\USBTool.ini', "Settings", "CachePath", @WorkingDir & '\cache') $CachePath = ($CachePath & '\') EndFunc ;==>GetCachePath Func PrepFormat($Drive) GetDriveLetters() createDiskPartScriptFile($CachePath & 'clean.dat', 'Sel Dis ' & $Drive & @CRLF & 'clean' & @CRLF & 'Exit') createDiskPartScriptFile($CachePath & 'attrib.dat', 'Sel Dis ' & $Drive & @CRLF & 'attribute disk clear readonly' & @CRLF & 'Exit') createDiskPartScriptFile($CachePath & 'scrubber.dat', 'Sel Dis ' & $Drive & @CRLF & 'cre par pri' & @CRLF & 'format quick fs=NTFS label=scrubber' & @CRLF & 'Exit') createDiskPartScriptFile($CachePath & 'convert.dat', 'Sel Dis ' & $Drive & @CRLF & 'convert mbr' & @CRLF & 'Exit') createDiskPartScriptFile($CachePath & 'initdata.dat', 'Sel Dis ' & $Drive & @CRLF & 'cre par pri' & @CRLF & 'shrink minimum=' & $wimSize & @CRLF & 'format quick fs=ntfs label="WinPE Data"' & @CRLF & 'assign letter=' & $dataDrive & @CRLF & 'Exit') createDiskPartScriptFile($CachePath & 'initboot.dat', 'Sel Dis ' & $Drive & @CRLF & 'cre par pri' & @CRLF & 'format quick fs=fat32 label="BOOTFILES"' & @CRLF & 'assign letter=' & $bootDrive & @CRLF & 'Active' & @CRLF & 'Exit') EndFunc ;==>PrepFormat Func CopyBootFiles() RunWait('cmd /c xcopy ' & $MountedDrive & ':\BOOT ' & $bootDrive & ':\BOOT /i /s /e /h /r /v /y', @WorkingDir, @SW_HIDE) ProgressSet(27 & "%", "Copying Boot Partition ") RunWait('cmd /c xcopy ' & $MountedDrive & ':\EFI ' & $bootDrive & ':\EFI /i /s /e /h /r /v /y', @WorkingDir, @SW_HIDE) ProgressSet(40 & "%", "Copying Boot.wim, this may take a while... ") RunWait('cmd /c xcopy ' & $MountedDrive & ':\sources ' & $bootDrive & ':\sources /i /s /e /h /r /v /y', @WorkingDir, @SW_HIDE) ProgressSet(50 & "%", "Copying Boot Files ") If FileExists($MountedDrive & ":\BOOTMGR.") Then RunWait('cmd /c xcopy ' & $MountedDrive & ':\BOOTMGR. ' & $bootDrive & ':\ /h /r /v /y', @WorkingDir, @SW_HIDE) If FileExists($MountedDrive & ":\bootmgr.efi") Then RunWait('cmd /c xcopy ' & $MountedDrive & ':\bootmgr.efi ' & $bootDrive & ':\ /h /r /v /y', @WorkingDir, @SW_HIDE) If FileExists($MountedDrive & ":\bootmgr.exe") Then RunWait('cmd /c xcopy ' & $MountedDrive & ':\bootmgr.exe ' & $bootDrive & ':\ /h /r /v /y', @WorkingDir, @SW_HIDE) If FileExists($MountedDrive & ":\menu.lst") Then RunWait('cmd /c xcopy ' & $MountedDrive & ':\menu.lst ' & $bootDrive & ':\ /h /r /v /y', @WorkingDir, @SW_HIDE) EndFunc ;==>CopyBootFiles Func CopyDataFilesF() Local $GoFiles = ($CachePath & $finalfiles), $StartProgAt, $xcopycmd, $line = "" FileOpen($GoFiles, 0) Local $aArray[1000] ReDim $aArray[_FileCountLines($GoFiles) + 1] For $i = 1 To _FileCountLines($GoFiles) $newline = FileReadLine($GoFiles, $i) $aArray[$i] = $newline Next _ArraySort($aArray) $StartProgAt = 55 For $i = 1 To UBound($aArray) - 1 $line = StdoutRead($xcopycmd = RunWait('cmd /c echo | xcopy ' & $MountedDrive & ':\' & $aArray[$i] & ' ' & $dataDrive & ':\' & ' /h /r /v /y', @WorkingDir, @SW_HIDE, 2)) ProgressSet($StartProgAt & "%", "Copying " & $line) $StartProgAt = ($StartProgAt + 1) Next EndFunc ;==>CopyDataFilesF Func CopyDataFilesD() Local $GoFiles = ($CachePath & $finaldirs), $StartProgAt, $xcopycmd, $line = "" FileOpen($GoFiles, 0) Local $aArray[1000] ReDim $aArray[_FileCountLines($GoFiles) + 1] For $i = 1 To _FileCountLines($GoFiles) $newline = FileReadLine($GoFiles, $i) $aArray[$i] = $newline Next _ArraySort($aArray) $StartProgAt = 65 For $i = 1 To UBound($aArray) - 1 $line = StdoutRead($xcopycmd = RunWait('cmd /c echo | xcopy ' & $MountedDrive & ':\' & $aArray[$i] & ' ' & $dataDrive & ':\' & $aArray[$i] & ' /i /s /e /h /r /v /y', @WorkingDir, @SW_HIDE, 2)) If $aArray[$i] = "Programs" Then ProgressSet($StartProgAt & "%", "Copying " & $line) $StartProgAt = ($StartProgAt + 15) Else ProgressSet($StartProgAt & "%", "Copying " & $line) $StartProgAt = ($StartProgAt + 1) EndIf Next EndFunc ;==>CopyDataFilesD Func createDiskPartScriptFile($fileName, $message) $CacheFile = '' $CacheFile = FileOpen($fileName, 2) FileWrite($CacheFile, $message) FileClose($CacheFile) EndFunc ;==>createDiskPartScriptFile Func GetDriveLetters() Local $allDriveLetters = "CDEFGHIJKLMNOPQRSTUVWXYZ", $AvailDriveLetters Local $aArray = DriveGetDrive($DT_ALL) If @error Then ; An error occurred when retrieving the drives. MsgBox($MB_SYSTEMMODAL, "", "An Error Occurred! Unable to retrieve " & @CRLF & "available drive letters! Exiting Program...") Cleanup() UnmountIso() Exit Else For $i = 1 To $aArray[0] $driveLetter = StringLeft(StringUpper($aArray[$i]), 1) $allDriveLetters = StringReplace($allDriveLetters, $driveLetter, "") Next EndIf $AvailDriveLetters = StringSplit($allDriveLetters, "") $bootDrive = $AvailDriveLetters[1] ;Get first available letter $dataDrive = $AvailDriveLetters[2] ;Get second available letter EndFunc ;==>GetDriveLetters Func CleanDirList() Local $rawlist = 'isod.dat' $finaldirs = 'isodirs.dat' RunWait('cmd /c DIR /B /A:D ' & $MountedDrive & ':\>' & '"' & $CachePath & $rawlist & '"', @WorkingDir, @SW_HIDE) RunWait('cmd /c FINDSTR /v /i /c:' & '"' & 'efi' & '"' & ' /c:' & '"' & 'boot' & '"' & ' /c:' & '"' & 'sources' & '"' & ' "' & $CachePath & $rawlist & '"' & '>>' & '"' & $CachePath & $finaldirs & '"', @WorkingDir, @SW_HIDE) EndFunc ;==>CleanDirList Func CleanFileList() Local $rawlist = 'isof.dat' $finalfiles = 'isofiles.dat' RunWait('cmd /c DIR /B /A-D ' & $MountedDrive & ':\>' & '"' & $CachePath & $rawlist & '"', @WorkingDir, @SW_HIDE) RunWait('cmd /c FINDSTR /v /i /c:' & '"' & 'bootmgr' & '"' & ' /c:' & '"' & 'menu' & '"' & ' "' & $CachePath & $rawlist & '"' & '>>' & '"' & $CachePath & $finalfiles & '"', @WorkingDir, @SW_HIDE) EndFunc ;==>CleanFileList Func Format() Local $aArray[7][3] = [ _ ["Cleaning Drive", 'cmd /c diskpart /s ' & '"' & $CachePath & 'clean.dat' & '"'], _ ["Cleaning Drive", 'cmd /c diskpart /s ' & '"' & $CachePath & 'scrub.dat' & '"'], _ ["Cleaning Drive", 'cmd /c diskpart /s ' & '"' & $CachePath & 'clean.dat' & '"'], _ ["Resetting Disk Attributes", 'cmd /c diskpart /s ' & '"' & $CachePath & 'attrib.dat' & '"'], _ ["Converting Layout to MBR", 'cmd /c diskpart /s ' & '"' & $CachePath & 'convert.dat' & '"'], _ ["Creating Data Partition", 'cmd /c diskpart /s ' & '"' & $CachePath & 'initdata.dat' & '"'], _ ["Creating Boot Partition", 'cmd /c diskpart /s ' & '"' & $CachePath & 'initboot.dat' & '"'] _ ] For $i = 0 To UBound($aArray) - 1 ProgressSet($i * 2 & "%", $aArray[$i][0]) ;MsgBox($MB_ICONINFORMATION, "Troubleshooting.. ", $aArray[$i][1]) ;Troubleshoot Array Data RunWait($aArray[$i][1], @WorkingDir, @SW_HIDE) Sleep(750) Next EndFunc ;==>Format Edited December 10, 2021 by bobomb Link to comment Share on other sites More sharing options...
benners Posted December 10, 2021 Share Posted December 10, 2021 Good point about the iniread. You could use a static local variable to hold the value. The ini will be read once when the variable is initialised, after that it is ignored and the value will just be returned. You can then remove the first call to the function in the script and start it from the DirCreate line. Func GetCachePath() Local Static $s_CachePath = IniRead(@WorkingDir & '\USBTool.ini', "Settings", "CachePath", @WorkingDir & '\cache') & '\' Return $s_CachePath EndFunc ;==>GetCachePath For me, using _FileReadToArray is easier. No need to ubound to get the total. An example below using the GetCachePath above Func DiskList() RunWait('cmd /c diskpart /s ' & '"' & GetCachePath() & 'list.ini' & '"' & '>' & '"' & GetCachePath() & 'dpoutput.txt' & '"', @WorkingDir, @SW_HIDE) Local $as_diskpart = 0 Local $s_Filtered = '' ; read the file to an array _FileReadToArray(GetCachePath() & 'dpoutput.txt', $as_diskpart) ; loop through the array For $i = 1 To $as_diskpart[0] If StringRegExp($as_diskpart[$i], '(?i)Disk [\d]+') Then $s_Filtered &= $as_diskpart[$i] & '|' Next ; return the filtered string Return StringRegExpReplace($s_Filtered, '[\s|]*$', '') EndFunc ;==>DiskList You could also split the CheckWIM function into two, one to test for the file and the other to get the size. Keeps the functions simple and have a single job. Also gets rid of another global ($wimSize) ; check for the boot wim file Func BootWim_Check() If Not FileExists($MountedDrive & ':\sources\boot.wim') Then MsgBox($MB_ICONERROR, "Notice: ", "BOOT.WIM NOT DETECTED!!!" & @CRLF & "This tool is designed for SE" & @CRLF & "and XPE projects only.") UnmountIso() Exit EndIf EndFunc ; get the boot wim size and add 200 megabytes for headroom on boot partition Func BootWim_GetSize() Return Round((FileGetSize($MountedDrive & ':\sources\boot.wim') + 209715200) / 1048576) EndFunc In the burn pressed function, when you split the disk string to an array and use $DiskN[6], this will only work if the number of drives is less than 10. I know, who has that many. but for completeness you could try below. This should get disk numbers with double digits expandcollapse popupFunc BurnPressed() If GUICtrlRead($DiskList) = '' Then MsgBox( _ $MB_ICONERROR, _ "Notice: ", _ "No disk has been selected") Else Local $s_DiskNumber = StringRegExp(GUICtrlRead($DiskList), '(?<=Disk\s)[0-9]+', $STR_REGEXPARRAYMATCH)[0] If @error Then MsgBox( _ $MB_ICONERROR, _ "Notice: ", _ "An error occured retrieving the disk number") Else If MsgBox( _ BitOR($MB_TOPMOST, $MB_ICONWARNING, $MB_YESNO, $MB_DEFBUTTON2), _ 'This will FORMAT Disk ' & $s_DiskNumber, _ 'ALL DATA WILL BE ERASED FROM DISK ' & $s_DiskNumber & @CRLF & 'Are you sure you want to proceed?') = $IDYES Then GUISetState(@SW_HIDE) ProgressOn("Applying ISO...", "Creating Bootable Media... ", "0%") PrepFormat($s_DiskNumber) ProgressSet(5 & "%", "Formatting Disk " & $s_DiskNumber) Format() ProgressSet(25 & "%", "Analyzing ISO Structure ") CleanDirList() CleanFileList() ProgressSet(26 & "%", "Copying Boot Partition ") CopyBootFiles() ;Progress in function; start at 55% CopyDataFilesF() ;Progress in function; start at 65% CopyDataFilesD() ProgressSet(100, "Finished", "ISO Applied!!") Sleep(2750) ProgressOff() Cleanup() UnmountIso() MsgBox($MB_ICONINFORMATION, "", " Enjoy! ") Exit EndIf EndIf EndIf EndFunc ;==>BurnPressed For the files issue. You could use FileListToArray or FileListToArrayRec to list the files and use AutoIt to copy them. This would give you the names and path to display and save on txt file creation. Yashied has create a file copy udf here that works great. On the subject of less file creation, if the contents of list.ini never change, you could create the file yourself and include it in the compiled exe. Use FIleInstall to copy it to the cache folder. You can then remove the code that creates it and lose another global variable. bobomb 1 Link to comment Share on other sites More sharing options...
Luke94 Posted December 10, 2021 Share Posted December 10, 2021 @bobomb, does this work? Func CopyDataFilesD() Local $GoFiles = ($CachePath & $finaldirs), $StartProgAt, $xcopycmd, $line = "" FileOpen($GoFiles, 0) Local $aArray[1000] ReDim $aArray[_FileCountLines($GoFiles) + 1] For $i = 1 To _FileCountLines($GoFiles) $newline = FileReadLine($GoFiles, $i) $aArray[$i] = $newline Next _ArraySort($aArray) $StartProgAt = 65 For $i = 1 To UBound($aArray) - 1 $xcopycmd = Run('cmd /c xcopy ' & $MountedDrive & ':\' & $aArray[$i] & ' ' & $dataDrive & ':\' & $aArray[$i] & ' /i /s /e /h /r /v /y', @WorkingDir, @SW_HIDE, 2) ProcessWaitClose($xcopycmd) $line = StdoutRead($xcopycmd) If $aArray[$i] = "Programs" Then ProgressSet($StartProgAt & "%", "Copying " & $line) $StartProgAt = ($StartProgAt + 15) Else ProgressSet($StartProgAt & "%", "Copying " & $line) $StartProgAt = ($StartProgAt + 1) EndIf Next EndFunc ;==>CopyDataFilesD You may want to write $line to the Console to see what's been returned by StdoutRead. bobomb 1 Link to comment Share on other sites More sharing options...
bobomb Posted December 11, 2021 Author Share Posted December 11, 2021 (edited) @Luke94 that does work, is there any way to pipe the output of a copied dir in realtime? This was originally a command script i put together a while back. When The directories are copied as directories xcopy still displayed each file copied on the output running down the screen. Im trying to get a similar effect if possible under the progress bar. Edited December 11, 2021 by bobomb Link to comment Share on other sites More sharing options...
Luke94 Posted December 11, 2021 Share Posted December 11, 2021 The command is executed and once completed the console is read. You could split $line with @CRLF and loop through the return array? bobomb 1 Link to comment Share on other sites More sharing options...
bobomb Posted December 11, 2021 Author Share Posted December 11, 2021 (edited) How would get I get last line on the split? $displayline = StringSplit($line, "@CRLF") $displayline[?] Edited December 11, 2021 by bobomb Link to comment Share on other sites More sharing options...
Luke94 Posted December 11, 2021 Share Posted December 11, 2021 Local $aLines = StringSplit($line, @CRLF) Local $sLastLine = $aLines[(UBound($aLines) - 1)] bobomb 1 Link to comment Share on other sites More sharing options...
bobomb Posted December 11, 2021 Author Share Posted December 11, 2021 (edited) not working, nested in the loop or at the top of the function, i have this right now expandcollapse popup#NoTrayIcon #RequireAdmin #include <AutoItConstants.au3> #include <GUIConstantsEx.au3> #include <MsgBoxConstants.au3> #include <Constants.au3> #include <File.au3> #include <Array.au3> #include <String.au3> Global $DiskList, $Selection, $IsoFile, $MountedDrive = "" Global $finalfiles, $finaldirs, $wimSize, $bootDrive, $dataDrive GetCachePath() ProperUse() MountIso() GetISODriveLetter() BootWim_Check() Cleanup() DirCreate(GetCachePath()) $listFile = FileOpen(GetCachePath() & 'list.ini', 2) FileWrite($listFile, 'lis dis') FileClose($listFile) Opt("GUIOnEventMode", 1) MainMenu() Cleanup() Exit Func MainMenu() GUICreate('Burn Tool (XPE/SE) v2.0', 300, 298) GUISetOnEvent($GUI_EVENT_CLOSE, "SpecialEvents") GUISetOnEvent($GUI_EVENT_MINIMIZE, "SpecialEvents") GUISetOnEvent($GUI_EVENT_RESTORE, "SpecialEvents") GUISetIcon(@WorkingDir & '\USBTool.ico', 1) GUISetBkColor(0x797979) GUICtrlCreateLabel('1: Select a disk use...', 20, 10, 280) $DiskList = GUICtrlCreateList('', 20, 30, 260, 150) GUICtrlSetData(-1, DiskList()) $Refresh = GUICtrlCreateButton('Refresh List', 110, 185, 80, 25) GUICtrlSetOnEvent(-1, "RefreshPressed") GUICtrlSetState(-1, $GUI_FOCUS) GUICtrlCreateLabel('________________________________________', 30, 210, 280, 30) $Burn = GUICtrlCreateButton('Burn', 90, 232, 120, 40) GUICtrlSetOnEvent(-1, "BurnPressed") GUICtrlCreateLabel('( * ) Disk is Currently GPT', 160, 278, 130, 30) GUISetState() ; Just idle around While 1 Sleep(10) WEnd EndFunc ;==>MainMenu Func RefreshPressed() GUICtrlSetData($DiskList, "") GUICtrlSetData($DiskList, DiskList()) EndFunc ;==>RefreshPressed Func BurnPressed() If GUICtrlRead($DiskList) = '' Then MsgBox( _ $MB_ICONERROR, _ "Notice: ", _ "No disk has been selected") Else Local $s_DiskNumber = StringRegExp(GUICtrlRead($DiskList), '(?<=Disk\s)[0-9]+', $STR_REGEXPARRAYMATCH)[0] If @error Then MsgBox( _ $MB_ICONERROR, _ "Notice: ", _ "An error occured retrieving the disk number") Else If MsgBox( _ BitOR($MB_TOPMOST, $MB_ICONWARNING, $MB_YESNO, $MB_DEFBUTTON2), _ 'This will FORMAT Disk ' & $s_DiskNumber, _ 'ALL DATA WILL BE ERASED FROM DISK ' & $s_DiskNumber & @CRLF & 'Are you sure you want to proceed?') = $IDYES Then GUISetState(@SW_HIDE) ProgressOn("Applying ISO...", "Creating Bootable Media... ", "0%") PrepFormat($s_DiskNumber) ProgressSet(5 & "%", "Formatting Disk " & $s_DiskNumber) Format() ProgressSet(25 & "%", "Analyzing ISO Structure ") CleanDirList() CleanFileList() ProgressSet(26 & "%", "Copying Boot Partition ") CopyBootFiles() ;Progress in function; start at 55% CopyDataFilesF() ;Progress in function; start at 65% CopyDataFilesD() ProgressSet(100, "Finished", "ISO Applied!!") Sleep(2750) ProgressOff() Cleanup() UnmountIso() MsgBox($MB_ICONINFORMATION, "", " Enjoy! ") Exit EndIf EndIf EndIf EndFunc ;==>BurnPressed Func SpecialEvents() Select Case @GUI_CtrlId = $GUI_EVENT_CLOSE ; Code below for actions on Close Cleanup() UnmountIso() Exit Case @GUI_CtrlId = $GUI_EVENT_MINIMIZE ; Code below for actions on Minimize Case @GUI_CtrlId = $GUI_EVENT_RESTORE ; Code below for actions on Restore EndSelect EndFunc ;==>SpecialEvents Func ProperUse() If Not ($CmdLine[0]) = 0 Then ;Something was dropped on the EXE file or CLI was used with a flag(s) $IsoFile = ($CmdLine[1]) ;Sets $IsoFile var to the full path of whatever was dropped onto the EXE file or the 1st CLI flag that was used Else MsgBox($MB_ICONERROR, "Notice: ", "This program cannot be run directly!" & @CRLF & "Please drag an ISO onto" & @CRLF & "the program to begin...") Exit EndIf EndFunc ;==>ProperUse Func BootWim_Check() ; check for the boot wim file If Not FileExists($MountedDrive & ':\sources\boot.wim') Then MsgBox($MB_ICONERROR, "Notice: ", "BOOT.WIM NOT DETECTED!!!" & @CRLF & "This tool is designed for SE" & @CRLF & "and XPE projects only.") UnmountIso() Exit EndIf EndFunc Func BootWim_GetSize() ; get the boot wim size and add 200 megabytes for headroom on boot partition Return Round((FileGetSize($MountedDrive & ':\sources\boot.wim') + 209715200) / 1048576) EndFunc Func MountIso() RunWait('cmd /c powershell.exe ' & '"Mount-DiskImage "' & '"' & $IsoFile & '"' & '"' & '"' & ' >nul', @WorkingDir, @SW_HIDE) EndFunc ;==>MountIso Func UnmountIso() RunWait('cmd /c powershell.exe ' & '"Dismount-DiskImage "' & '"' & $IsoFile & '"' & '"' & '"' & ' >nul', @WorkingDir, @SW_HIDE) EndFunc ;==>UnmountIso Func Cleanup() If FileExists(GetCachePath()) Then DirRemove(GetCachePath(), $DIR_REMOVE) EndIf EndFunc ;==>Cleanup Func GetISODriveLetter() Local $findiso = StringSplit("CDEFGHIJKLMNOPQRSTUVWXYZ", "", 1) For $i = 1 To $findiso[0] Step +1 $isoExists = FileExists($findiso[$i] & ":\CdUsb.Y") If $isoExists Then If PathIsWritable($findiso[$i] & ":\") = False Then $MountedDrive = ($findiso[$i]) EndIf EndIf Next If $MountedDrive = "" Then MsgBox($MB_ICONERROR, "Notice: ", "CdUsb.Y NOT DETECTED!!!" & @CRLF & "This tool is designed for SE" & @CRLF & "and XPE projects only.") Exit EndIf EndFunc ;==>GetISODriveLetter Func PathIsWritable($sFile) Local $aRet = DllCall('kernel32.dll', 'handle', 'CreateFileW', _ 'wstr', $sFile, _ 'dword', 2, _ 'dword', 7, _ 'struct*', 0, _ 'dword', 3, _ 'dword', 0x02000000, _ 'handle', 0) If @error Or $aRet[0] = Ptr(-1) Or $aRet[0] = 0 Then Return False DllCall('kernel32.dll', 'bool', 'CloseHandle', 'handle', $aRet[0]) Return True EndFunc ;==>PathIsWritable Func DiskList() RunWait('cmd /c diskpart /s ' & '"' & GetCachePath() & 'list.ini' & '"' & '>' & '"' & GetCachePath() & 'dpoutput.txt' & '"', @WorkingDir, @SW_HIDE) Local $as_diskpart = 0 Local $s_Filtered = '' ; read the file to an array _FileReadToArray(GetCachePath() & 'dpoutput.txt', $as_diskpart) ; loop through the array For $i = 1 To $as_diskpart[0] If StringRegExp($as_diskpart[$i], '(?i)Disk [\d]+') Then $s_Filtered &= $as_diskpart[$i] & '|' Next ; return the filtered string Return StringRegExpReplace($s_Filtered, '[\s|]*$', '') EndFunc ;==>DiskList Func GetCachePath() Local Static $s_CachePath = IniRead(@WorkingDir & '\USBTool.ini', "Settings", "CachePath", @WorkingDir & '\cache') & '\' Return $s_CachePath EndFunc ;==>GetCachePath Func PrepFormat($Drive) GetDriveLetters() createDiskPartScriptFile(GetCachePath() & 'clean.dat', 'Sel Dis ' & $Drive & @CRLF & 'clean' & @CRLF & 'Exit') createDiskPartScriptFile(GetCachePath() & 'attrib.dat', 'Sel Dis ' & $Drive & @CRLF & 'attribute disk clear readonly' & @CRLF & 'Exit') createDiskPartScriptFile(GetCachePath() & 'scrubber.dat', 'Sel Dis ' & $Drive & @CRLF & 'cre par pri' & @CRLF & 'format quick fs=NTFS label=scrubber' & @CRLF & 'Exit') createDiskPartScriptFile(GetCachePath() & 'convert.dat', 'Sel Dis ' & $Drive & @CRLF & 'convert mbr' & @CRLF & 'Exit') createDiskPartScriptFile(GetCachePath() & 'initdata.dat', 'Sel Dis ' & $Drive & @CRLF & 'cre par pri' & @CRLF & 'shrink minimum=' & BootWim_GetSize() & @CRLF & 'format quick fs=ntfs label="WinPE Data"' & @CRLF & 'assign letter=' & $dataDrive & @CRLF & 'Exit') createDiskPartScriptFile(GetCachePath() & 'initboot.dat', 'Sel Dis ' & $Drive & @CRLF & 'cre par pri' & @CRLF & 'format quick fs=fat32 label="BOOTFILES"' & @CRLF & 'assign letter=' & $bootDrive & @CRLF & 'Active' & @CRLF & 'Exit') EndFunc ;==>PrepFormat Func CopyBootFiles() RunWait('cmd /c xcopy ' & $MountedDrive & ':\BOOT ' & $bootDrive & ':\BOOT /i /s /e /h /r /v /y', @WorkingDir, @SW_HIDE) ProgressSet(27 & "%", "Copying Boot Partition ") RunWait('cmd /c xcopy ' & $MountedDrive & ':\EFI ' & $bootDrive & ':\EFI /i /s /e /h /r /v /y', @WorkingDir, @SW_HIDE) ProgressSet(40 & "%", "Copying Boot.wim, this may take a while... ") RunWait('cmd /c xcopy ' & $MountedDrive & ':\sources ' & $bootDrive & ':\sources /i /s /e /h /r /v /y', @WorkingDir, @SW_HIDE) ProgressSet(50 & "%", "Copying Boot Files ") If FileExists($MountedDrive & ":\BOOTMGR.") Then RunWait('cmd /c xcopy ' & $MountedDrive & ':\BOOTMGR. ' & $bootDrive & ':\ /h /r /v /y', @WorkingDir, @SW_HIDE) If FileExists($MountedDrive & ":\bootmgr.efi") Then RunWait('cmd /c xcopy ' & $MountedDrive & ':\bootmgr.efi ' & $bootDrive & ':\ /h /r /v /y', @WorkingDir, @SW_HIDE) If FileExists($MountedDrive & ":\bootmgr.exe") Then RunWait('cmd /c xcopy ' & $MountedDrive & ':\bootmgr.exe ' & $bootDrive & ':\ /h /r /v /y', @WorkingDir, @SW_HIDE) If FileExists($MountedDrive & ":\menu.lst") Then RunWait('cmd /c xcopy ' & $MountedDrive & ':\menu.lst ' & $bootDrive & ':\ /h /r /v /y', @WorkingDir, @SW_HIDE) EndFunc ;==>CopyBootFiles Func CopyDataFilesF() Local $GoFiles = (GetCachePath() & $finalfiles), $StartProgAt, $xcopycmd, $line = "" FileOpen($GoFiles, 0) Local $aArray[1000] ReDim $aArray[_FileCountLines($GoFiles) + 1] For $i = 1 To _FileCountLines($GoFiles) $newline = FileReadLine($GoFiles, $i) $aArray[$i] = $newline Next _ArraySort($aArray) $StartProgAt = 55 For $i = 1 To UBound($aArray) - 1 $xcopycmd = RunWait('cmd /c xcopy ' & $MountedDrive & ':\' & $aArray[$i] & ' ' & $dataDrive & ':\' & ' /h /r /v /y', @WorkingDir, @SW_HIDE, 2) ProcessWaitClose($xcopycmd) $line = StdoutRead($xcopycmd) $aLines = StringSplit($line, @CRLF) $sLastLine = $aLines[(UBound($aLines) - 1)] ProgressSet($StartProgAt & "%", "Copying " & $sLastLine) $StartProgAt = ($StartProgAt + 1) Next EndFunc ;==>CopyDataFilesF Func CopyDataFilesD() Local $GoFiles = (GetCachePath() & $finaldirs), $StartProgAt, $xcopycmd, $line = "" FileOpen($GoFiles, 0) Local $aArray[1000] ReDim $aArray[_FileCountLines($GoFiles) + 1] For $i = 1 To _FileCountLines($GoFiles) $newline = FileReadLine($GoFiles, $i) $aArray[$i] = $newline Next _ArraySort($aArray) $StartProgAt = 65 For $i = 1 To UBound($aArray) - 1 $xcopycmd = Run('cmd /c xcopy ' & $MountedDrive & ':\' & $aArray[$i] & ' ' & $dataDrive & ':\' & $aArray[$i] & ' /i /s /e /h /r /v /y', @WorkingDir, @SW_HIDE, 2) ProcessWaitClose($xcopycmd) $line = StdoutRead($xcopycmd) $aLines = StringSplit($line, @CRLF) $sLastLine = $aLines[(UBound($aLines) - 1)] If $aArray[$i] = "Programs" Then ProgressSet($StartProgAt & "%", "Copying " & $sLastLine) $StartProgAt = ($StartProgAt + 15) Else ProgressSet($StartProgAt & "%", "Copying " & $sLastLine) $StartProgAt = ($StartProgAt + 1) EndIf Next EndFunc ;==>CopyDataFilesD Func createDiskPartScriptFile($fileName, $message) $CacheFile = '' $CacheFile = FileOpen($fileName, 2) FileWrite($CacheFile, $message) FileClose($CacheFile) EndFunc ;==>createDiskPartScriptFile Func GetDriveLetters() Local $allDriveLetters = "CDEFGHIJKLMNOPQRSTUVWXYZ", $AvailDriveLetters Local $aArray = DriveGetDrive($DT_ALL) If @error Then ; An error occurred when retrieving the drives. MsgBox($MB_SYSTEMMODAL, "", "An Error Occurred! Unable to retrieve " & @CRLF & "available drive letters! Exiting Program...") Cleanup() UnmountIso() Exit Else For $i = 1 To $aArray[0] $driveLetter = StringLeft(StringUpper($aArray[$i]), 1) $allDriveLetters = StringReplace($allDriveLetters, $driveLetter, "") Next EndIf $AvailDriveLetters = StringSplit($allDriveLetters, "") $bootDrive = $AvailDriveLetters[1] ;Get first available letter $dataDrive = $AvailDriveLetters[2] ;Get second available letter EndFunc ;==>GetDriveLetters Func CleanDirList() Local $rawlist = 'isod.dat' $finaldirs = 'isodirs.dat' RunWait('cmd /c DIR /B /A:D ' & $MountedDrive & ':\>' & '"' & GetCachePath() & $rawlist & '"', @WorkingDir, @SW_HIDE) RunWait('cmd /c FINDSTR /v /i /c:' & '"' & 'efi' & '"' & ' /c:' & '"' & 'boot' & '"' & ' /c:' & '"' & 'sources' & '"' & ' "' & GetCachePath() & $rawlist & '"' & '>>' & '"' & GetCachePath() & $finaldirs & '"', @WorkingDir, @SW_HIDE) EndFunc ;==>CleanDirList Func CleanFileList() Local $rawlist = 'isof.dat' $finalfiles = 'isofiles.dat' RunWait('cmd /c DIR /B /A-D ' & $MountedDrive & ':\>' & '"' & GetCachePath() & $rawlist & '"', @WorkingDir, @SW_HIDE) RunWait('cmd /c FINDSTR /v /i /c:' & '"' & 'bootmgr' & '"' & ' /c:' & '"' & 'menu' & '"' & ' "' & GetCachePath() & $rawlist & '"' & '>>' & '"' & GetCachePath() & $finalfiles & '"', @WorkingDir, @SW_HIDE) EndFunc ;==>CleanFileList Func Format() Local $aArray[7][3] = [ _ ["Cleaning Drive", 'cmd /c diskpart /s ' & '"' & GetCachePath() & 'clean.dat' & '"'], _ ["Cleaning Drive", 'cmd /c diskpart /s ' & '"' & GetCachePath() & 'scrub.dat' & '"'], _ ["Cleaning Drive", 'cmd /c diskpart /s ' & '"' & GetCachePath() & 'clean.dat' & '"'], _ ["Resetting Disk Attributes", 'cmd /c diskpart /s ' & '"' & GetCachePath() & 'attrib.dat' & '"'], _ ["Converting Layout to MBR", 'cmd /c diskpart /s ' & '"' & GetCachePath() & 'convert.dat' & '"'], _ ["Creating Data Partition", 'cmd /c diskpart /s ' & '"' & GetCachePath() & 'initdata.dat' & '"'], _ ["Creating Boot Partition", 'cmd /c diskpart /s ' & '"' & GetCachePath() & 'initboot.dat' & '"'] _ ] For $i = 0 To UBound($aArray) - 1 ProgressSet($i * 2 & "%", $aArray[$i][0]) ;MsgBox($MB_ICONINFORMATION, "Troubleshooting.. ", $aArray[$i][1]) ;Troubleshoot Array Data RunWait($aArray[$i][1], @WorkingDir, @SW_HIDE) Sleep(750) Next EndFunc ;==>Format @benners has some awesome suggestions too all shown implemented and im looking into the UDF he suggested now 😜 EDITED** Edited December 11, 2021 by bobomb Link to comment Share on other sites More sharing options...
Luke94 Posted December 11, 2021 Share Posted December 11, 2021 Try: Local $aLines = StringSplit($line, @CRLF) Local $sLine = $aLines[(UBound($aLines) - 2)] The last line might be just a new line. Above will return the second to last line. Link to comment Share on other sites More sharing options...
bobomb Posted December 11, 2021 Author Share Posted December 11, 2021 (edited) I got rid of the STDout section i think I'm going to try @benners suggestion looking into AutoIT copy UDF etc... for now this is the updated code, the real goal is trying to get some way i can at least make an attempt to track an accurate progress bar.. if i cannot copy with xcopy and see lastline stdout then i probably cant get good progress tracking with xcopy ;( so hopefully autoit copy commands handle it expandcollapse popup#NoTrayIcon #RequireAdmin #include <AutoItConstants.au3> #include <GUIConstantsEx.au3> #include <MsgBoxConstants.au3> #include <Constants.au3> #include <File.au3> #include <Array.au3> #include <String.au3> Global $DiskList, $Selection, $IsoFile, $MountedDrive = "" Global $finalfiles, $finaldirs, $wimSize, $bootDrive, $dataDrive ProperUse() MountIso() GetISODriveLetter() BootWim_Check() Cleanup() DirCreate(GetCachePath()) $listFile = FileOpen(GetCachePath() & 'list.ini', 2) FileWrite($listFile, 'lis dis') FileClose($listFile) Opt("GUIOnEventMode", 1) MainMenu() Cleanup() Exit Func MainMenu() GUICreate('Burn Tool (XPE/SE) v2.0', 300, 298) GUISetOnEvent($GUI_EVENT_CLOSE, "SpecialEvents") GUISetOnEvent($GUI_EVENT_MINIMIZE, "SpecialEvents") GUISetOnEvent($GUI_EVENT_RESTORE, "SpecialEvents") GUISetIcon(@WorkingDir & '\USBTool.ico', 1) GUISetBkColor(0x797979) GUICtrlCreateLabel('1: Select a disk use...', 20, 10, 280) $DiskList = GUICtrlCreateList('', 20, 30, 260, 150) GUICtrlSetData(-1, DiskList()) $Refresh = GUICtrlCreateButton('Refresh List', 110, 185, 80, 25) GUICtrlSetOnEvent(-1, "RefreshPressed") GUICtrlSetState(-1, $GUI_FOCUS) GUICtrlCreateLabel('________________________________________', 30, 210, 280, 30) $Burn = GUICtrlCreateButton('Burn', 90, 232, 120, 40) GUICtrlSetOnEvent(-1, "BurnPressed") GUICtrlCreateLabel('( * ) Disk is Currently GPT', 160, 278, 130, 30) GUISetState() ; Just idle around While 1 Sleep(10) WEnd EndFunc ;==>MainMenu Func RefreshPressed() GUICtrlSetData($DiskList, "") GUICtrlSetData($DiskList, DiskList()) EndFunc ;==>RefreshPressed Func BurnPressed() If GUICtrlRead($DiskList) = '' Then MsgBox( _ $MB_ICONERROR, _ "Notice: ", _ "No disk has been selected") Else Local $s_DiskNumber = StringRegExp(GUICtrlRead($DiskList), '(?<=Disk\s)[0-9]+', $STR_REGEXPARRAYMATCH)[0] If @error Then MsgBox( _ $MB_ICONERROR, _ "Notice: ", _ "An error occured retrieving the disk number") Else If MsgBox( _ BitOR($MB_TOPMOST, $MB_ICONWARNING, $MB_YESNO, $MB_DEFBUTTON2), _ 'This will FORMAT Disk ' & $s_DiskNumber, _ 'ALL DATA WILL BE ERASED FROM DISK ' & $s_DiskNumber & @CRLF & 'Are you sure you want to proceed?') = $IDYES Then GUISetState(@SW_HIDE) ProgressOn("Applying ISO...", "Creating Bootable Media... ", "0%") PrepFormat($s_DiskNumber) ProgressSet(5 & "%", "Formatting Disk " & $s_DiskNumber) Format() ProgressSet(25 & "%", "Analyzing ISO Structure ") CleanDirList() CleanFileList() ProgressSet(26 & "%", "Copying Boot Partition ") CopyBootFiles() ;Progress in function; start at 55% CopyDataFilesF() ;Progress in function; start at 65% CopyDataFilesD() ProgressSet(100, "Finished", "ISO Applied!!") Sleep(2750) ProgressOff() Cleanup() UnmountIso() MsgBox($MB_ICONINFORMATION, "", " Enjoy! ") Exit EndIf EndIf EndIf EndFunc ;==>BurnPressed Func SpecialEvents() Select Case @GUI_CtrlId = $GUI_EVENT_CLOSE ; Code below for actions on Close Cleanup() UnmountIso() Exit Case @GUI_CtrlId = $GUI_EVENT_MINIMIZE ; Code below for actions on Minimize Case @GUI_CtrlId = $GUI_EVENT_RESTORE ; Code below for actions on Restore EndSelect EndFunc ;==>SpecialEvents Func ProperUse() If Not ($CmdLine[0]) = 0 Then ;Something was dropped on the EXE file or CLI was used with a flag(s) $IsoFile = ($CmdLine[1]) ;Sets $IsoFile var to the full path of whatever was dropped onto the EXE file or the 1st CLI flag that was used Else MsgBox($MB_ICONERROR, "Notice: ", "This program cannot be run directly!" & @CRLF & "Please drag an ISO onto" & @CRLF & "the program to begin...") Exit EndIf EndFunc ;==>ProperUse Func BootWim_Check() ; check for the boot wim file If Not FileExists($MountedDrive & ':\sources\boot.wim') Then MsgBox($MB_ICONERROR, "Notice: ", "BOOT.WIM NOT DETECTED!!!" & @CRLF & "This tool is designed for SE" & @CRLF & "and XPE projects only.") UnmountIso() Exit EndIf EndFunc ;==>BootWim_Check Func BootWim_GetSize() ; get the boot wim size and add 200 megabytes for headroom on boot partition Return Round((FileGetSize($MountedDrive & ':\sources\boot.wim') + 209715200) / 1048576) EndFunc ;==>BootWim_GetSize Func MountIso() RunWait('cmd /c powershell.exe ' & '"Mount-DiskImage "' & '"' & $IsoFile & '"' & '"' & '"' & ' >nul', @WorkingDir, @SW_HIDE) EndFunc ;==>MountIso Func UnmountIso() RunWait('cmd /c powershell.exe ' & '"Dismount-DiskImage "' & '"' & $IsoFile & '"' & '"' & '"' & ' >nul', @WorkingDir, @SW_HIDE) EndFunc ;==>UnmountIso Func Cleanup() If FileExists(GetCachePath()) Then DirRemove(GetCachePath(), $DIR_REMOVE) EndIf EndFunc ;==>Cleanup Func GetISODriveLetter() Local $findiso = StringSplit("CDEFGHIJKLMNOPQRSTUVWXYZ", "", 1) For $i = 1 To $findiso[0] Step +1 $isoExists = FileExists($findiso[$i] & ":\CdUsb.Y") If $isoExists Then If PathIsWritable($findiso[$i] & ":\") = False Then $MountedDrive = ($findiso[$i]) EndIf EndIf Next If $MountedDrive = "" Then MsgBox($MB_ICONERROR, "Notice: ", "CdUsb.Y NOT DETECTED!!!" & @CRLF & "This tool is designed for SE" & @CRLF & "and XPE projects only.") Exit EndIf EndFunc ;==>GetISODriveLetter Func PathIsWritable($sFile) Local $aRet = DllCall('kernel32.dll', 'handle', 'CreateFileW', _ 'wstr', $sFile, _ 'dword', 2, _ 'dword', 7, _ 'struct*', 0, _ 'dword', 3, _ 'dword', 0x02000000, _ 'handle', 0) If @error Or $aRet[0] = Ptr(-1) Or $aRet[0] = 0 Then Return False DllCall('kernel32.dll', 'bool', 'CloseHandle', 'handle', $aRet[0]) Return True EndFunc ;==>PathIsWritable Func DiskList() RunWait('cmd /c diskpart /s ' & '"' & GetCachePath() & 'list.ini' & '"' & '>' & '"' & GetCachePath() & 'dpoutput.txt' & '"', @WorkingDir, @SW_HIDE) Local $as_diskpart = 0 Local $s_Filtered = '' ; read the file to an array _FileReadToArray(GetCachePath() & 'dpoutput.txt', $as_diskpart) ; loop through the array For $i = 1 To $as_diskpart[0] If StringRegExp($as_diskpart[$i], '(?i)Disk [\d]+') Then $s_Filtered &= $as_diskpart[$i] & '|' Next ; return the filtered string Return StringRegExpReplace($s_Filtered, '[\s|]*$', '') EndFunc ;==>DiskList Func GetCachePath() Local Static $s_CachePath = IniRead(@WorkingDir & '\USBTool.ini', "Settings", "CachePath", @WorkingDir & '\cache') & '\' Return $s_CachePath EndFunc ;==>GetCachePath Func PrepFormat($Drive) GetDriveLetters() createDiskPartScriptFile(GetCachePath() & 'clean.dat', 'Sel Dis ' & $Drive & @CRLF & 'clean' & @CRLF & 'Exit') createDiskPartScriptFile(GetCachePath() & 'attrib.dat', 'Sel Dis ' & $Drive & @CRLF & 'attribute disk clear readonly' & @CRLF & 'Exit') createDiskPartScriptFile(GetCachePath() & 'scrubber.dat', 'Sel Dis ' & $Drive & @CRLF & 'cre par pri' & @CRLF & 'format quick fs=NTFS label=scrubber' & @CRLF & 'Exit') createDiskPartScriptFile(GetCachePath() & 'convert.dat', 'Sel Dis ' & $Drive & @CRLF & 'convert mbr' & @CRLF & 'Exit') createDiskPartScriptFile(GetCachePath() & 'initdata.dat', 'Sel Dis ' & $Drive & @CRLF & 'cre par pri' & @CRLF & 'shrink minimum=' & BootWim_GetSize() & @CRLF & 'format quick fs=ntfs label="WinPE Data"' & @CRLF & 'assign letter=' & $dataDrive & @CRLF & 'Exit') createDiskPartScriptFile(GetCachePath() & 'initboot.dat', 'Sel Dis ' & $Drive & @CRLF & 'cre par pri' & @CRLF & 'format quick fs=fat32 label="BOOTFILES"' & @CRLF & 'assign letter=' & $bootDrive & @CRLF & 'Active' & @CRLF & 'Exit') EndFunc ;==>PrepFormat Func CopyBootFiles() RunWait('cmd /c xcopy ' & $MountedDrive & ':\BOOT ' & $bootDrive & ':\BOOT /i /s /e /h /r /v /y', @WorkingDir, @SW_HIDE) ProgressSet(27 & "%", "Copying Boot Partition ") RunWait('cmd /c xcopy ' & $MountedDrive & ':\EFI ' & $bootDrive & ':\EFI /i /s /e /h /r /v /y', @WorkingDir, @SW_HIDE) ProgressSet(40 & "%", "Copying Boot.wim, this may take a while... ") RunWait('cmd /c xcopy ' & $MountedDrive & ':\sources ' & $bootDrive & ':\sources /i /s /e /h /r /v /y', @WorkingDir, @SW_HIDE) ProgressSet(50 & "%", "Copying Boot Files ") If FileExists($MountedDrive & ":\BOOTMGR.") Then RunWait('cmd /c xcopy ' & $MountedDrive & ':\BOOTMGR. ' & $bootDrive & ':\ /h /r /v /y', @WorkingDir, @SW_HIDE) If FileExists($MountedDrive & ":\bootmgr.efi") Then RunWait('cmd /c xcopy ' & $MountedDrive & ':\bootmgr.efi ' & $bootDrive & ':\ /h /r /v /y', @WorkingDir, @SW_HIDE) If FileExists($MountedDrive & ":\bootmgr.exe") Then RunWait('cmd /c xcopy ' & $MountedDrive & ':\bootmgr.exe ' & $bootDrive & ':\ /h /r /v /y', @WorkingDir, @SW_HIDE) If FileExists($MountedDrive & ":\menu.lst") Then RunWait('cmd /c xcopy ' & $MountedDrive & ':\menu.lst ' & $bootDrive & ':\ /h /r /v /y', @WorkingDir, @SW_HIDE) EndFunc ;==>CopyBootFiles Func CopyDataFilesF() Local $GoFiles = (GetCachePath() & $finalfiles), $StartProgAt, $xcopycmd, $line = "" FileOpen($GoFiles, 0) Local $aArray[1000] ReDim $aArray[_FileCountLines($GoFiles) + 1] For $i = 1 To _FileCountLines($GoFiles) $newline = FileReadLine($GoFiles, $i) $aArray[$i] = $newline Next _ArraySort($aArray) $StartProgAt = 55 For $i = 1 To UBound($aArray) - 1 ProgressSet($StartProgAt & "%", "Copying " & $aArray[$i]) RunWait('cmd /c xcopy ' & $MountedDrive & ':\' & $aArray[$i] & ' ' & $dataDrive & ':\' & ' /h /r /v /y', @WorkingDir, @SW_HIDE, 2) $StartProgAt = ($StartProgAt + 1) Next EndFunc ;==>CopyDataFilesF Func CopyDataFilesD() Local $GoFiles = (GetCachePath() & $finaldirs), $StartProgAt, $xcopycmd, $line = "" FileOpen($GoFiles, 0) Local $aArray[1000] ReDim $aArray[_FileCountLines($GoFiles) + 1] For $i = 1 To _FileCountLines($GoFiles) $newline = FileReadLine($GoFiles, $i) $aArray[$i] = $newline Next _ArraySort($aArray) $StartProgAt = 65 For $i = 1 To UBound($aArray) - 1 If $aArray[$i] = "Programs" Then ProgressSet($StartProgAt & "%", "Copying Programs Folder, this may take a while...") RunWait('cmd /c xcopy ' & $MountedDrive & ':\' & $aArray[$i] & ' ' & $dataDrive & ':\' & $aArray[$i] & ' /i /s /e /h /r /v /y', @WorkingDir, @SW_HIDE, 2) $StartProgAt = ($StartProgAt + 15) Else ProgressSet($StartProgAt & "%", "Copying " & $aArray[$i] & " Folder") RunWait('cmd /c xcopy ' & $MountedDrive & ':\' & $aArray[$i] & ' ' & $dataDrive & ':\' & $aArray[$i] & ' /i /s /e /h /r /v /y', @WorkingDir, @SW_HIDE, 2) $StartProgAt = ($StartProgAt + 1) EndIf Next EndFunc ;==>CopyDataFilesD Func createDiskPartScriptFile($fileName, $message) $CacheFile = '' $CacheFile = FileOpen($fileName, 2) FileWrite($CacheFile, $message) FileClose($CacheFile) EndFunc ;==>createDiskPartScriptFile Func GetDriveLetters() Local $allDriveLetters = "CDEFGHIJKLMNOPQRSTUVWXYZ", $AvailDriveLetters Local $aArray = DriveGetDrive($DT_ALL) If @error Then ; An error occurred when retrieving the drives. MsgBox($MB_SYSTEMMODAL, "", "An Error Occurred! Unable to retrieve " & @CRLF & "available drive letters! Exiting Program...") Cleanup() UnmountIso() Exit Else For $i = 1 To $aArray[0] $driveLetter = StringLeft(StringUpper($aArray[$i]), 1) $allDriveLetters = StringReplace($allDriveLetters, $driveLetter, "") Next EndIf $AvailDriveLetters = StringSplit($allDriveLetters, "") $bootDrive = $AvailDriveLetters[1] ;Get first available letter $dataDrive = $AvailDriveLetters[2] ;Get second available letter EndFunc ;==>GetDriveLetters Func CleanDirList() Local $rawlist = 'isod.dat' $finaldirs = 'isodirs.dat' RunWait('cmd /c DIR /B /A:D ' & $MountedDrive & ':\>' & '"' & GetCachePath() & $rawlist & '"', @WorkingDir, @SW_HIDE) RunWait('cmd /c FINDSTR /v /i /c:' & '"' & 'efi' & '"' & ' /c:' & '"' & 'boot' & '"' & ' /c:' & '"' & 'sources' & '"' & ' "' & GetCachePath() & $rawlist & '"' & '>>' & '"' & GetCachePath() & $finaldirs & '"', @WorkingDir, @SW_HIDE) EndFunc ;==>CleanDirList Func CleanFileList() Local $rawlist = 'isof.dat' $finalfiles = 'isofiles.dat' RunWait('cmd /c DIR /B /A-D ' & $MountedDrive & ':\>' & '"' & GetCachePath() & $rawlist & '"', @WorkingDir, @SW_HIDE) RunWait('cmd /c FINDSTR /v /i /c:' & '"' & 'bootmgr' & '"' & ' /c:' & '"' & 'menu' & '"' & ' "' & GetCachePath() & $rawlist & '"' & '>>' & '"' & GetCachePath() & $finalfiles & '"', @WorkingDir, @SW_HIDE) EndFunc ;==>CleanFileList Func Format() Local $aArray[7][3] = [ _ ["Cleaning Drive", 'cmd /c diskpart /s ' & '"' & GetCachePath() & 'clean.dat' & '"'], _ ["Cleaning Drive", 'cmd /c diskpart /s ' & '"' & GetCachePath() & 'scrub.dat' & '"'], _ ["Cleaning Drive", 'cmd /c diskpart /s ' & '"' & GetCachePath() & 'clean.dat' & '"'], _ ["Resetting Disk Attributes", 'cmd /c diskpart /s ' & '"' & GetCachePath() & 'attrib.dat' & '"'], _ ["Converting Layout to MBR", 'cmd /c diskpart /s ' & '"' & GetCachePath() & 'convert.dat' & '"'], _ ["Creating Data Partition", 'cmd /c diskpart /s ' & '"' & GetCachePath() & 'initdata.dat' & '"'], _ ["Creating Boot Partition", 'cmd /c diskpart /s ' & '"' & GetCachePath() & 'initboot.dat' & '"'] _ ] For $i = 0 To UBound($aArray) - 1 ProgressSet($i * 2 & "%", $aArray[$i][0]) ;MsgBox($MB_ICONINFORMATION, "Troubleshooting.. ", $aArray[$i][1]) ;Troubleshoot Array Data RunWait($aArray[$i][1], @WorkingDir, @SW_HIDE) Sleep(750) Next EndFunc ;==>Format Edited December 12, 2021 by bobomb Link to comment Share on other sites More sharing options...
benners Posted December 11, 2021 Share Posted December 11, 2021 It would be better and easier to use AutoIt to copy the files. Benefits are as you know, no messing with STDOUT (some programs don't return the output until the end). Error checking with AutoIt functions. You can easily get the file names for progress or label updating. From looking at the code, it seems the programs aim is to allow selection of a drive, format the drive and copy the contents of an iso image to it. Is this correct? I have a couple of questions about it. In CleanFileList and CleanDirList, you get a ist of the files, then another list that excludes certain files. The excluded files are copied over anyway in CopyBootFiles. Is there a reason for this? There is a free program called Rufus that does this exact thing, albeit missing the check for the marker file, have you heard of this program or are you doing this project to learn AutoIt? If you need help with the AutoIt commands, I don't mind helping. Link to comment Share on other sites More sharing options...
bobomb Posted December 11, 2021 Author Share Posted December 11, 2021 (edited) 1.) Cleanfilelist and CleanDirlist remove all traces of boot files/folders from the data partition file list. The Boot files are always the same but the data files are an unknown factor depending on how you create your media. Originally this was a simple cmd script with text interface, I could hardcode the paths for the necessary bootfiles but not the other data...originally thats how I was doing it so I just have to break from that method is all... 2.) This faster than rufus by a noticeable amount on USB 2.0 drives(when lots of small files are involved) but no real difference on faster 3.0 drives, maybe a few seconds. Its simpler, and it can be used on fixed HDD's... Rufus cannot... The original cmd script I made was before rufus allowed for UEFI + Legacy support option you used to have to choose one or the other with Rufus...I think sometime between 3.11 and 3.13. Cmd script works perfect still I just am doing this to replace the the below CMD script and retire it. And ALSO MAINLY to learn.... Just as a reference the original CMD below (Dont want to post cmd scripts but we have been going over it so much I wanted to show u where this whole thing came from) expandcollapse popup@ECHO OFF CLS SETLOCAL EnableExtensions EnableDelayedExpansion TITLE Bob.Omb's USB Creation Tool :PROPERUSE IF [%1]==[] GOTO IMPROPERUSE POWERSHELL.EXE "Mount-DiskImage ""%1""" >nul for /f "tokens=3 delims=\:" %%d in ('reg query hklm\system\mounteddevices ^| findstr /c:"5C003F00" ^| findstr /v "{.*}"') do ( IF EXIST %%d:\CdUsb.Y SET SOURCE=%%d ) IF NOT EXIST %SOURCE%:\CdUsb.Y GOTO NOTCOMPAT2 SET SIZE=0 CALL :FILESIZE "%SOURCE%:\sources\boot.wim" SET /A SIZE=(%size%+209715000)/1048576 GOTO CHECKSIZE :FILESIZE SET SIZE=%~z1 EXIT /b 0 :CHECKSIZE IF [%SIZE%]==[] GOTO NOTCOMPAT1 :BOOTDRV SET "s=" FOR %%s IN (I J K L M N O P Q) DO ( IF NOT EXIST %%s: SET "BOOTDRV=%%s" && GOTO PROGDRV ) :PROGDRV SET "t=" FOR %%t IN (R S T U V W X Y Z) DO ( IF NOT EXIST %%t: SET "PROGDRV=%%t" && GOTO INIT1 ) :INIT1 CLS ECHO Bob.Omb's USB Creation Tool ECHO -------------------------------------------- IF EXIST "%~dp0TempUSB" DEL /S /Q "%~dp0TempUSB\*.*" >nul MD "%~dp0TempUSB" >nul ECHO list disk >"%~dp0TempUSB\list.txt" diskpart /s "%~dp0TempUSB\list.txt" ECHO. DEL "%~dp0TempUSB\list.txt" SET /p disk="Select the disk number for your USB Drive (e.g. 2): " IF [%DISK%]==[] GOTO CHOOSEABORT ECHO. IF %DISK%==0 ECHO THIS IS USUALLY YOUR SYSTEM DRIVE! ARE YOU SURE? & ECHO. ECHO --WARNING-- This will FORMAT the selected disk and ERASE ALL DATA ECHO. ECHO MAKE SURE YOU ARE SELECTING THE CORRECT DISK!! ECHO. ECHO You selected disk ---^> %disk% ECHO. CHOICE /C YN /M "Is this correct " IF %ERRORLEVEL%==1 GOTO INIT2 IF %ERRORLEVEL%==2 GOTO INIT1 :ABORT CLS ECHO -Cleaning Up- CD /D %~dp0 IF EXIST "%~dp0TempUSB\*.*" DEL /S /Q "%~dp0TempUSB\*.*" >nul IF EXIST "%~dp0TempUSB" RD "%~dp0TempUSB" >nul POWERSHELL.EXE "Dismount-DiskImage ""%1""" >nul ECHO Process Aborted, No changes have been made... ECHO. PAUSE EXIT :INIT2 ECHO select disk %disk% >"%~dp0TempUSB\init.txt" ECHO attribute disk clear readonly >>"%~dp0TempUSB\init.txt" ECHO clean >>"%~dp0TempUSB\init.txt" ECHO exit >>"%~dp0TempUSB\init.txt" ECHO select disk %disk% >"%~dp0TempUSB\initdata.txt" ECHO clean >>"%~dp0TempUSB\initdata.txt" ECHO convert mbr >>"%~dp0TempUSB\initdata.txt" ECHO create partition primary >>"%~dp0TempUSB\initdata.txt" ECHO shrink minimum=%SIZE% >>"%~dp0TempUSB\initdata.txt" ECHO format quick fs=ntfs label="WinPE Data" >>"%~dp0TempUSB\initdata.txt" ECHO assign letter=%PROGDRV% >>"%~dp0TempUSB\initdata.txt" ECHO exit >>"%~dp0TempUSB\initdata.txt" ECHO select disk %disk% >"%~dp0TempUSB\initboot.txt" ECHO create partition primary>>"%~dp0TempUSB\initboot.txt" ECHO format quick fs=fat32 label="BOOTFILES" >>"%~dp0TempUSB\initboot.txt" ECHO assign letter=%BOOTDRV% >>"%~dp0TempUSB\initboot.txt" ECHO active >>"%~dp0TempUSB\initboot.txt" ECHO exit >>"%~dp0TempUSB\initboot.txt" :RUNMBR CLS ECHO Bob.Omb's USB Creation Tool ECHO -------------------------------------------- ECHO. CD /D "%~dp0" ECHO Preparing Disk %disk%... ECHO. diskpart /s "%~dp0TempUSB\init.txt" >nul ECHO. ECHO Formatting Data Section of Disk %disk%... ECHO. diskpart /s "%~dp0TempUSB\initdata.txt" >nul ECHO. ECHO Formatting Boot Section of Disk %disk%... diskpart /s "%~dp0TempUSB\initboot.txt" >nul ECHO. ECHO -Preparing FileCopy- :COPYBOOTFILES CD /D %SOURCE%: IF EXIST "%~dp0TempUSB\isod.txt" DEL "%~dp0TempUSB\isod.txt" IF EXIST "%~dp0TempUSB\isodirs.txt" DEL "%~dp0TempUSB\isodirs.txt" DIR /B /A:D>"%~dp0TempUSB\isod.txt" FINDSTR /v /i /c:"efi" /c:"boot" /c:"sources" "%~dp0TempUSB\isod.txt">>"%~dp0TempUSB\isodirs.txt" DEL "%~dp0TempUSB\isod.txt" >nul IF EXIST "%~dp0TempUSB\isof.txt" DEL "%~dp0TempUSB\isof.txt" IF EXIST "%~dp0TempUSB\isofiles.txt" DEL "%~dp0TempUSB\isofiles.txt" DIR /B /A-D>"%~dp0TempUSB\isof.txt" FINDSTR /v /i /c:"bootmgr" /c:"menu" "%~dp0TempUSB\isof.txt">>"%~dp0TempUSB\isofiles.txt" DEL "%~dp0TempUSB\isof.txt" >nul ECHO. ECHO -Copying Boot Files- XCOPY %SOURCE%:\BOOT %BOOTDRV%:\BOOT /i /s /e /r /v /h /y XCOPY %SOURCE%:\EFI %BOOTDRV%:\EFI /i /s /e /r /v /h /y ECHO THE SOURCES FOLDER MAY TAKE A WHILE - PLEASE BE PATIENT ECHO USB 3.0 = Approx 1-3 minutes ECHO USB 2.0 = Approx 5-15 minutes XCOPY %SOURCE%:\sources %BOOTDRV%:\sources /i /s /e /r /v /h /y IF EXIST %SOURCE%:\BOOTMGR. XCOPY %SOURCE%:\BOOTMGR. %BOOTDRV%:\ /r /v /h /y IF EXIST %SOURCE%:\bootmgr.efi XCOPY %SOURCE%:\bootmgr.efi %BOOTDRV%:\ /r /v /h /y IF EXIST %SOURCE%:\bootmgr.exe XCOPY %SOURCE%:\bootmgr.exe %BOOTDRV%:\ /r /v /h /y IF EXIST %SOURCE%:\menu.lst XCOPY %SOURCE%:\menu.lst %BOOTDRV%:\ /r /v /h /y ECHO. ECHO -Copying Program Files- CD /D %~dp0 pushd "%~dp0TempUSB" SET "a=" for /f "tokens=* delims=" %%a in ('TYPE ISODIRS.TXT') do xcopy /isehrvy "%SOURCE%:\%%a" "%PROGDRV%:\%%a" popd DEL /S /Q "%~dp0TempUSB\isodirs.txt" >nul pushd "%~dp0TempUSB" SET "a=" for /f "tokens=* delims=" %%a in ('TYPE ISOFILES.TXT') do xcopy /hrvy "%SOURCE%:\%%a" "%PROGDRV%:\" popd DEL /S /Q "%~dp0TempUSB\isofiles.txt" >nul ECHO. ECHO -Cleaning Up- ENDLOCAL CD /D %~dp0 IF EXIST "%~dp0TempUSB\*.*" DEL /S /Q "%~dp0TempUSB\*.*" >nul IF EXIST "%~dp0TempUSB" RD "%~dp0TempUSB" >nul POWERSHELL.EXE "Dismount-DiskImage ""%1""" >nul ECHO. ECHO The USB drive is now prepared for Legacy and UEFI boot (Macs Too) ECHO. ECHO. PAUSE EXIT :IMPROPERUSE CLS ECHO. ECHO ============================================= ECHO. ECHO IMPROPER USE DETECTED ECHO. ECHO CLOSE THE PROGRAM AND DRAG AND DROP THE ISO ECHO ONTO THE TOOL TO BEGIN ECHO. ECHO THIS TOOL CANNOT BE RUN DIRECTLY ECHO ============================================= ECHO. ECHO. ECHO. PAUSE EXIT :CHOOSEABORT ECHO. CHOICE /C YN /M "Would you like to abort? " IF %ERRORLEVEL%==1 GOTO ABORT ) ELSE ( GOTO INITMBR ) EXIT :NOTCOMPAT1 CLS CD /D %~dp0 IF EXIST "%~dp0TempUSB\*.*" DEL /S /Q "%~dp0TempUSB\*.*" >nul IF EXIST "%~dp0TempUSB" RD "%~dp0TempUSB" >nul POWERSHELL.EXE "Dismount-DiskImage ""%1""" >nul ECHO. ECHO ============================================== ECHO. ECHO INCOMPATIBLE ISO ECHO. ECHO THIS TOOL IS FOR ISO's CREATED BY PESE/XPE ECHO BOOT.WIM MUST BE PRESENT ECHO. ECHO ============================================== ECHO. ECHO. ECHO. PAUSE EXIT :NOTCOMPAT2 CLS CD /D %~dp0 IF EXIST "%~dp0TempUSB\*.*" DEL /S /Q "%~dp0TempUSB\*.*" >nul IF EXIST "%~dp0TempUSB" RD "%~dp0TempUSB" >nul POWERSHELL.EXE "Dismount-DiskImage ""%1""" >nul ECHO. ECHO ============================================== ECHO. ECHO INCOMPATIBLE ISO ECHO. ECHO THIS TOOL IS FOR ISO's CREATED BY PESE/XPE ECHO CdUsb.Y MUST BE PRESENT ECHO. ECHO ============================================== ECHO. ECHO. ECHO. PAUSE EXIT END LOCAL Edited December 12, 2021 by bobomb benners 1 Link to comment Share on other sites More sharing options...
bobomb Posted December 11, 2021 Author Share Posted December 11, 2021 (edited) I feel like if I am making something to put a bootable ISO onto a USB there really shouldnt be any questions for the user... They shouldnt have to decide the partition layout, cluster size... I dont even want people to have to select an ISO.. Thats why the program will only run if you drop and ISO directly on the EXE, or CLI the full path to an ISO.. Drop the ISO on the tool to open it, if the program is open the ISO is already selected: 2 steps to use, Pick your USB/Disk number, click 'Burn'... and it burns as fast as possible, no options, no choices.. and at the other end a bootable usb(or fixed disk) compatible with Legacy/UEFI PC's and Macs pops out every time, and you can focus on why u needed to burn the ISO and not burning the ISO lol... I cant remember exactly why preferred this method over what Rufus would achieve. There was a reason Im sure, other than the advanced interface. (It may have been that a MBR fat32 partition was necessary to boot on macs? Rufus creates a single MBR NTFS partition with an EFI structure to allow for CSM/UEFI dual boot, which works, but not on macs...i dont remember I think there was something else too) Also the disk layout had to have the data partition first and the boot partition second as Windows 7 would only recognize the "First" partition on a USB with multiple partitions.. I dont mean to leave such a long winded explanation, Rufus is the king for sure for burning bootable USB's.. Edited December 11, 2021 by bobomb Link to comment Share on other sites More sharing options...
benners Posted December 11, 2021 Share Posted December 11, 2021 Aye, the dos functions will be quicker, so for simple things it maybe worthwhile keeping those. I have done another function to fill the list which doesn't use a file write and read and runs diskpart directly. You can swap it with the DiskList and remove the 3 lines after DirCreate(GetCachePath()) Func GetDiskListings() Local $i_PID = Run('diskpart.exe', @SystemDir, @SW_HIDE, BitOR($STDIN_CHILD, $STDOUT_CHILD)) StdinWrite($i_PID, 'list disk') StdinWrite($i_PID) Local $s_STDOUT = '' Local $s_Ret = '' While 1 $s_STDOUT = StdoutRead($i_PID) If @error Then ExitLoop ; clean up the string and add it to the return if it has disk info If StringRegExp($s_STDOUT, '(?i)Disk [\d]+') Then $s_Ret &= StringReplace(StringRegExpReplace($s_STDOUT, '[\s|]*$', ''), @crlf, '') & '|' WEnd Return $s_Ret EndFunc bobomb 1 Link to comment Share on other sites More sharing options...
bobomb Posted December 11, 2021 Author Share Posted December 11, 2021 (edited) @benners I found this elsewhere on the forum for disk checking and it looks a LOT better than what I'm using. Is there any way to make this parse with this type of look and only be able to select the "Disk" line but still show the partition line? I cannot even get it to wrap(got it) when I add it to my disk function but it will display all on 1 line with return Example MsgBox from the forum: expandcollapse popup#include <WinAPIFiles.au3> #include <Array.au3> GetDriveList() Func GetDriveList() Local $aDriveInfo, $iLastDevNumber = -1 Local $aFixed = DriveGetDrive('FIXED'), $aRemovable = DriveGetDrive('REMOVABLE') Local $aDrives[ (IsArray($aFixed) ? $aFixed[0] : 0) + (IsArray($aRemovable) ? $aRemovable[0] : 0) ][3] Local $iDrive = 0 For $i = 1 To UBound($aFixed) - 1 $aDrives[$iDrive][0] = $aFixed[$i] $aDriveInfo = _WinAPI_GetDriveNumber($aFixed[$i]) If Not @error Then $aDrives[$iDrive][1] = $aDriveInfo[1] $aDrives[$iDrive][2] = $aDriveInfo[2] EndIf $iDrive += 1 Next For $i = 1 To UBound($aRemovable) - 1 $aDrives[$iDrive][0] = $aRemovable[$i] $aDriveInfo = _WinAPI_GetDriveNumber($aRemovable[$i]) If Not @error Then $aDrives[$iDrive][1] = $aDriveInfo[1] $aDrives[$iDrive][2] = $aDriveInfo[2] EndIf $iDrive += 1 Next _ArraySort($aDrives, 0, 0, 0, 1) Local $sDrivesInfo = "Drive list :" & @CRLF For $i = 0 To UBound($aDrives) - 1 If IsNumber($aDrives[$i][1]) Then If $aDrives[$i][1] <> $iLastDevNumber Then $sDrivesInfo &= @CRLF & "Disk #" & $aDrives[$i][1] & " [" & _GetDiskNameByNumber($aDrives[$i][1]) & "]" & @CRLF $iLastDevNumber = $aDrives[$i][1] EndIf $sDrivesInfo &= " - Partition #" & $aDrives[$i][2] & " " & DriveGetLabel($aDrives[$i][0]) & " - " & $aDrives[$i][0] & @CRLF EndIf Next MsgBox(0, "", $sDrivesInfo) EndFunc Func _GetDiskNameByNumber($iDiskNumber) Local $iCount = RegRead("HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\disk\Enum", "Count") Local $sDiskKey = RegRead("HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\disk\Enum", String($iDiskNumber)) If @error Then Return SetError(1, 0, 0) Local $sDiskName = RegRead("HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\" & $sDiskKey, "FriendlyName") If $sDiskName = "" Then $sDiskName = RegRead("HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\" & $sDiskKey, "DeviceDesc") Return $sDiskName EndFunc Located here https://www.autoitscript.com/forum/topic/184895-get-diskname-without-diskpart-wmi-wmic/page/3/?tab=comments#comment-1329548 With my attempt to integrate it.. This displays in reverse, the partitions in their own group and the disk list is also in its own grouped together, the partitions being out of place I cant tell which disk they belong to.. expandcollapse popup#NoTrayIcon #RequireAdmin #include <AutoItConstants.au3> #include <WinAPIFiles.au3> #include <GUIConstantsEx.au3> #include <MsgBoxConstants.au3> #include <Constants.au3> #include <File.au3> #include <Array.au3> #include <String.au3> Global $DiskList, $Selection, $IsoFile, $MountedDrive = "" Global $finalfiles, $finaldirs, $wimSize, $bootDrive, $dataDrive ProperUse() MountIso() GetISODriveLetter() BootWim_Check() Cleanup() DirCreate(GetCachePath()) Opt("GUIOnEventMode", 1) MainMenu() Cleanup() Exit Func MainMenu() GUICreate('Burn Tool (XPE/SE) v2.0', 300, 298) GUISetOnEvent($GUI_EVENT_CLOSE, "SpecialEvents") GUISetOnEvent($GUI_EVENT_MINIMIZE, "SpecialEvents") GUISetOnEvent($GUI_EVENT_RESTORE, "SpecialEvents") GUISetIcon(@WorkingDir & '\USBTool.ico', 1) GUISetBkColor(0x797979) GUICtrlCreateLabel('1: Select a disk use...', 20, 10, 280) $DiskList = GUICtrlCreateList('', 20, 30, 260, 150) GUICtrlSetData(-1, GetDiskList()) $Refresh = GUICtrlCreateButton('Refresh List', 110, 185, 80, 25) GUICtrlSetOnEvent(-1, "RefreshPressed") GUICtrlSetState(-1, $GUI_FOCUS) GUICtrlCreateLabel('________________________________________', 30, 210, 280, 30) $Burn = GUICtrlCreateButton('Burn', 90, 232, 120, 40) GUICtrlSetOnEvent(-1, "BurnPressed") GUICtrlCreateLabel('( * ) Disk is Currently GPT', 160, 278, 130, 30) GUISetState() ; Just idle around While 1 Sleep(10) WEnd EndFunc ;==>MainMenu Func RefreshPressed() GUICtrlSetData($DiskList, "") GUICtrlSetData($DiskList, GetDiskList()) EndFunc ;==>RefreshPressed Func BurnPressed() If GUICtrlRead($DiskList) = '' Then MsgBox( _ $MB_ICONERROR, _ "Notice: ", _ "No disk has been selected") Else Local $s_DiskNumber = StringRegExp(GUICtrlRead($DiskList), '(?<=Disk\s)[0-9]+', $STR_REGEXPARRAYMATCH)[0] If @error Then MsgBox( _ $MB_ICONERROR, _ "Notice: ", _ "An error occured retrieving the disk number") Else If MsgBox( _ BitOR($MB_TOPMOST, $MB_ICONWARNING, $MB_YESNO, $MB_DEFBUTTON2), _ 'This will FORMAT Disk ' & $s_DiskNumber, _ 'ALL DATA WILL BE ERASED FROM DISK ' & $s_DiskNumber & @CRLF & 'Are you sure you want to proceed?') = $IDYES Then GUISetState(@SW_HIDE) ProgressOn("Applying ISO...", "Creating Bootable Media... ", "0%") PrepFormat($s_DiskNumber) ProgressSet(5 & "%", "Formatting Disk " & $s_DiskNumber) Format() ProgressSet(25 & "%", "Analyzing ISO Structure ") CleanDirList() CleanFileList() ProgressSet(26 & "%", "Copying Boot Partition ") CopyBootFiles() ;Progress in function; start at 55% CopyDataFilesF() ;Progress in function; start at 65% CopyDataFilesD() ProgressSet(100, "Finished", "ISO Applied!!") Sleep(2750) ProgressOff() Cleanup() UnmountIso() MsgBox($MB_ICONINFORMATION, "", " Enjoy! ") Exit EndIf EndIf EndIf EndFunc ;==>BurnPressed Func SpecialEvents() Select Case @GUI_CtrlId = $GUI_EVENT_CLOSE ; Code below for actions on Close Cleanup() UnmountIso() Exit Case @GUI_CtrlId = $GUI_EVENT_MINIMIZE ; Code below for actions on Minimize Case @GUI_CtrlId = $GUI_EVENT_RESTORE ; Code below for actions on Restore EndSelect EndFunc ;==>SpecialEvents Func ProperUse() If Not ($CmdLine[0]) = 0 Then ;Something was dropped on the EXE file or CLI was used with a flag(s) $IsoFile = ($CmdLine[1]) ;Sets $IsoFile var to the full path of whatever was dropped onto the EXE file or the 1st CLI flag that was used Else MsgBox($MB_ICONERROR, "Notice: ", "This program cannot be run directly!" & @CRLF & "Please drag an ISO onto" & @CRLF & "the program to begin...") Exit EndIf EndFunc ;==>ProperUse Func BootWim_Check() ; check for the boot wim file If Not FileExists($MountedDrive & ':\sources\boot.wim') Then MsgBox($MB_ICONERROR, "Notice: ", "BOOT.WIM NOT DETECTED!!!" & @CRLF & "This tool is designed for SE" & @CRLF & "and XPE projects only.") UnmountIso() Exit EndIf EndFunc ;==>BootWim_Check Func BootWim_GetSize() ; get the boot wim size and add 200 megabytes for headroom on boot partition Return Round((FileGetSize($MountedDrive & ':\sources\boot.wim') + 209715200) / 1048576) EndFunc ;==>BootWim_GetSize Func MountIso() RunWait('cmd /c powershell.exe ' & '"Mount-DiskImage "' & '"' & $IsoFile & '"' & '"' & '"' & ' >nul', @WorkingDir, @SW_HIDE) EndFunc ;==>MountIso Func UnmountIso() RunWait('cmd /c powershell.exe ' & '"Dismount-DiskImage "' & '"' & $IsoFile & '"' & '"' & '"' & ' >nul', @WorkingDir, @SW_HIDE) EndFunc ;==>UnmountIso Func Cleanup() If FileExists(GetCachePath()) Then DirRemove(GetCachePath(), $DIR_REMOVE) EndIf EndFunc ;==>Cleanup Func GetISODriveLetter() Local $findiso = StringSplit("CDEFGHIJKLMNOPQRSTUVWXYZ", "", 1) For $i = 1 To $findiso[0] Step +1 $isoExists = FileExists($findiso[$i] & ":\CdUsb.Y") If $isoExists Then If PathIsWritable($findiso[$i] & ":\") = False Then $MountedDrive = ($findiso[$i]) EndIf EndIf Next If $MountedDrive = "" Then MsgBox($MB_ICONERROR, "Notice: ", "CdUsb.Y NOT DETECTED!!!" & @CRLF & "This tool is designed for SE" & @CRLF & "and XPE projects only.") Exit EndIf EndFunc ;==>GetISODriveLetter Func PathIsWritable($sFile) Local $aRet = DllCall('kernel32.dll', 'handle', 'CreateFileW', _ 'wstr', $sFile, _ 'dword', 2, _ 'dword', 7, _ 'struct*', 0, _ 'dword', 3, _ 'dword', 0x02000000, _ 'handle', 0) If @error Or $aRet[0] = Ptr(-1) Or $aRet[0] = 0 Then Return False DllCall('kernel32.dll', 'bool', 'CloseHandle', 'handle', $aRet[0]) Return True EndFunc ;==>PathIsWritable Func GetDiskList() Local $aDriveInfo, $iLastDevNumber = -1 Local $aFixed = DriveGetDrive('FIXED'), $aRemovable = DriveGetDrive('REMOVABLE') Local $aDrives[(IsArray($aFixed) ? $aFixed[0] : 0) + (IsArray($aRemovable) ? $aRemovable[0] : 0)][3] Local $iDrive = 0 For $i = 1 To UBound($aFixed) - 1 $aDrives[$iDrive][0] = $aFixed[$i] $aDriveInfo = _WinAPI_GetDriveNumber($aFixed[$i]) If Not @error Then $aDrives[$iDrive][1] = $aDriveInfo[1] $aDrives[$iDrive][2] = $aDriveInfo[2] EndIf $iDrive += 1 Next For $i = 1 To UBound($aRemovable) - 1 $aDrives[$iDrive][0] = $aRemovable[$i] $aDriveInfo = _WinAPI_GetDriveNumber($aRemovable[$i]) If Not @error Then $aDrives[$iDrive][1] = $aDriveInfo[1] $aDrives[$iDrive][2] = $aDriveInfo[2] EndIf $iDrive += 1 Next _ArraySort($aDrives, 0, 0, 0, 1) Local $sDrivesInfo, $s_Drives For $i = 0 To UBound($aDrives) - 1 If IsNumber($aDrives[$i][1]) Then If $aDrives[$i][1] <> $iLastDevNumber Then $sDrivesInfo &= "Disk " & $aDrives[$i][1] & " [" & _GetDiskNameByNumber($aDrives[$i][1]) & "]" & "|" & @CRLF $iLastDevNumber = $aDrives[$i][1] EndIf $sDrivesInfo &= " - Partition #" & $aDrives[$i][2] & " " & DriveGetLabel($aDrives[$i][0]) & " - " & $aDrives[$i][0] & "|" & @CRLF EndIf Next Return $sDrivesInfo EndFunc ;==>GetDiskList Func _GetDiskNameByNumber($iDiskNumber) Local $iCount = RegRead("HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\disk\Enum", "Count") Local $sDiskKey = RegRead("HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\disk\Enum", String($iDiskNumber)) If @error Then Return SetError(1, 0, 0) Local $sDiskName = RegRead("HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\" & $sDiskKey, "FriendlyName") If $sDiskName = "" Then $sDiskName = RegRead("HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\" & $sDiskKey, "DeviceDesc") Return $sDiskName EndFunc ;==>_GetDiskNameByNumber Func GetCachePath() Local Static $s_CachePath = IniRead(@WorkingDir & '\USBTool.ini', "Settings", "CachePath", @WorkingDir & '\cache') & '\' Return $s_CachePath EndFunc ;==>GetCachePath Func PrepFormat($Drive) GetDriveLetters() createDiskPartScriptFile(GetCachePath() & 'clean.dat', 'Sel Dis ' & $Drive & @CRLF & 'clean' & @CRLF & 'Exit') createDiskPartScriptFile(GetCachePath() & 'attrib.dat', 'Sel Dis ' & $Drive & @CRLF & 'attribute disk clear readonly' & @CRLF & 'Exit') createDiskPartScriptFile(GetCachePath() & 'scrubber.dat', 'Sel Dis ' & $Drive & @CRLF & 'cre par pri' & @CRLF & 'format quick fs=NTFS label=scrubber' & @CRLF & 'Exit') createDiskPartScriptFile(GetCachePath() & 'convert.dat', 'Sel Dis ' & $Drive & @CRLF & 'convert mbr' & @CRLF & 'Exit') createDiskPartScriptFile(GetCachePath() & 'initdata.dat', 'Sel Dis ' & $Drive & @CRLF & 'cre par pri' & @CRLF & 'shrink minimum=' & BootWim_GetSize() & @CRLF & 'format quick fs=ntfs label="WinPE Data"' & @CRLF & 'assign letter=' & $dataDrive & @CRLF & 'Exit') createDiskPartScriptFile(GetCachePath() & 'initboot.dat', 'Sel Dis ' & $Drive & @CRLF & 'cre par pri' & @CRLF & 'format quick fs=fat32 label="BOOTFILES"' & @CRLF & 'assign letter=' & $bootDrive & @CRLF & 'Active' & @CRLF & 'Exit') EndFunc ;==>PrepFormat Func CopyBootFiles() RunWait('cmd /c xcopy ' & $MountedDrive & ':\BOOT ' & $bootDrive & ':\BOOT /i /s /e /h /r /v /y', @WorkingDir, @SW_HIDE) ProgressSet(27 & "%", "Copying Boot Partition ") RunWait('cmd /c xcopy ' & $MountedDrive & ':\EFI ' & $bootDrive & ':\EFI /i /s /e /h /r /v /y', @WorkingDir, @SW_HIDE) ProgressSet(40 & "%", "Copying Boot.wim, this may take a while... ") RunWait('cmd /c xcopy ' & $MountedDrive & ':\sources ' & $bootDrive & ':\sources /i /s /e /h /r /v /y', @WorkingDir, @SW_HIDE) ProgressSet(50 & "%", "Copying Boot Files ") If FileExists($MountedDrive & ":\BOOTMGR.") Then RunWait('cmd /c xcopy ' & $MountedDrive & ':\BOOTMGR. ' & $bootDrive & ':\ /h /r /v /y', @WorkingDir, @SW_HIDE) If FileExists($MountedDrive & ":\bootmgr.efi") Then RunWait('cmd /c xcopy ' & $MountedDrive & ':\bootmgr.efi ' & $bootDrive & ':\ /h /r /v /y', @WorkingDir, @SW_HIDE) If FileExists($MountedDrive & ":\bootmgr.exe") Then RunWait('cmd /c xcopy ' & $MountedDrive & ':\bootmgr.exe ' & $bootDrive & ':\ /h /r /v /y', @WorkingDir, @SW_HIDE) If FileExists($MountedDrive & ":\menu.lst") Then RunWait('cmd /c xcopy ' & $MountedDrive & ':\menu.lst ' & $bootDrive & ':\ /h /r /v /y', @WorkingDir, @SW_HIDE) EndFunc ;==>CopyBootFiles Func CopyDataFilesF() Local $GoFiles = (GetCachePath() & $finalfiles), $StartProgAt, $xcopycmd, $line = "" FileOpen($GoFiles, 0) Local $aArray[1000] ReDim $aArray[_FileCountLines($GoFiles) + 1] For $i = 1 To _FileCountLines($GoFiles) $newline = FileReadLine($GoFiles, $i) $aArray[$i] = $newline Next _ArraySort($aArray) $StartProgAt = 55 For $i = 1 To UBound($aArray) - 1 ProgressSet($StartProgAt & "%", "Copying " & $aArray[$i]) RunWait('cmd /c xcopy ' & $MountedDrive & ':\' & $aArray[$i] & ' ' & $dataDrive & ':\' & ' /h /r /v /y', @WorkingDir, @SW_HIDE, 2) $StartProgAt = ($StartProgAt + 1) Next EndFunc ;==>CopyDataFilesF Func CopyDataFilesD() Local $GoFiles = (GetCachePath() & $finaldirs), $StartProgAt, $xcopycmd, $line = "" FileOpen($GoFiles, 0) Local $aArray[1000] ReDim $aArray[_FileCountLines($GoFiles) + 1] For $i = 1 To _FileCountLines($GoFiles) $newline = FileReadLine($GoFiles, $i) $aArray[$i] = $newline Next _ArraySort($aArray) $StartProgAt = 65 For $i = 1 To UBound($aArray) - 1 If $aArray[$i] = "Programs" Then ProgressSet($StartProgAt & "%", "Copying Programs Folder, this may take a while...") RunWait('cmd /c xcopy ' & $MountedDrive & ':\' & $aArray[$i] & ' ' & $dataDrive & ':\' & $aArray[$i] & ' /i /s /e /h /r /v /y', @WorkingDir, @SW_HIDE, 2) $StartProgAt = ($StartProgAt + 15) Else ProgressSet($StartProgAt & "%", "Copying " & $aArray[$i] & " Folder") RunWait('cmd /c xcopy ' & $MountedDrive & ':\' & $aArray[$i] & ' ' & $dataDrive & ':\' & $aArray[$i] & ' /i /s /e /h /r /v /y', @WorkingDir, @SW_HIDE, 2) $StartProgAt = ($StartProgAt + 1) EndIf Next EndFunc ;==>CopyDataFilesD Func createDiskPartScriptFile($fileName, $message) $CacheFile = '' $CacheFile = FileOpen($fileName, 2) FileWrite($CacheFile, $message) FileClose($CacheFile) EndFunc ;==>createDiskPartScriptFile Func GetDriveLetters() Local $allDriveLetters = "CDEFGHIJKLMNOPQRSTUVWXYZ", $AvailDriveLetters Local $aArray = DriveGetDrive($DT_ALL) If @error Then ; An error occurred when retrieving the drives. MsgBox($MB_SYSTEMMODAL, "", "An Error Occurred! Unable to retrieve " & @CRLF & "available drive letters! Exiting Program...") Cleanup() UnmountIso() Exit Else For $i = 1 To $aArray[0] $driveLetter = StringLeft(StringUpper($aArray[$i]), 1) $allDriveLetters = StringReplace($allDriveLetters, $driveLetter, "") Next EndIf $AvailDriveLetters = StringSplit($allDriveLetters, "") $bootDrive = $AvailDriveLetters[1] ;Get first available letter $dataDrive = $AvailDriveLetters[2] ;Get second available letter EndFunc ;==>GetDriveLetters Func CleanDirList() Local $rawlist = 'isod.dat' $finaldirs = 'isodirs.dat' RunWait('cmd /c DIR /B /A:D ' & $MountedDrive & ':\>' & '"' & GetCachePath() & $rawlist & '"', @WorkingDir, @SW_HIDE) RunWait('cmd /c FINDSTR /v /i /c:' & '"' & 'efi' & '"' & ' /c:' & '"' & 'boot' & '"' & ' /c:' & '"' & 'sources' & '"' & ' "' & GetCachePath() & $rawlist & '"' & '>>' & '"' & GetCachePath() & $finaldirs & '"', @WorkingDir, @SW_HIDE) EndFunc ;==>CleanDirList Func CleanFileList() Local $rawlist = 'isof.dat' $finalfiles = 'isofiles.dat' RunWait('cmd /c DIR /B /A-D ' & $MountedDrive & ':\>' & '"' & GetCachePath() & $rawlist & '"', @WorkingDir, @SW_HIDE) RunWait('cmd /c FINDSTR /v /i /c:' & '"' & 'bootmgr' & '"' & ' /c:' & '"' & 'menu' & '"' & ' "' & GetCachePath() & $rawlist & '"' & '>>' & '"' & GetCachePath() & $finalfiles & '"', @WorkingDir, @SW_HIDE) EndFunc ;==>CleanFileList Func Format() Local $aArray[7][3] = [ _ ["Cleaning Drive", 'cmd /c diskpart /s ' & '"' & GetCachePath() & 'clean.dat' & '"'], _ ["Cleaning Drive", 'cmd /c diskpart /s ' & '"' & GetCachePath() & 'scrub.dat' & '"'], _ ["Cleaning Drive", 'cmd /c diskpart /s ' & '"' & GetCachePath() & 'clean.dat' & '"'], _ ["Resetting Disk Attributes", 'cmd /c diskpart /s ' & '"' & GetCachePath() & 'attrib.dat' & '"'], _ ["Converting Layout to MBR", 'cmd /c diskpart /s ' & '"' & GetCachePath() & 'convert.dat' & '"'], _ ["Creating Data Partition", 'cmd /c diskpart /s ' & '"' & GetCachePath() & 'initdata.dat' & '"'], _ ["Creating Boot Partition", 'cmd /c diskpart /s ' & '"' & GetCachePath() & 'initboot.dat' & '"'] _ ] For $i = 0 To UBound($aArray) - 1 ProgressSet($i * 2 & "%", $aArray[$i][0]) ;MsgBox($MB_ICONINFORMATION, "Troubleshooting.. ", $aArray[$i][1]) ;Troubleshoot Array Data RunWait($aArray[$i][1], @WorkingDir, @SW_HIDE) Sleep(750) Next EndFunc ;==>Format Should I open a new thread for this? I dont want to crosspost too much for the same app but also I do not want to drag several questions down an incorrectly titled thread.. (update thread name maybe?) Edited December 12, 2021 by bobomb Link to comment Share on other sites More sharing options...
benners Posted December 12, 2021 Share Posted December 12, 2021 I'll have a look, I'm sure we can manipulate the results to the programs need but I doubt you will be able to get the list to function like that. Some ideas would be Change the list to a listview or combo box. The listview could have columns for the drive info and partition info ( a bit fiddly if there's loads or partitions). A combo would just have the drive info for selection and add another control to display the partition info. Keep the list but add a label or other control to display the partition info. If you're going to want to display file names, copy progress etc you will have to alter the gui or create another one anyway. As for the topic, It's your topic. You could add different tags for the topic and\or change the title to USB Burning Tool, this would encompass all the different changes to the program and would be a better description of the topic content. Link to comment Share on other sites More sharing options...
bobomb Posted December 12, 2021 Author Share Posted December 12, 2021 (edited) Maybe I will take the partitions out if needed. I would prefer if the correct partitions showed under their respective disks, i could just set a msgbox to instruct the user to choose a line containing a disk... or figure out a way to have the selection associated with the appropriate disk if a partition is selected. idk depends on if it is a pain or not, btw you are awesome. I am still going to make use of your STDout example with other sections I just need to review it a few times and run some tests.. Really reversing the array would be enough for me to get unstuck.. Edited December 12, 2021 by bobomb Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now