doestergaard

Locate Windows Drive using WMI (for WinPE)

12 posts in this topic

#1 ·  Posted (edited)

In one of my scripts, I needed to know, where Windows was installed at. I know there is several ways to this already, but I was thinking that I would share how I do it using WMI.

If anyone has any suggestions or comment on the code, feel free to do so.

 

Code:

#include <File.au3>

Local $STR_DRIVE = GetWindowsDrive()
If @error Then
   MsgBox(@extended, "Result", "Unable to locate Windows", 0)
Else
   MsgBox(@extended, "Result", "Windows is located at: " & $STR_DRIVE, 0)
EndIf
Exit


Func GetWindowsDrive()
   Local $WMI_GET = ObjGet("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2")
   If Not IsObj($WMI_GET) Then Return SetError(1, 16, 0)

   Local $WMI_COL_DRIVES = $WMI_GET.ExecQuery("SELECT DeviceID FROM Win32_DiskDrive WHERE MediaType='Fixed hard disk media'")

   For $WMI_DRIVE In $WMI_COL_DRIVES
      Local $WMI_COL_PARTITIONS = $WMI_GET.ExecQuery("ASSOCIATORS OF {Win32_DiskDrive.DeviceID='" & $WMI_DRIVE.DeviceID & "'} WHERE AssocClass = Win32_DiskDriveToDiskPartition")

      For $WMI_PARTITION In $WMI_COL_PARTITIONS
         Local $WMI_COL_LOGICALDISKS = $WMI_GET.ExecQuery("ASSOCIATORS OF {Win32_DiskPartition.DeviceID='" & $WMI_PARTITION.DeviceID & "'} WHERE AssocClass = Win32_LogicalDiskToPartition")

         For $WMI_LOGICALDISK In $WMI_COL_LOGICALDISKS
            If FileExists($WMI_LOGICALDISK.DeviceID & "\Windows\explorer.exe") Then
               Local $STR_RESULT = $WMI_LOGICALDISK.DeviceID
            EndIf
         Next

      Next

   Next

   $WMI_GET = 0
   $WMI_COL_DRIVES = 0
   $WMI_DRIVE = 0
   $WMI_COL_PARTITIONS = 0
   $WMI_PARTITION = 0
   $WMI_LOGICALDISKS = 0
   $WMI_LOGICALDISK = 0

   Return SetError(0, 64, $STR_RESULT)
EndFunc ; ==>GetWindowsDrive()

 

Edited by doestergaard

Share this post


Link to post
Share on other sites



#2 ·  Posted (edited)

It's a good idea to declare your vars first, especially with WMI and loops --

or else you wind up having AutoIt errors like:

"Error: Variable used without being declared"

when a property is not found.

 

And you are right, there are several ways...

Local $rtn = Example()
MsgBox(0, '', $rtn)
Exit

Func Example()
    Local $objWMI = ObjGet('winmgmts:\\.\root\CIMV2')
    Local $objClass = $objWMI.InstancesOf('Win32_OperatingSystem')
    If Not IsObj($objClass) Then Return -1; invalid object
    If Not $objClass.Count Then Return -2; nothing found

    For $objItem In $objClass
       Return $objItem.WindowsDirectory
    Next
EndFunc

 

I personally would use the @WindowsDir macro.

 

Edited by ripdad

"The mediocre teacher tells. The Good teacher explains. The superior teacher demonstrates. The great teacher inspires." -William Arthur Ward

Share this post


Link to post
Share on other sites

It's a good idea to declare your vars first, especially with WMI and loops --

or else you wind up having AutoIt errors like:

"Error: Variable used without being declared"

when a property is not found.

 

And you are right, there are several ways...

Local $rtn = Example()
MsgBox(0, '', $rtn)
Exit

Func Example()
    Local $objWMI = ObjGet('winmgmts:\\.\root\CIMV2')
    Local $objClass = $objWMI.InstancesOf('Win32_OperatingSystem')
    If Not IsObj($objClass) Then Return -1; invalid object
    If Not $objClass.Count Then Return -2; nothing found

    For $objItem In $objClass
       Return $objItem.WindowsDirectory
    Next
EndFunc

 

I personally would use the @WindowsDir macro.

 

Forgot to mention that the script was intended for use in Windows PE. The Win32_OperatingSystem class will only work on the current running OS. I haven't tried running use the macro you are suggesting, but my guess is that the same thing will happen.

Share this post


Link to post
Share on other sites

Yes, that would change things a bit.

Guess I would do it something like this, providing there is only

one Windows installation and the folder name is Windows...

Local $rtn = Example()
If @error Then
    MsgBox(0, '', 'An Error Occurred')
Else
    MsgBox(0, '', $rtn)
EndIf

Func Example()
    Local $array = DriveGetDrive('FIXED')
    If IsArray($array) Then
        For $i = 1 To $array[0]
            If FileExists($array[$i] & '\Windows\Explorer.exe') Then
                Return StringUpper($array[$i]) & '\Windows'
            EndIf
        Next
    EndIf
    Return SetError(1)
EndFunc

 


"The mediocre teacher tells. The Good teacher explains. The superior teacher demonstrates. The great teacher inspires." -William Arthur Ward

Share this post


Link to post
Share on other sites

Thats exactly the problem i am trying to solve, what if there is more than one? Maybe you can throw in a counter that does increment by 1, and if the counter is above 1 then display a window where the user must select what drive to use to proceed, at least thats what im aiming at.

I've just used this method, because it proved to be working so far. But if there is a proper way to do it im all ears. I ended up using WMI because i think it is cool, and that way i can even filter out, what disk and partition Windows was found on.

 

Thanks Again for you contribution, it is always cool to learn new stuff :)

 

Share this post


Link to post
Share on other sites

#6 ·  Posted (edited)

You could also use DISM (or imagex)  with the windir parameter or get-wiminfo if you are going in blind.   Because from what i am understanding, you know a wim has been deployed, you just dont know the location of windir..

Edited by boththose

,-. .--. ________ .-. .-. ,---. ,-. .-. .-. .-.
|(| / /\ \ |\ /| |__ __||| | | || .-' | |/ / \ \_/ )/
(_) / /__\ \ |(\ / | )| | | `-' | | `-. | | / __ \ (_)
| | | __ | (_)\/ | (_) | | .-. | | .-' | | \ |__| ) (
| | | | |)| | \ / | | | | | |)| | `--. | |) \ | |
`-' |_| (_) | |\/| | `-' /( (_)/( __.' |((_)-' /(_|
'-' '-' (__) (__) (_) (__)

Share this post


Link to post
Share on other sites

#7 ·  Posted (edited)

@boththose

Thanks for your reply. Image has not been deployed yet. If a user / administrator choose to leave the hard drive(s) untouched, the script should look for and detect where Windows is installed.

So far, I've been using this, which I created myself:

Example:

Opt("MustDeclareVars", 1)

Local $STR_RETURN = GetDiskAndPartition()

If $STR_RETURN Then

   Local $ARR_RESULT = StringSplit($STR_RETURN, ",")

   Local Const $STR_DRIVE = $ARR_RESULT[1]
   Local Const $INT_DISK = StringRegExpReplace($ARR_RESULT[2], "\D", "")
   Local Const $INT_PARTITION = StringRegExpReplace($ARR_RESULT[3], "\D", "")

   MsgBox(64, "Result", "Windows was found on drive '" & $STR_DRIVE & "' and is located at: Disk #" & $INT_DISK & ", Partition #" & $INT_PARTITION, 0)
   Exit
Else
   MsgBox(16, "Result", "Error: Could not detect", 0)
EndIf

Exit


Func GetDiskAndPartition()
   Local $WMI_GET = ObjGet("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2")
   If Not IsObj($WMI_GET) Then Return SetError(1, 16, "Invalid object")

   Local $WMI_COL_DRIVES = $WMI_GET.ExecQuery("SELECT DeviceID FROM Win32_DiskDrive WHERE MediaType='Fixed hard disk media'")

   For $WMI_DRIVE In $WMI_COL_DRIVES
      Local $WMI_COL_PARTITIONS = $WMI_GET.ExecQuery("ASSOCIATORS OF {Win32_DiskDrive.DeviceID='" & $WMI_DRIVE.DeviceID & "'} WHERE AssocClass = Win32_DiskDriveToDiskPartition")

      For $WMI_PARTITION In $WMI_COL_PARTITIONS
         Local $WMI_COL_LOGICALDISKS = $WMI_GET.ExecQuery("ASSOCIATORS OF {Win32_DiskPartition.DeviceID='" & $WMI_PARTITION.DeviceID & "'} WHERE AssocClass = Win32_LogicalDiskToPartition")

         For $WMI_LOGICALDISK In $WMI_COL_LOGICALDISKS
            If FileExists($WMI_LOGICALDISK.DeviceID & "\Windows\explorer.exe") Then

               Local $STR_RESULT = $WMI_LOGICALDISK.DeviceID & "\," & $WMI_PARTITION.Caption

            EndIf

         Next



      Next



   Next



   $WMI_GET = 0
   $WMI_COL_DRIVES = 0
   $WMI_DRIVE = 0
   $WMI_COL_PARTITIONS = 0
   $WMI_PARTITION = 0
   $WMI_COL_LOGICALDISKS = 0
   $WMI_LOGICALDISK = 0

   If $STR_RESULT = "\" Then Return False
   Return $STR_RESULT
EndFunc ; ==>GetWindowsDrive()

I am filtering out the disk and partition number as the results found is used to create a disk part txt file.

Edited by doestergaard

Share this post


Link to post
Share on other sites

#8 ·  Posted (edited)

 the script should look for and detect where Windows is installed.

but 

 Image has not been deployed yet

Does it hurt when you read that?

If its vista or higher, whatever is there can be interrogated with imagex

Edited by boththose

,-. .--. ________ .-. .-. ,---. ,-. .-. .-. .-.
|(| / /\ \ |\ /| |__ __||| | | || .-' | |/ / \ \_/ )/
(_) / /__\ \ |(\ / | )| | | `-' | | `-. | | / __ \ (_)
| | | __ | (_)\/ | (_) | | .-. | | .-' | | \ |__| ) (
| | | | |)| | \ / | | | | | |)| | `--. | |) \ | |
`-' |_| (_) | |\/| | `-' /( (_)/( __.' |((_)-' /(_|
'-' '-' (__) (__) (_) (__)

Share this post


Link to post
Share on other sites

#9 ·  Posted (edited)

I dont know what you mean by "Does it hurt when i read that?" :P

A lot of Pc's comes with Windows preinstalled, so I think it makes sense that you should have the option choose whether or not you want to format the entire drive.

Another scenario would be that you have more than one physical drive installed, for ex. backup purposes. IMHO me, its a critical step that my script selects the right disk and partition to avoid deleting the wrong files :)

Edited by doestergaard

Share this post


Link to post
Share on other sites

This should be more robust and do what you expect.

#include 'Array.au3'

Local $a = Example()
If @error Or Not IsArray($a) Then
    MsgBox(0, '', 'An Error Occurred')
Else
    _ArrayDisplay($a)
    ;-----------------------------------------------------
    If $a[0] > 1 Then; <-- test
        MsgBox(0, '', 'Found more than one installation!')
        ; <-- additional code here to handle this event
    EndIf
    ;-----------------------------------------------------
EndIf

Func Example()
    Local $sDrive, $hFile, $sFolder, $str = ''
    Local $array = DriveGetDrive('FIXED')
    ;
    If IsArray($array) Then
        For $i = 1 To $array[0]
            $sDrive = StringUpper($array[$i])
            $hFile = FileFindFirstFile($sDrive & '\*')
            If $hFile = -1 Then ContinueLoop
            ;
            While 1
                $sFolder = FileFindNextFile($hFile); enum all root folders on drive
                If @error Then
                    ExitLoop
                ElseIf @extended Then
                    If FileExists($sDrive & '\' & $sFolder & '\System32\Config') Then
                        $str &= '|' & $sDrive & '\' & $sFolder
                    EndIf
                EndIf
            WEnd
            FileClose($hFile)
        Next
    EndIf
    ;
    If StringLen($str) Then
        $str = StringTrimLeft($str, 1)
        Return StringSplit($str, '|')
    Else
        Return SetError(1)
    EndIf
EndFunc

 


"The mediocre teacher tells. The Good teacher explains. The superior teacher demonstrates. The great teacher inspires." -William Arthur Ward

Share this post


Link to post
Share on other sites

DISM would fail when there is no target, just as FileExists fails when there is no file, expectedly. 

You could also loop C: to Z: running just the If fileexists line and it may be faster?  If it is a brand new OEM box you could also read the panther logs. 


,-. .--. ________ .-. .-. ,---. ,-. .-. .-. .-.
|(| / /\ \ |\ /| |__ __||| | | || .-' | |/ / \ \_/ )/
(_) / /__\ \ |(\ / | )| | | `-' | | `-. | | / __ \ (_)
| | | __ | (_)\/ | (_) | | .-. | | .-' | | \ |__| ) (
| | | | |)| | \ / | | | | | |)| | `--. | |) \ | |
`-' |_| (_) | |\/| | `-' /( (_)/( __.' |((_)-' /(_|
'-' '-' (__) (__) (_) (__)

Share this post


Link to post
Share on other sites

#12 ·  Posted (edited)

Share this post


Link to post
Share on other sites

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 account

Sign in

Already have an account? Sign in here.


Sign In Now

  • Similar Content

    • ModemJunki
      By ModemJunki
      Hello,
      I'm working in Windows PE environment (10.0.10586). I think I have some permissions issue related to AutoIT
      I've tried with Net Share and with DriveMapAdd - neither work.
      So finally I made the script output a batch file with a pause and what I found is that in WinPE, the batch file behaves differently if it's run at the command prompt or if it is spawned by AutoIT.
      If spawned by AutoIT, the net use command gives error 1231 "The network location cannot be reached". I assume this is the same problem that DriveMapAdd is having.
      But if I run the same batch file under the command shell in the Windows PE instance, it works.
      I also made a simple test with Ping() and it always returns 1 (host is offline) but I can ping it from the command line in the same PE session.
      Are there service dependencies for this to work? What is preventing AutoIT from accessing the network?
      Below sample is kind of dirty but illustrates what I'm doing.
      #RequireAdmin #include <Array.au3> ;~ #include <AutoItConstants.au3> $s_user = "USER" $s_pass = "PASS" _SetUpPEIP() Func _SetUpPEIP() Local $s_RMTIP = "10.1.1.4" Local $s_RMTSHR = "SHARED_FOLDER" Local $s_Mapbat = "X:\MapShare.bat" Local $s_IPPrefix = "10.1.1." Local $s_netMask = "255.255.255.0" Local $s_StartIP = 20 Local $a_NICs[1] Local $objWMIService = ObjGet("winmgmts:\\localhost\root\CIMV2") Local $colItems = $objWMIService.ExecQuery("SELECT * FROM Win32_NetworkAdapter", "WQL") If IsObj($colItems) Then ; gather network card names For $objItem In $colItems If $objItem.NetConnectionStatus == "2" Or $objItem.NetConnectionStatus == "9" Then _ArrayAdd($a_NICs, $objItem.NetConnectionID) EndIf Next EndIf If IsArray($a_NICs) Then ; assign them I.P. addresses For $i = 1 To UBound($a_NICs) - 1 $s_setIP = "netsh interface IP set address name=""" & $a_NICs[$i] & """ static " & $s_IPPrefix & $i + $s_StartIP - 1 & " " & $s_netMask $s_ipRes = RunWait(@ComSpec & " /c " & $s_setIP, @ScriptDir, @SW_HIDE) ; expect 0 Sleep(100) ConsoleWrite($s_setIP & " result is: " & $s_ipRes & @CRLF) Next ; now map a drive $s_mapDrv = "net use Z: \\" & $s_RMTIP & "\" & $s_RMTSHR & " /user:" & $s_user & " " & $s_pass & " /y" $OpenMapFile = FileOpen($s_Mapbat, 2) FileWriteLine($OpenMapFile, $s_mapDrv) FileWriteLine($OpenMapFile, "pause") FileClose($OpenMapFile) ;~ $s_mapRes = RunWait(@ComSpec & " /c " & $s_Mapbat, @ScriptDir) ; expect 0 $s_mapRes = ShellExecuteWait($s_Mapbat, "", @ScriptDir) ; expect 0 ConsoleWrite("result of " & $s_mapDrv & " is: " & $s_mapRes & " extended code is " & @error & @CRLF) Else ; error! No cards found! EndIf EndFunc ;==>_SetUpPEIP  
    • mdwerne
      By mdwerne
      I'm attempting to cobble together a replacement for the 64bit version of BGInfo that will run within WinPE 10/64. I've located a couple useful threads:
       Between the two, they get me close (see code below), but for some reason GDI+ is not working the same within WinPE as it does in Windows 10. Bottomline is that the "Text" never get's written to WallPaper.
      Here is what I have thus far. Any thoughts if any of the GDI commands might not work within WinPE? Any other way to achieve the same result (system information on the wallpaper in WinPE 10)?
      #include <GDIPlus.au3> #include <Date.au3> _GDIPlus_Startup() $image = _GDIPlus_ImageLoadFromFile(@ScriptDir & "\WallPaper.bmp") $imagegraphics = _GDIPlus_ImageGetGraphicsContext($image) $w = _GDIPlus_ImageGetWidth($image) $h = _GDIPlus_ImageGetHeight($image) $whitebrush = _GDIPlus_BrushCreateSolid(0xFFFFFFFF) $fontfamily = _GDIPlus_FontFamilyCreate("Arial") $font = _GDIPlus_FontCreate($fontfamily, 16) $stringformat = _GDIPlus_StringFormatCreate() _GDIPlus_StringFormatSetAlign($stringformat, 2) $rect = _GDIPlus_RectFCreate(0, $h - $h + 100, $w - 25, $h) ;$rect = _GDIPlus_RectFCreate(100, 100, 200, 200) _GDIPlus_GraphicsDrawStringEx($imagegraphics, _Now() & @CRLF & @UserName & @CRLF & @ComputerName & @CRLF & @IPAddress1, $font, $rect, $stringformat, $whitebrush) _GDIPlus_ImageSaveToFile($image, @ScriptDir & "\NewWallPaper.bmp") _GDIPlus_ImageDispose($image) _GDIPlus_GraphicsDispose($imagegraphics) _GDIPlus_BrushDispose($whitebrush) _GDIPlus_FontFamilyDispose($fontfamily) _GDIPlus_FontDispose($font) _GDIPlus_StringFormatDispose($stringformat) _GDIPlus_Shutdown() _ChangeDesktopWallpaper(@ScriptDir & "\NewWallPaper.bmp", 2) Func _ChangeDesktopWallpaper($bmp, $style = 0) ;=============================================================================== ; ; Function Name: _ChangeDesktopWallPaper ; Description: Update WallPaper Settings ; Usage: _ChangeDesktopWallPaper(@WindowsDir & '\' & 'zapotec.bmp',1) ; Parameter(s): $bmp - Full Path to BitMap File (*.bmp) ; [$style] - 0 = Centered, 1 = Tiled, 2 = Stretched ; Requirement(s): None. ; Return Value(s): On Success - Returns 0 ; On Failure - -1 ; Author(s): FlyingBoz ; Thanks: Larry - DllCall Example - Tested and Working under XPHome and W2K Pro ; Excalibur - Reawakening my interest in Getting This done. ; ;=============================================================================== If Not FileExists($bmp) Then Return -1 ;The $SPI* values could be defined elsewhere via #include - if you conflict, ; remove these, or add if Not IsDeclared "SPI_SETDESKWALLPAPER" Logic Local $SPI_SETDESKWALLPAPER = 20 Local $SPIF_UPDATEINIFILE = 1 Local $SPIF_SENDCHANGE = 2 Local $REG_DESKTOP = "HKEY_CURRENT_USER\Control Panel\Desktop" If $style = 1 Then RegWrite($REG_DESKTOP, "TileWallPaper", "REG_SZ", 1) RegWrite($REG_DESKTOP, "WallpaperStyle", "REG_SZ", 0) Else RegWrite($REG_DESKTOP, "TileWallPaper", "REG_SZ", 0) RegWrite($REG_DESKTOP, "WallpaperStyle", "REG_SZ", $style) EndIf DllCall("user32.dll", "int", "SystemParametersInfo", _ "int", $SPI_SETDESKWALLPAPER, _ "int", 0, _ "str", $bmp, _ "int", BitOR($SPIF_UPDATEINIFILE, $SPIF_SENDCHANGE)) Return 0 EndFunc ;==>_ChangeDesktopWallpaper Thanks for your time,
      -Mike
    • MadDogVachon
      By MadDogVachon
      Hi everyone,
      Here is my script that does the job of the original BootSectGui. I wrote it because I needed a BootSectGui that works in WinPE x64 environment. The original works only in x86 envoronment. It is free to use, modify and distribute. I coded first in French and then in English, it may have some mistranslation.
      In the 7z attached file you have these files:
      BootSectGui - original - Main.png    ->  The original Main window of BootSectGui BootSectGui - original - Log.png     ->  The original Log window of BootSectGui BootSectGui - original.exe               ->  The original BooSectGui.exe program BootSectGui_x86_x64.au3              ->  My code BootSectGui_x86.exe                      ->  My program x86 version 1.3 BootSectGui_x64.exe                      ->  My program x64 version 1.3 BootSectGui_x86_x64 1.2.1.au3     ->  My code for 1.2.1 BootSectGui_x86 1.2.1.exe             ->  My program 1.2.1 x86 version
      BootSectGui_x64 1.2.1.exe             ->  My program 1.2.1 x64 version BootSectGui_x64 - Main.png          ->  My Main window
      BootSectGui_x64 - Log.png            ->  My Log window BootSectGui_x64 - Main 1.2.1.png  ->  My Main window 1.2.1
      BootSectGui.psd                             ->  My "code" for the ico files in Photoshop format BootSectGui BSG 64.ico                 ->  The icon used with my program, in 64 dots BootSectGui BSG 256.ico               ->  The same in 256 dots BootSectGui G BS 64.ico                ->  Another icon that looks more like the original one, in 64 dots BootSectGui G BS 256.ico              ->  The same in 256 dots Enjoy!
      MDV
      Here's the code:
      #RequireAdmin #region ;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_Icon=BootSectGui BSG 64.ico #AutoIt3Wrapper_Compile_Both=y #AutoIt3Wrapper_UseX64=y #AutoIt3Wrapper_Compression=4 #AutoIt3Wrapper_Res_Comment=New BootSectGui #AutoIt3Wrapper_Res_Description=New BootSectGui that works in WinPE x86 and x64 #AutoIt3Wrapper_Res_Fileversion=1.3 #AutoIt3Wrapper_Res_SaveSource=y #AutoIt3Wrapper_Run_Obfuscator=y #Obfuscator_Parameters=/sf /sv /om /cs=0 /cn=0 #AutoIt3Wrapper_Run_After=del /f /q "%scriptdir%\%scriptfile%_Obfuscated.au3" #endregion ;**** Directives created by AutoIt3Wrapper_GUI **** #cs ---------------------------------------------------------------------------- AutoIt Version: 3.3.8.1 Author: MadDogVachon Script Function: A Gui for BootSect that work in WinPE x64 environment (also in WinPE x86 and Windows x86 x64) Thanks to AZJIO for the improvement of my code! #ce ---------------------------------------------------------------------------- #include <GuiConstantsEx.au3> #include <Constants.au3> #include <GuiEdit.au3> #include <GuiConstantsEx.au3> #include <ComboConstants.au3> #include <WindowsConstants.au3> Opt('MustDeclareVars', 1) Local $Title = "BootSectGui - AutoIt3", $sPathBootSect, $sDriveSelectionItems, $sDriveSelectionFirst, $sBootCode, $sp ; GUI + ID Local $hBootSectGuiMain, $msg, $iSingleDrive, $iAllDrives, $iSYSDrive, $iNT60, $iNT52, $iMBRYesNo, $iForceYesNo, $iDriveSelection, $iBtnWrite, $iQuit If FileExists(@WorkingDir & "\bootsect.exe") Then $sPathBootSect = @WorkingDir & "\bootsect.exe" ElseIf FileExists(@ScriptDir & "\bootsect.exe") Then $sPathBootSect = @ScriptDir & "\bootsect.exe" ElseIf FileExists(@SystemDir & "\bootsect.exe") Then $sPathBootSect = @SystemDir & "\bootsect.exe" ElseIf FileExists(@WindowsDir & "\bootsect.exe") Then $sPathBootSect = @WindowsDir & "\bootsect.exe" Else MsgBox(16 + 262144, $Title, "The necessary 'BootSect.exe' file not found!" & @CRLF & @CRLF & "The program will end now!") Exit EndIf ;Main Menu $hBootSectGuiMain = GUICreate($Title, 525, 175) Local $GuiX = 18, $GuiY = 20 ; Group Drive(s) GUICtrlCreateGroup("Write master boot code into", $GuiX, $GuiY, 189, 130) $iAllDrives = GUICtrlCreateRadio("All Drives", $GuiX + 15, $GuiY + 20, 80) $iSingleDrive = GUICtrlCreateRadio("Single Drive:", $GuiX + 15, $GuiY + 45, 80) GUICtrlSetState(-1, $GUI_CHECKED) ; ================================= $sp = Chr(1) Opt("GUIDataSeparatorChar", $sp) $sDriveSelectionItems = _GetDrv() If Not $sDriveSelectionItems Then ; An error occurred when retrieving the drives. MsgBox(4096, $Title, "Error on querying drives" & @CRLF & @CRLF & "The program will end now!") Exit EndIf $sDriveSelectionFirst = StringRegExp($sDriveSelectionItems, '(?:\A|\001)([C-Z]: Fixed.*?)(?=\001)', 1) If @error Then $sDriveSelectionFirst = StringLeft($sDriveSelectionItems, StringInStr($sDriveSelectionItems & $sp, $sp) - 1) Else $sDriveSelectionFirst = $sDriveSelectionFirst[0] EndIf $iDriveSelection = GUICtrlCreateCombo("", $GuiX + 15, $GuiY + 70, 160, 25, $WS_VSCROLL + $CBS_DROPDOWNLIST) GUICtrlSetFont(-1, -1, -1, 0, "Courier New") GUICtrlSendMsg(-1, 0x160, 370, 0) GUICtrlSetData(-1, $sDriveSelectionItems, $sDriveSelectionFirst) ; ================================= $iSYSDrive = GUICtrlCreateRadio("System Drive", $GuiX + 15, $GuiY + 95, 80) GUICtrlCreateGroup("", -99, -99, 1, 1) ;close group $GuiX += 205 ; Group Windows version GUICtrlCreateGroup("Select master boot code version", $GuiX, $GuiY, 185, 80) $iNT60 = GUICtrlCreateRadio("Windows Vista/7/8 ""/NT60""", $GuiX + 15, $GuiY + 20, 160) GUICtrlSetState(-1, $GUI_CHECKED) $iNT52 = GUICtrlCreateRadio("Windows XP ""/NT52""", $GuiX + 15, $GuiY + 45, 130) GUICtrlCreateGroup("", -99, -99, 1, 1) ;close group $GuiX += 200 ; Group Master Boot Record GUICtrlCreateGroup("Options", $GuiX, $GuiY, 85, 80) $iMBRYesNo = GUICtrlCreateCheckbox("MBR", $GuiX + 15, $GuiY + 20, 60) GUICtrlSetState(-1, $GUI_CHECKED) $iForceYesNo = GUICtrlCreateCheckbox("Force", $GuiX + 15, $GuiY + 45, 60) GUICtrlCreateGroup("", -99, -99, 1, 1) ;close group ; Group Button Local $ButtonX = 18 + 205 + 17, $ButtonY = $GuiY + 95 $iBtnWrite = GUICtrlCreateButton("Write master boot code", $ButtonX, $ButtonY, 150, 40) $iQuit = GUICtrlCreateButton("Quit", $ButtonX + 183, $ButtonY, 85, 40) GUICtrlSetState(-1, $GUI_FOCUS) ; the focus is on this button GUISetState() ; Run the GUI until the dialog is closed While 1 Switch GUIGetMsg() Case $iBtnWrite If GUICtrlRead($iNT60) = $GUI_CHECKED Then $sBootCode = "/NT60" ElseIf GUICtrlRead($iNT52) = $GUI_CHECKED Then $sBootCode = "/NT52" EndIf If GUICtrlRead($iSingleDrive) = $GUI_CHECKED Then BootSectLog(StringLeft(GUICtrlRead($iDriveSelection), 2)) ElseIf GUICtrlRead($iAllDrives) = $GUI_CHECKED Then BootSectLog("All") Else BootSectLog("SYS") EndIf Case $iSingleDrive GUICtrlSetState($iDriveSelection, $GUI_ENABLE) Case $iAllDrives, $iSYSDrive GUICtrlSetState($iDriveSelection, $GUI_DISABLE) Case $GUI_EVENT_CLOSE, $iQuit Exit EndSwitch WEnd Func BootSectLog($sBootSectDrive) Local $hBootSectGuiLog, $iPID, $sBootSectInProgress, $iBootSectLog, $sLine, $iWidth = 530, $iHeight = 330, $iClose, $sMBR, $sForce If GUICtrlRead($iMBRYesNo) = $GUI_CHECKED Then $sMBR = " /mbr" If GUICtrlRead($iForceYesNo) = $GUI_CHECKED Then $sForce = " /force" $iPID = Run(@ComSpec & ' /c "' & $sPathBootSect & '" ' & $sBootCode & " " & $sBootSectDrive & $sMBR & $sForce, @ScriptDir, @SW_HIDE, $STDOUT_CHILD) $sBootSectInProgress = "Executing:" & @CRLF & " Bootsect " & $sBootCode & " " & $sBootSectDrive & $sMBR & $sForce & @CRLF & @CRLF & "--------------------------------------------------------------------------------" GUISetState(@SW_DISABLE, $hBootSectGuiMain) $hBootSectGuiLog = GUICreate("BootSect Log", $iWidth, $iHeight, -1, -1, $WS_CAPTION + $WS_SYSMENU + $WS_POPUP, -1, $hBootSectGuiMain) $iBootSectLog = GUICtrlCreateEdit($sBootSectInProgress, 2, 2, $iWidth, $iHeight - 60) $iClose = GUICtrlCreateButton("Close", $iWidth / 2 - 148, $iHeight - 38, 295, 30) GUICtrlSetState(-1, $GUI_DISABLE) ; Disable "Close" button GUISetState(@SW_SHOW, $hBootSectGuiLog) _GUICtrlEdit_AppendText($iBootSectLog, @CRLF) ; Add space While 1 $sLine = StdoutRead($iPID) If @error Then ExitLoop If $sLine Then _GUICtrlEdit_AppendText($iBootSectLog, @CRLF & $sLine) WEnd _GUICtrlEdit_AppendText($iBootSectLog, @CRLF & "--------------------------------------------------------------------------------" & @CRLF & @CRLF & "Bootsect has terminated itself") GUICtrlSetState($iClose, $GUI_ENABLE) ; Enable "Close" button While 1 $msg = GUIGetMsg() If $msg = $GUI_EVENT_CLOSE Or $msg = $iClose Then GUISetState(@SW_ENABLE, $hBootSectGuiMain) GUIDelete($hBootSectGuiLog) ExitLoop EndIf WEnd EndFunc ;==>BootSectLog Func _GetDrv() Local $sInfo = _ComboListDrive('Fixed') $sInfo &= _ComboListDrive('Removable') Return StringTrimLeft($sInfo, 1) EndFunc ;==>_GetDrv Func _ComboListDrive($Type) ; coded by AZJIO (2013.01.26) Local $aDrive = DriveGetDrive($Type), $list = '', $sString, $sLabel If @error Then Return '' If $Type = 'Removable' Then $Type = 'Rem' For $i = 1 To $aDrive[0] If $aDrive[$i] = 'A:' Then ContinueLoop $sLabel = DriveGetLabel($aDrive[$i]) If StringLen($sLabel) > 15 Then $sLabel = StringLeft($sLabel, 12) & '...' $sString = StringFormat("%-2s %-5s %-15s %-5s ", StringUpper($aDrive[$i]), $Type, $sLabel, _ DriveGetFileSystem($aDrive[$i])) & _GetSize(DriveSpaceTotal($aDrive[$i])) & ' Gb' $list &= $sp & $sString Next Return $list EndFunc ;==>_ComboListDrive Func _GetSize($s) ; coded by AZJIO $s = StringFormat('%.03f', $s / 1024) If StringLen($s) > 7 Then $s = StringRegExpReplace(StringTrimRight($s, 4), '(\A\d{1,3}(?=(\d{3})+\z)|\d{3}(?=\d))', '\1 ') & StringRight($s, 4) Return StringFormat('%9s', $s) ; 9 ???????? EndFunc ;==>_GetSize - - - - -
      Edit 1: Corrected mistype in topic title, updated code with JFX recommendation and updated BootSectGui_x64 - Main.png with the new code. Version 1.1
      Edit 2: Added /mbr (by default). Corrected the line to execute bootsect.exe using the variable $BootSect. Version 1.1.1
      Edit 3: Added /force. Corrected a bug when not founding boosect.exe. Added SYS (system drive) in the list. Updated BootSectGui_x64 - Main.png, BootSectGui_x64 - Log.png and exe files. Version 1.2
      Edit 4: Added improvement by AZJIO and updated files. Version 1.3
      Edit 5: Little update of code added version 1.2.1 with improvement of AZJIO and a simple list of drives.
      BootSectGui_x64.7z
    • Tripredacus
      By Tripredacus
      I've been getting reports from manufacturing that some of our applications have been generating an error, such as:

      AUTOIT ERROR LINE 1165(X:\windows\system32\program.exe) ERROR: Subscript used w/ non-array variable