This is the continuation of my previous post about adding data drives to an Azure VM using PowerShell. Here I will explain how to initialize the drive, format it, and assign a drive letter to it.

I wrote three scripts for the task: one to determine the LUN number that Windows used for the new drive, another one to create text files for diskpart.exe, and the last one to copy the files to the destination VMs and run them. Don’t worry; the scripts are pretty short and simple.

Let’s take a look at the first one:

rep = @()
Import-Csv C:\temp\vms_increase.csv | % {
   $vmname = $_.NAme
   $Disks = Get-WmiObject -Class Win32_DiskDrive -ComputerName $vmname
   $info = "" | Select ComputerName, DiskSize, DiskNumber
   $dskmax = ($Disks.Deviceid.Substring(17) | Measure -Maximum).Maximum
   $dskid = "PHYSICALDRIVE" + $dskmax
   $dsk = $Disks | ?{$_.Deviceid -match $dskid} 
   $info.ComputerName = $vmname
   $info.DiskSize = $dsk.size/1gb
   $info.DiskNumber = $dsk.Deviceid.Substring(17)
   $rep +=$info
$rep | Export-Csv -Path C:\temp\vmdrives.csv

First, I get the server names one by one from the .csv file through the Import-Csv cmdlet and then use each name to get the disks' object data from the remote machine with the Get-WmiObject cmdlet.  This data is stored in the $Disks variable. After that, I prepare the $info object for use in saving the disk data.

After all preparations are done, I get the highest disk number from the DeviceId field of the $Disks variable. This information is stored in the format "PHYSICALDRIVENN," where "NN" is the disk number. I get this number using the substring command that starts at the 17th symbol of the string. To find the highest number, I use the Measure –Maximum command.

Since Windows adds drives one after the other, the drive that was added last will have the largest number. In fact, I could stop here because I already have all the required information to proceed. However, to ensure that I get the right drive I also read the size. To do that, I first store the drive number in the $dskmax variable to use in getting the drive size from the $Disks variable.

Then I store all information for the current drive in the $info object. Since I’m in a loop, I use the $rep array I created in the first line of the script to save information I’ve obtained from all VMs in the .csv file. When the loop has completed, I export data to the .csv file.

This is what the script output looks like:

Check drive numbers

Check drive numbers

Now I need to prepare the text files I’m going to use to run diskpart.exe on the remote machines. There are going to be two files for each machine: one for disk initialization and another one for formatting the volume and assigning the drive letter.

Import-Csv C:\temp\vmdrives.csv | % {
   $vmname = $_.ComputerName
   $DiskN = $_.DiskNumber
   $dinit = New-Item -ItemType file -Path "c:\temp\$vmname-dinit.txt" -Force
   Add-Content -path $dinit -Value "select disk $DiskN"
   Add-Content -path $dinit -Value "ATTRIBUTES DISK CLEAR READONLY"
   Add-Content -path $dinit -Value "online disk"
   Add-Content -path $dinit -Value "CONVERT MBR"
   $dformat = New-Item -ItemType file -Path "c:\temp\$vmname-dformat.txt" -Force
   Add-Content -path $dformat -Value "select disk $DiskN"
   Add-Content -path $dformat -Value "create partition primary"
   Add-Content -path $dformat -Value "select partition 1"
   Add-Content -path $dformat -Value "format fs=ntfs label=Data quick"
   Add-Content -path $dformat -Value "assign letter=Z"

Here I import the .csv file created by the previous script and loop though its contents to assign computer name and disk number values to the variables $vmname and $DiskN, respectively. Then I prepare the text file for disk initialization using the New-Item cmdlet.

Next, I use the Add-Content cmdlet to add the diskpart.exe commands to the file. I start by selecting disk, followed by the command that clears the read-only attribute, the command that gets the drive online, and finally the command that converts the drive into an MBR disk.

After the disk is initialized, I have to format it. To do that, I create a second file. The process is the same: select a disk, create a primary partition, select the partition, format it as NTFS using quick format, assign a label, and finally assign a drive letter.

After the script is done, I have two files for each VM. The first one initializes the disk:

select disk 3
online disk

And the second formats the disk:

select disk 3
create partition primary
select partition 1
format fs=ntfs label=Data quicj
assign letter=Z

Finally, I have to run the two files on the remote machines. The script below does just that.

Import-Csv C:\temp\vms_increase.csv | %{
   $vmname = $_.Name
   $Dest = "\\" + $_.Name + "\"+ "C$\Windows\temp"
   $Dinit = "$vmname-dinit.txt"
   $Dformat = "$vmname-dformat.txt"
   Copy-Item "C:\temp\$vmname-dinit.txt" -Destination $Dest -Force
   Copy-Item "C:\temp\$vmname-dformat.txt" -Destination $Dest -Force
   Invoke-Command -ComputerName $vmname -ScriptBlock{
      $DinitExp = "C:\windows\system32\diskpart.exe /s c:\Windows\temp\$Using:Dinit"
      $DformatExp = "C:\windows\system32\diskpart.exe /s c:\Windows\temp\$Using:Dformat"
      Invoke-Expression $DinitExp
      sleep 15
      Invoke-Expression $DformatExp

Note that I once again import the .csv file with the server names and loop though it. First I assign the VM name to the $vmname variable and then define the $Dest variable, which is nothing more than the path to which I’m going copy .txt files for diskpart.exe.

Then I assign file names to the $Dinit and $Dformat variables for the current VM and copy those files to the remote machine using Copy-Item. To run diskpart.exe on the remote machine, I apply the Invoke-Command cmdlet to the current VM name.

To format the diskpart.exe command line, I use two variables, $DinintExp and $DformatExp. I format the disks using the Invoke-Expression cmdlet with a 15-second interval between commands.

This is the script output:

Subscribe to 4sysops newsletter!

Diskpart run 1

Diskpart run 1

Diskpart run 2

Diskpart run 2

Diskpart run 3

Diskpart run 3

After this has been completed, my remote VMs have access to the newly-assigned drives, which have been initialized and formatted.


Leave a reply

Please enclose code in pre tags

Your email address will not be published. Required fields are marked *


© 4sysops 2006 - 2021


Please ask IT administration questions in the forums. Any other messages are welcome.


Log in with your credentials


Forgot your details?

Create Account