cherdeg Posted October 28, 2008 Share Posted October 28, 2008 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 Link to comment Share on other sites More sharing options...
Bert Posted October 28, 2008 Share Posted October 28, 2008 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. The Vollatran project My blog: http://www.vollysinterestingshit.com/ Link to comment Share on other sites More sharing options...
cherdeg Posted October 28, 2008 Author Share Posted October 28, 2008 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. Link to comment Share on other sites More sharing options...
Bert Posted October 28, 2008 Share Posted October 28, 2008 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 2Once 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 partitionAre 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. The Vollatran project My blog: http://www.vollysinterestingshit.com/ Link to comment Share on other sites More sharing options...
Legacy99 Posted October 28, 2008 Share Posted October 28, 2008 Diskpart is what you need.http://support.microsoft.com/kb/300415http://technet.microsoft.com/en-us/library/cc766465.aspx Link to comment Share on other sites More sharing options...
Kerros Posted October 28, 2008 Share Posted October 28, 2008 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. Link to comment Share on other sites More sharing options...
cherdeg Posted October 28, 2008 Author Share Posted October 28, 2008 1. The company you work for.2. Cost - you have no money for software.3. Both 1 and 2Hi 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? Link to comment Share on other sites More sharing options...
cherdeg Posted October 28, 2008 Author Share Posted October 28, 2008 (edited) Diskpart is what you need.http://support.microsoft.com/kb/300415http://technet.microsoft.com/en-us/library/cc766465.aspxI 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 October 28, 2008 by cherdeg Link to comment Share on other sites More sharing options...
cherdeg Posted October 29, 2008 Author Share Posted October 29, 2008 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)KerrosHello Kerros!If you got a working solution, would you mind letting please me take part in it?Regards, Chris Link to comment Share on other sites More sharing options...
Kerros Posted October 29, 2008 Share Posted October 29, 2008 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. expandcollapse popup@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. Link to comment Share on other sites More sharing options...
cherdeg Posted October 29, 2008 Author Share Posted October 29, 2008 Ahhh...okay...that easy...so I WILL reinvent the wheel...Kerros: thank you VERY MUCH!!! Link to comment Share on other sites More sharing options...
cherdeg Posted November 5, 2008 Author Share Posted November 5, 2008 (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: expandcollapse popup;#################################################################### ;# ;# 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 November 5, 2008 by cherdeg 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