Sign in to follow this  
Followers 0
cherdeg

Auto-Create Partitions

12 posts in this topic

Hi there!

Is there a way to do the following (pseudo-code):

Get Number of Harddisks
If Number of Harddisks = 1 Then
    Create 2nd Partition on Harddisk#1 using all free space
    Format new Partition
Else
    For $i=0 to Number of Harddisks
        If current Harddisk is Harddisk#1 Then
            Do Nothing
        Else
            Create Partition on current Harddisk using all free space
            Format new Partition
        EndIf
    Next
Endif

So in words: I need a tool to prepare all harddisks within a system automatically. On the 1st disk shall be two partitions: an already existing system partition and a second partition containing all the free space left on the drive. All other disks shall get one single partition. All newly created partitions shall be formatted.

I looked at the thread about "diskpart-automation", but couldn't adapt it to my purpose...any ideas?

Regards,

Chris

Share this post


Link to post
Share on other sites



Take a look at gdisk. It is a Norton tool, part of Ghost. If you are booting to a Bart CD, you can run your script from there. If you are laying a image onto a PC, then you can configure Ghost to do this when you image with command line switches.

Sorry, but using more than Windows own tools is no option. And no, the script is not intended to run from Windows PE but any full version from W2K and later.

Share this post


Link to post
Share on other sites

Ok, before we go further, I need to ask a important question:

Is the reason you can only use Windows only tools is for:

1. The company you work for.

2. Cost - you have no money for software.

3. Both 1 and 2

Once I know the reason, I can direct you further. There are a few options depending on your environment.

All other disks shall get one single partition

Are you wanting to setup a raid if the computer has multiple drives?

Is Windows ALREADY installed? From your response, I take it as yes, and you wish to reconfigure the RAID or reconfigure the drives. Is this just for your PC, or many PCs?

Again, to answer your question, need to know more about your environment.

Share this post


Link to post
Share on other sites

I would suggest looking at the diskpart automation again.

I currently use a batch script, wrapped in a larger Autoit script to do partitioning and formatting of drives for testing.

In my environment we start with raw drives and need to add 3 partitions to 2 different drives, (Windows WHQL driver testing), but I've been playing around with that Diskpart automation to see if that would work better with the different requirements from SATA and SAS drives. (2 partitions and one mirrored partition across two drives)

Kerros


Kerros===============================================================How to learn scripting: Figure out enough to be dangerous, then ask for assistance.

Share this post


Link to post
Share on other sites

1. The company you work for.

2. Cost - you have no money for software.

3. Both 1 and 2

Hi again, Volly - thanks for your time so far! It's quite a pity, but the answer would be "Both 1 and 2".

Are you wanting to setup a raid if the computer has multiple drives?

Nope. Either the hosts have one or more single disks or one or more hardware RAID volumes.

Is Windows ALREADY installed? From your response, I take it as yes, and you wish to reconfigure the RAID or reconfigure the drives. Is this just for your PC, or many PCs?

Yep, Windows is already installed on the 1st partition of the 1st drive. Nope, I do not want to reconfugure RAID volumes. I simply want to create partitions after the scheme layed out in my OP. This is for many hosts but there is no need to do it remotely (which nevertheless would be cool to know about).

I have to manage about 450 machines whose purpose is to be used as testbed systems for software development. I'm building a utility to automate all the post-installation-tasks required to get the machines compliant to company policies as well as ready for the customers to use 'em as test systems. The tool will run locally on every single machine under administrative privileges.

Enough info?

Share this post


Link to post
Share on other sites

#8 ·  Posted (edited)

I currently use a batch script, wrapped in a larger Autoit script to do partitioning and formatting of drives for testing.

In my environment we start with raw drives and need to add 3 partitions to 2 different drives, (Windows WHQL driver testing), but I've been playing around with that Diskpart automation to see if that would work better with the different requirements from SATA and SAS drives. (2 partitions and one mirrored partition across two drives)

I know both the links and of course, I know diskpart. But I don't have the time to reinvent the wheel. Please, if you know how to do it, drop me an example for my task definition.

Edited by cherdeg

Share this post


Link to post
Share on other sites

I would suggest looking at the diskpart automation again.

I currently use a batch script, wrapped in a larger Autoit script to do partitioning and formatting of drives for testing.

In my environment we start with raw drives and need to add 3 partitions to 2 different drives, (Windows WHQL driver testing), but I've been playing around with that Diskpart automation to see if that would work better with the different requirements from SATA and SAS drives. (2 partitions and one mirrored partition across two drives)

Kerros

Hello Kerros!

If you got a working solution, would you mind letting please me take part in it?

Regards, Chris

Share this post


Link to post
Share on other sites

Chris

Here is the code that I use for the batch file, I've been playing around with the Diskpart automation as I would like to be able to have a little more control then what is offered by the batch file.

In this example it will find a drive that is not completely used and create a partition on it. It currently does NOT do multiple drives.

Kerros

Copy into a bat file and run with admin rights.

@echo off

echo list disk > listdisk.txt

diskpart /s listdisk.txt > disks.txt

rem ====================================================================================================

=========
rem = Parse the file to determine which version of DiskPart is being used. This is necessary as different
rem = versions write the information differently to the files.
rem ====================================================================================================

=========
for /f "tokens=1-9" %%A in (disks.txt) do (set ver=%%D && goto test)

:test
 if %ver%==5.1.3565 set ver=XP && set count=8
 if %ver%==5.2.3790.1830 set ver=2K3 && set count=7
 if %ver%==1.0 set ver=xpsp1 && set count=7
 if %ver%==6.0.6000 set ver=vista && set count=7
for /f "skip=%count% tokens=6" %%A in (disks.txt) do (set diska=%%A && goto disk1)

:disk1
set /a count=%count%+1
for /f "skip=%count% tokens=6" %%B in (disks.txt) do (set diskb=%%B && goto selectdisk)

:selectdisk
set sel=none
if %diska% GTR 0 set sel=0
if %diskb% GTR 0 set sel=1
if %sel% EQU none goto none_available

echo select disk %sel% > part.txt
echo create partition primary >> part.txt
echo assign >> part.txt

diskpart /s part.txt
format d: /FS:NTFS /q /v:D: /y 
goto :cleanup

:cleanup
if exist disks.txt del disks.txt
if exist part.txt del part.txt
if exist listdisk.txt del listdisk.txt
exit

:none_available
Echo No disk available. Exiting
pause
goto :cleanup

Kerros===============================================================How to learn scripting: Figure out enough to be dangerous, then ask for assistance.

Share this post


Link to post
Share on other sites

Ahhh...okay...that easy...so I WILL reinvent the wheel...Kerros: thank you VERY MUCH!!!

Share this post


Link to post
Share on other sites

#12 ·  Posted (edited)

Ahhh...okay...that easy...so I WILL reinvent the wheel...Kerros: thank you VERY MUCH!!!

Okay, here finally is that f***ing wheel (sorry for the delay, I had to do another tool ("Install-Update-on-many-remote-Machines-at-once") first). This does the following tasks:

- Identify the system drive and system partition

- Check if there is space for a second partition on the system drive

- Change the drive letters of optical and removable drives

- Check for empty hard drives

- If above Yes, Create a second partition on the systen drive

- Create partitions on empty drives

- Format the newly created partitions

- Assign drive letters to the new volumes

- Rename the volume names of all drives from e.g. "Local Volume" to "HD0-System" or "HD1-Data"

And here the code:

;####################################################################
;#
;#  Christoph Herdeg, November 2008
;#  http://www.cs-it-solutions.de
;#
;####################################################################


; ----------------------------------------------------------------------------------------------------------------
; Define the include files
#include <Array.au3>
#include <file.au3>

; ----------------------------------------------------------------------------------------------------------------
; Variables
Local $s_SystemDriveLetter
Local $s_AssignedDriveLetter
Local $s_SystemPartitionID
Local $s_SystemDeviceID
Local $i_SystemDeviceSize
Local $i_SystemPartitionSize
Local $i_NumberOfPartitions
Local $a_DriveDetails[1][3]

Local $wbemFlagReturnImmediately    = 0x10
Local $wbemFlagForwardOnly          = 0x20
Local $h_wbemFlags                  = $wbemFlagReturnImmediately + $wbemFlagForwardOnly
Local $s_ComputerName               = @ComputerName
Local $s_TagContent                 = "%PHYSICALDRIVE%"
Local $s_DriveDelimiter             = "%:"
Local $i_Counter                    = 0

Global $s_SystemTempHome            = @TempDir
Global $s_DiskpartCommandsFile      = $s_SystemTempHome & "\" & "commands.txt"


; ----------------------------------------------------------------------------------------------------------------
; Set the WMI-Service
$o_WMIService                       = ObjGet("winmgmts:\\" & $s_ComputerName & "\root\CIMV2")


; ----------------------------------------------------------------------------------------------------------------
; First of all the DriveLetters of optical and removable drives are renamed
; out of the way, starting with "O:" for optical and "R:" for removable drives. 
; Using this convention it would be possible to have up to six ptical and 
; removable drives in one system, wich should happen quite seldom. Also it
; would be possible to have up to 17 logical volumes in a system (drives C:
; through T:).
;
; 1st get arrays of WMI objects this could be simplified into one array pro-
; vided with another column containing the "Descriptions" ('CD-ROM Disc' and 
; 'Removalbe Disk').
$o_OpticalDrives    = $o_WMIService.ExecQuery("SELECT * FROM Win32_LogicalDisk WHERE Description = 'CD-ROM Disc'", "WQL", $h_wbemFlags)
$o_RemovableDrives  = $o_WMIService.ExecQuery("SELECT * FROM Win32_LogicalDisk WHERE Description = 'Removable Disk'", "WQL", $h_wbemFlags)

; 2nd create the arrays containing the GUIDs and their DriveLetters
;
; ...for Optical Drives
Global $a_OpticalDriveList[1][2]
For $o_items in $o_OpticalDrives
    $s_DriveLetter = $o_items.Caption
    Local $a_TempAdd[2] = [$s_DriveLetter, _FindGUID($s_DriveLetter)]
    _2DArrayAdd($a_OpticalDriveList, $a_TempAdd, False)
Next
_ArrayDelete($a_OpticalDriveList, 0)

; ...and then the Removable Disks
Global $a_RemovableDriveList[1][2]
For $o_items in $o_RemovableDrives
    $s_DriveLetter = $o_items.Caption
    Local $a_TempAdd[2] = [$s_DriveLetter, _FindGUID($s_DriveLetter)]
    _2DArrayAdd($a_RemovableDriveList, $a_TempAdd, False)
Next
_ArrayDelete($a_RemovableDriveList, 0)


; 3rd change the driveletters
; Due to the fact that optical drives usually get the drive letter "D:" after
; the base operating system installation, they must be "moved" first. Then I
; treat the removable drives, which also get lower drive letters at start.
; Finally the hard drives are handled; they will close upo after "C:".
;
; ...for Optical Drives, starting with "O:" for "optical"
$s_FirstOpticalDrive = "O"
For $i = 0 to UBound($a_OpticalDriveList) - 1
    $s_cmd = "mountvol " & $a_OpticalDriveList[$i][0] & " /D"
    RunWait(@ComSpec & " /c " & $s_cmd, "", @SW_HIDE)
    $s_DriveLetterCharNew = Chr((Asc($s_FirstOpticalDrive)) + $i)
    $a_OpticalDriveList[$i][0] = $s_DriveLetterCharNew & ":"
    $s_cmd = "mountvol " & $a_OpticalDriveList[$i][0] & " " & $a_OpticalDriveList[$i][1]
    RunWait(@ComSpec & " /c " & $s_cmd, "", @SW_HIDE)
Next

; ...and then the Removable Disks (USB), starting with "R:" for "removable"
$s_FirstRemovableDrive = "R"
For $i = 0 to UBound($a_RemovableDriveList) - 1
    $s_cmd = "mountvol " & $a_RemovableDriveList[$i][0] & " /D"
    RunWait(@ComSpec & " /c " & $s_cmd, "", @SW_HIDE)
    $s_DriveLetterCharNew = Chr((Asc($s_FirstRemovableDrive)) + $i)
    $a_RemovableDriveList[$i][0] = $s_DriveLetterCharNew & ":"
    $s_cmd = "mountvol " & $a_RemovableDriveList[$i][0] & " " & $a_RemovableDriveList[$i][1]
    RunWait(@ComSpec & " /c " & $s_cmd, "", @SW_HIDE)
Next


; ----------------------------------------------------------------------------------------------------------------
; Now Mine for information about the partition/volume/drive containing the 
; operating system, so we later can get the size of the volume housing it. 
; This is important to estimate the sense of creating a second data partition 
; on that drive.
;
; Get the (1) DriveLetter (aka "C:") of the partition containing the OS
$o_OperatingSystem  = $o_WMIService.ExecQuery("SELECT * FROM Win32_OperatingSystem WHERE SystemDrive LIKE '" & $s_DriveDelimiter & "' ", "WQL", $h_wbemFlags)
For $o_items in $o_OperatingSystem
    $s_SystemDriveLetter = $o_items.SystemDrive
Next
; Get the (2) DeviceID (aka "Disk #0, Partition #0") of the system partition
$o_LogicalDiskToPartition = $o_WMIService.ExecQuery("SELECT * FROM Win32_LogicalDiskToPartition", "WQL", $h_wbemFlags)
For $o_items in $o_LogicalDiskToPartition
    If StringRight($o_items.Dependent,4) = """" & $s_SystemDriveLetter & """" then
        $s_SystemPartitionID = StringLeft(StringRight($o_items.Antecedent, 22), 21)
    EndIf
Next
; Get the (3) DeviceID (aka "\\\.\PHYSICALDRIVE0") of the device conbtaining 
; the system partition
$o_DiskDriveToDiskPartition = $o_WMIService.ExecQuery("SELECT * FROM Win32_DiskDriveToDiskPartition", "WQL", $h_wbemFlags)
For $o_items in $o_DiskDriveToDiskPartition
    If StringRight($o_items.Dependent,23) = """" & $s_SystemPartitionID & """" then
        $s_SystemDeviceID = StringLeft(StringRight($o_items.Antecedent, 22), 21)
    EndIf
Next


; ----------------------------------------------------------------------------------------------------------------
; Get the size of the partition containing the OS
$o_DiskPartition = $o_WMIService.ExecQuery("SELECT * FROM Win32_DiskPartition WHERE DeviceID = '" & $s_SystemPartitionID & "' ", "WQL", $h_wbemFlags)
For $o_items in $o_DiskPartition
    $i_SystemPartitionSize = $o_items.Size
Next

; Now get the size of the drive containing the system partition. In my defini-
; tion it is only useful to create another partition on the system drive if the 
; remaining amounts to at least 10.0 GBytes
; (10GBytes = 10737418240 Bytes = 10 *1024 *1024 *1024 Bytes).
$o_DiskDrive = $o_WMIService.ExecQuery("SELECT * FROM Win32_DiskDrive WHERE DeviceID = '" & $s_SystemDeviceID & "' ", "WQL", $h_wbemFlags)
For $o_items in $o_DiskDrive
    $i_SystemDeviceSize = $o_items.Size
    $i_NumberOfPartitions = $o_items.Partitions
    If ($i_SystemDeviceSize - $i_SystemPartitionSize) >=  10737418240 And $i_NumberOfPartitions = 1 Then
        Local $b_2ndPartitionOnHD0 = True
        Local $b_CreatePartition = True
        Local $a_TempAdd[3] = [$o_items.DeviceId, $b_CreatePartition, $i_NumberOfPartitions]
        _2DArrayAdd($a_DriveDetails, $a_TempAdd, False)
    ElseIf $i_NumberOfPartitions = 2 Then
        Local $b_2ndPartitionOnHD0 = True
        Local $b_CreatePartition = False
        Local $a_TempAdd[3] = [$o_items.DeviceId, $b_CreatePartition, $i_NumberOfPartitions]
        _2DArrayAdd($a_DriveDetails, $a_TempAdd, False)
    Else
        Local $b_2ndPartitionOnHD0 = False

        Local $b_CreatePartition = False
        Local $a_TempAdd[3] = [$o_items.DeviceId, $b_CreatePartition, $i_NumberOfPartitions]
        _2DArrayAdd($a_DriveDetails, $a_TempAdd, False)
    EndIf
Next

; Check if partitions exist on the physical units NOT containing the OS
$o_DiskDrive = $o_WMIService.ExecQuery("SELECT * FROM Win32_DiskDrive", "WQL", $h_wbemFlags)
For $o_items in $o_DiskDrive
    If StringRight($o_items.DeviceId, 14) <> StringRight($s_SystemDeviceID, 14) Then
        $i_NumberOfPartitions = $o_items.Partitions
        If $i_NumberOfPartitions = 0 Then
            $b_CreatePartition = True
            Local $a_TempAdd[3] = [$o_items.DeviceId, $b_CreatePartition, $i_NumberOfPartitions]
            _2DArrayAdd($a_DriveDetails, $a_TempAdd, False)
        Else
            $b_CreatePartition = False
            Local $a_TempAdd[3] = [$o_items.DeviceId, $b_CreatePartition, $i_NumberOfPartitions]
            _2DArrayAdd($a_DriveDetails, $a_TempAdd, False)
        EndIf
    EndIf
Next

; Delete the first row of the array containing the drives with usable space; 
; it only contains the unneeded index
_ArrayDelete($a_DriveDetails, 0)


; ----------------------------------------------------------------------------------------------------------------
; Create partitions where needed: 
;       On Drive 0 if more than 10GB of space are available
;       On Drive n if no partitions exist
; DriveLetters are assigned starting with "D:"
$s_AssignedDriveLetter  = "D"
For $i_i = 0 to UBound($a_DriveDetails) -1
    If $a_DriveDetails[$i_i][1] = True Then
        $s_ActualDriveLetter = Chr((Asc($s_AssignedDriveLetter)) + $i_i)
        $s_ActualDrive = StringRight($a_DriveDetails[$i_i][0], 1)
        _FileCreate($s_DiskpartCommandsFile)
        FileOpen($s_DiskpartCommandsFile, 2)
        FileWriteLine($s_DiskpartCommandsFile, "select disk " & $s_ActualDrive)
        FileWriteLine($s_DiskpartCommandsFile, "create partition primary")
        FileWriteLine($s_DiskpartCommandsFile, "assign letter= " & $s_ActualDriveLetter)
        FileClose($s_DiskpartCommandsFile)
        $s_cmd = "diskpart /s " & $s_DiskpartCommandsFile
        RunWait(@ComSpec & " /c " & $s_cmd, "", @SW_SHOW)
        Sleep(1000)
        $s_cmd = "format /fs:ntfs /q /x /v:TempName /Y " & $s_ActualDriveLetter & ":"
        RunWait(@ComSpec & " /c " & $s_cmd, "", @SW_SHOW)
        FileDelete($s_DiskpartCommandsFile)
    EndIf
Next


; ----------------------------------------------------------------------------------------------------------------
; Finally rename the volumenames using HD0 for the first physical drive, 
; HD1 for the second and HDn for all further ones.
$o_LogicalDisks         = $o_WMIService.ExecQuery("SELECT * FROM Win32_LogicalDisk WHERE Description = 'Local Fixed Disk'", "WQL", $h_wbemFlags)
For $o_items in $o_LogicalDisks
    If $o_items.Caption = $s_SystemDriveLetter Then
        $i_Counter = 0
        $o_items.VolumeName = "HD" & $i_Counter & "-System"
        $o_items.Put_
    ElseIf $o_items.Caption = "M:" Or $o_items.Caption = "D:" And $b_2ndPartitionOnHD0 = True Then
        $i_Counter = 0
        $o_items.VolumeName = "HD" & $i_Counter & "-Data"
        $o_items.Put_
    Else
        $i_Counter = $i_Counter + 1
        $o_items.VolumeName = "HD" & $i_Counter & "-Data"
        $o_items.Put_
    EndIf
Next









; Function _FindGUID to find the GUID belonging to a DriveLetter
; ==============================================================================================
Func _FindGUID($Drive)
    Local Const $DevList = 'HKLM\SYSTEM\MountedDevices'
    Local $i
    Do
        If RegRead($DevList, '\DosDevices\' & $Drive) = RegRead($DevList, RegEnumVal($DevList, $i)) Then Return StringReplace(RegEnumVal($DevList, $i), '\??\', '\\?\', 1)
        $i += 1
    Until 0
EndFunc   ;==>_FindGUID


; Function _2DArrayAdd to add lines to a two-dimensional array
; ==============================================================================================
Func _2DArrayAdd(ByRef $avArray, $vValue, $NestArray = True)
    Local $iBoundArray0, $iBoundArray1, $iBoundArray2, $iBoundValue1
    ; $avArray is not an array
    If IsArray($avArray) = 0 Then Return SetError(1, 0, -1)
    ; No. of dimesions in array
    $iBoundArray0 = UBound($avArray, 0)
    ; $avArray is more than 2D
    If $iBoundArray0 > 2 Then Return SetError(1, 1, -1)
    ; Size of array in first dimension
    $iBoundArray1 = UBound($avArray, 1)
    ; Size of array in second dimension
    If $iBoundArray0 = 2 Then $iBoundArray2 = UBound($avArray, 2)

    ; If input array is 1D, or $vValue is not an array, or $NestArray = True (default) then save $vValue literally
    If ($iBoundArray0 = 1) Or (IsArray($vValue) = 0) Or $NestArray Then
        If $iBoundArray0 = 1 Then
            ; Add to 1D array
            ReDim $avArray[$iBoundArray1 + 1]
            $avArray[$iBoundArray1] = $vValue
        Else
            ; Add to 2D array at [n][0]
            ReDim $avArray[$iBoundArray1 + 1][$iBoundArray2]
            $avArray[$iBoundArray1][0] = $vValue
        EndIf
    Else
        ; If input array is 2D, and $vValue is an array, and $NestArray = False,
        ; then $vValue is a 1D array of values to add as a new row.
        ; $vValue array is not 1D
        If UBound($vValue, 0) <> 1 Then Return SetError(1, 2, -1)
        $iBoundValue1 = UBound($vValue, 1)
        ; $vValue array has too many elements
        If $iBoundArray2 < $iBoundValue1 Then Return SetError(1, 3, -1)
        ReDim $avArray[$iBoundArray1 + 1][$iBoundArray2]
        For $n = 0 To $iBoundValue1 - 1
            $avArray[$iBoundArray1][$n] = $vValue[$n]
        Next
    EndIf

    ; Return index of new last row in $avArray
    Return $iBoundArray1
EndFunc   ;==>_2DArrayAdd

I'd be pleased to see sombody simplify / modify / fix my code. Especially needed / wanted would be help regarding the association the different names of one and the same damn object within different WMI classes ("C:" is "Disk #0, Partition #0" and is on or can be \\.\PYSICALDRIVE0 which is also \\\\.\\PYSICALDRIVE0). It's such a mess...

Best Regards,

Chris

Edited by cherdeg

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
Sign in to follow this  
Followers 0