windows azure powershell

Azure – Provision Azure Virtual Machine with UnManaged disks

Microsoft has introduced a new type of disk called “Managed” disk wherein Azure manages the disk and the underlying storage account overhead for you. And, Microsoft recommends you create Azure virtual machines with “managed” disks, which is straightforward.

However, you might come across scenarios where your organization/client may require creating an Azure virtual machine with “unmanaged” disks. Use the below code to create an Azure virtual machine with “unmanaged” disks.

$location = "EastUS2"
$rgname = "manjuResourceGroup"
New-AzureRmResourceGroup -Name manjuResourceGroup -Location $location

# Create a subnet configuration
$subnetConfig = New-AzureRmVirtualNetworkSubnetConfig -Name mySubnet -AddressPrefix

# Create a virtual network
$vnet = New-AzureRmVirtualNetwork -ResourceGroupName manjuResourceGroup -Location $location `
    -Name MYvNET -AddressPrefix -Subnet $subnetConfig

# Create a public IP address and specify a DNS name
$pip = New-AzureRmPublicIpAddress -ResourceGroupName manjuResourceGroup -Location $location `

    -AllocationMethod Static -IdleTimeoutInMinutes 4 -Name "mypublicdns$(Get-Random)"

# Create an inbound network security group rule for port 3389
$nsgRuleRDP = New-AzureRmNetworkSecurityRuleConfig -Name myNetworkSecurityGroupRuleRDP  -Protocol Tcp `
    -Direction Inbound -Priority 1000 -SourceAddressPrefix '' -SourcePortRange * -DestinationAddressPrefix * `
    -DestinationPortRange 3389 -Access Allow

# Create an inbound network security group rule for port 80
$nsgRuleWeb = New-AzureRmNetworkSecurityRuleConfig -Name myNetworkSecurityGroupRuleWWW  -Protocol Tcp `
    -Direction Inbound -Priority 1001 -SourceAddressPrefix '' -SourcePortRange * -DestinationAddressPrefix * `
    -DestinationPortRange 80 -Access Allow

# Create a network security group
$nsg = New-AzureRmNetworkSecurityGroup -ResourceGroupName manjuResourceGroup -Location $location `
    -Name myNetworkSecurityGroup -SecurityRules $nsgRuleRDP,$nsgRuleWeb

# Create a virtual network card and associate with public IP address and NSG
$nic = New-AzureRmNetworkInterface -Name myNic -ResourceGroupName manjuResourceGroup -Location $location `
    -SubnetId $vnet.Subnets[0].Id -PublicIpAddressId $pip.Id -NetworkSecurityGroupId $nsg.Id

# Define a credential object
$cred = Get-Credential

#VM config
$vmsize = "Standard_DS2"
$vm = New-AzureRmVMConfig -VMName $vmName -VMSize $vmSize
$pubName = ”MicrosoftWindowsServer”
$offerName = ”WindowsServer”
$skuName = ”2016-Datacenter”
$vm = Set-AzureRmVMOperatingSystem -VM $vm -Windows -ComputerName $vmName -Credential $cred
$vm = Set-AzureRmVMSourceImage -VM $vm -PublisherName $pubName -Offer $offerName -Skus $skuName -Version "latest"
$vm = Add-AzureRmVMNetworkInterface -VM $vm -Id $NIC.Id

# Create a new storage account
New-AzureRmStorageAccount -ResourceGroupName "manjuResourceGroup" -AccountName "manjustorageaccount" -Location $location -SkuName "Standard_LRS"

# Disk setup
$diskName = ”manju-disk”
$storageaccount = "manjustorageaccount"
$STA = Get-AzureRmStorageAccount -ResourceGroupName $rgName -Name $storageAccount
$OSDiskUri = $STA.PrimaryEndpoints.Blob.ToString() + "vhds/" + $diskName? + ".vhd"
$vm = Set-AzureRmVMOSDisk -VM $vm -Name $diskName -VhdUri $OSDiskUri -CreateOption fromImage

# Create the virtual machine
New-AzureRmVM -ResourceGroupName manjuResourceGroup -Location $location -VM $vm


Click here to download my PowerShell scripts for Free !!

Click here for Azure tutorial videos !!


Azure – Expand OS Drive for Azure Virtual Machine

When you create an Azure Virtual Machine, it comes with an OS drive having a default size. The size is different for Windows and Linux machines. ~128GB and ~30GB for Windows and Linux machines respectively. The OS drive can be expanded to a maximum size of 2TB as of this writing. Use the below code to allocate space to your Azure VM’s OS drive. After executing the code, login to the virtual machine and expand (Disk Management for Windows) the drive using the newly allocated space.


Resize a Managed Disk:


## Resize OS disk size for Managed Disk

# Set Resource Group and Virtual Machine name
$resourceGroupName = 'my_resource_group_name'
$virtualMachineName = 'my_virtual_machine_name'

# Create VM reference object
$vm = Get-AzureRmVM -ResourceGroupName $resourceGroupName -Name $virtualMachineName

# Stop the Virtual Machine
Stop-AzureRmVM -ResourceGroupName $resourceGroupName -Name $virtualMachineName

# Create a reference to the Managed disk and set the size as required
$disk= Get-AzureRmDisk -ResourceGroupName $resourceGroupName -DiskName $vm.StorageProfile.OsDisk.Name
$disk.DiskSizeGB = 1023
Update-AzureRmDisk -ResourceGroupName $resourceGroupName -Disk $disk -DiskName $disk.Name

# Start the Azure Virtual Machine
Start-AzureRmVM -ResourceGroupName $resourceGroupName -Name $virtualMachineName



Resize an Unmanaged Disk:


## Resize OS disk size for Unmanaged Disk

# Set Resource Group and Virtual Machine name
$resourceGroupName = 'my-resource-group-name'
$virtualMachineName = 'my-vm-name'

# Create VM reference object
$vm = Get-AzureRmVM -ResourceGroupName $resourceGroupName -Name $virtualMachineName

# Stop the Virtual Machine
Stop-AzureRmVM -ResourceGroupName $resourceGroupName -Name $virtualMachineName

# Create a reference to the Unmanaged disk and set the size as required
$vm.StorageProfile.OSDisk.DiskSizeGB = 1023
Update-AzureRmVM -ResourceGroupName $resourceGroupName -VM $vm

# Start the Azure Virtual Machine
Start-AzureRmVM -ResourceGroupName $resourceGroupName -Name $virtualMachineName


Click here to download my PowerShell scripts for Free !!

Click here for Azure tutorial videos !!

Azure – Attach and Initialize Data disk to Azure Virtual Machine

When you create an Azure windows virtual machine, it comes a default OS drive (C:\) and a temporary drive (D:\). An azure virtual machine allows you to attach a data disk to it to expand the storage. The number of data disks that can be attached to the VM depends on the Size and Family of the VM.

You can automate the process of attaching the data disk and initializing it using two scripts:

Script 1: initializePartition.ps1

This script contains the code to initialize the RAW partition.

Script 2: attachAndInstallCSE.ps1

This script will attach the data disk to the Azure windows virtual machine. It also installs the Custom Script Extension to the virtual machine.



$disks = Get-Disk | Where partitionstyle -eq 'raw' | sort number
    $letters = 70..89 | ForEach-Object { [char]$_ }
    $count = 0
    $labels = "data1","data2"

    foreach ($disk in $disks) {
        $driveLetter = $letters[$count].ToString()
        $disk |
        Initialize-Disk -PartitionStyle MBR -PassThru |
        New-Partition -UseMaximumSize -DriveLetter $driveLetter |
        Format-Volume -FileSystem NTFS -NewFileSystemLabel $labels[$count] -Confirm:$false -Force




# Declaringvariables
$resourceGroupName = 'resourceGroupName'
$virtualMachineName = 'virtualMachineName'
$location = 'East US'
$storageType = 'Premium_LRS'
$dataDiskName = $virtualMachineName + '_datadisk1'

# Create a new managed data disk
$diskConfig = New-AzureRmDiskConfig -SkuName $storageType -Location $location -CreateOption Empty -DiskSizeGB 128
$dataDisk1 = New-AzureRmDisk -DiskName $dataDiskName -Disk $diskConfig -ResourceGroupName $resourceGroupName

# Get the virtual machine reference
$vm = Get-AzureRmVM -Name $virtualMachineName -ResourceGroupName $resourceGroupName

# Update the VM reference by adding the data disk
$vm = Add-AzureRmVMDataDisk -VM $vm -Name $dataDiskName -CreateOption Attach -ManagedDiskId $dataDisk1.Id -Lun 1

# Update the virtual machine
Update-AzureRmVM -VM $vm -ResourceGroupName $resourceGroupName

## Install the Custom Script Extension that inturn calls the initializePartition.ps1
$location = "East US 2"

# The name you want to give for the CSE
$extensionName = "extensionName"

$fileName = "initializePartition.ps1"

# Storage Account where the initializePartition.ps1 is present
$storageAccountName = "<INSERT_STORAGE_ACCOUNT_NAME>"

# Primary Access Key of Storage Account where the initializePartition.ps1 is present
$storageAccountAccessPrimaryKey = "<INSERT_STORAGE_PRIMARY_ACCESS_KEY>"

# Storage Account container where the initializePartition.ps1 is present
$storageAccountContainerName = "<INSERT_STORAGE_ACCOUNT_CONTAINER_NAME>"

Set-AzureRmVMCustomScriptExtension -ResourceGroupName $resourceGroupName -Location $location -VMName $virtualMachineName -Name $extensionName -TypeHandlerVersion "1.4" -StorageAccountName $storageAccountName -StorageAccountKey $storageAccountAccessPrimaryKey -FileName $fileName -ContainerName $storageAccountContainerName


Click here to download my PowerShell scripts for Free !!

Click here for Azure tutorial videos !!



Azure – Understand your Azure resource utilization using Azure Metrics

Understanding resource utilization is very crucial in determining how your resources are performing. Using this data, you can them make decisions on cost optimization. From my experience, clients are very keen on having a scheduled Resource Utilization Report.

If you are working in an infrastructure team, then your report for a virtual machine may include, CPU utilization, memory, disk usage, network in/Out etc.,

You can use Azure PowerShell to download Azure Insight Metric Data.

As an example, below code shows you how to retrieve CPU Utilization data for an Azure virtual machine.


# Get the virtual machine object
$vm = get-azurermvm -ResourceGroupName "automationResourceGroup" -Name "hybridworker"

# Get the resource ID for the virtual machine
$resourceID = $vm.Id

# Retrieve Azure Insight metric definitions for virtual machines
Get-AzureRmMetricDefinition –ResourceId $resourceID -DetailedOutput


Output of the above cmdlet will fetch a lot of metrics. I have selected the “Percentage CPU”.

sourceId             : /subscriptions/aaaaaaa-bbbb-cccc-dddd-eeeeeeeee/resourceGroups/automation/providers/Microsoft.Compute/virtualMachines/hybridworker

Name                   :

                             LocalizedValue : Percentage CPU

                             Value          : Percentage CPU


Unit                   : Percent

PrimaryAggregationType : Average

Id                     : /subscriptions/aaaaaaa-bbbb-cccc-dddd-eeeeeeeee/resourceGroups/automation/providers/Microsoft.Compute/virtualMachines/hybridworker/providers/microsoft.insights/metricdefinitions/Percentage CPU


The “Value” will give you the correct Metric Name.


Below code will pull the CPU utilization of the virtual machine for the last 40 minutes.

$endTime = Get-Date
$startTime = $endTime.AddMinutes(-40)
$timeGrain = '00:01:00'
$metricName = 'Percentage CPU'
$metricData = Get-AzureRmMetric -ResourceId $resourceID -TimeGrain $timeGrain -StartTime $startTime -EndTime $endTime -MetricNames $metricName


I have shown you how to fetch one such metric for an Azure resource (Azure virtual machine in this case). Similarly, you can fetch metrics for any Azure resource by obtaining the relevant “resourceID” and fetching the appropriate Azure Metric Definition.

Click here to download my PowerShell scripts for Free !!

Click here for Azure tutorial videos !!


Azure – TAG Azure Virtual Machines?

In a cloud environment, the effective way to organize and manage your infrastructure is by tagging your resources. Example, if your client has multiple silos like marketing, sales etc., and your cost model is different to each silo, tagging the resources provides an effective way to measure and manage the cost for your client.

Use the below code to TAG your Azure virtual machine:

$resource_group = "resourceGroupName"
$vm_name = "virtualMachineName"
$tags = (Get-AzureRmResource -ResourceGroupName $resource_group -Name $vm_name).Tags
$tags += @{toolsinstalled="true"}
Set-AzureRmResource -ResourceGroupName $resource_group -Name $vm_name -ResourceType "Microsoft.Compute/VirtualMachines" -Tag $tags -Force


You may tag other resources (Storage Account, Virtual Network etc.,) by providing the correct values to “-ResourceType” parameter.

If you have a set of standard tags and you want to tag all virtual machines in a resource group, then use the code below as a template:



  ## Parameter declaration


  # Tag values passed as a parameter








$azure_vm_list = get-azurermvm -ResourceGroupName $resource_group

foreach($azure_vm_list_iterator in $azure_vm_list){

$tags = (Get-AzureRmResource -ResourceGroupName $resource_group -Name $

# Creating a hash table with tag name and value

$tags += @{"RTB status"=$rtb_status_tag_value}

$tags += @{"OS Type"=$os_type_tag_value}

$tags += @{"Environment"=$environment_tag_value}

$tags += @{"Built Date"=$build_date_tag_value}

$tags += @{"Project Name"=$project_name_tag_value}

$tags += @{"Support Type"=$support_type_tag_value}

"Setting tags"| write-output

Set-AzureRmResource -ResourceGroupName $resource_group -Name $ -ResourceType "Microsoft.Compute/VirtualMachines" -Tag $tags -ApiVersion '2017-12-01' -force



Click here to download my PowerShell scripts for Free !!

Click here for Azure tutorial videos !!

Azure – Install software on Azure Virtual Machine using Azure Custom Script Extension (CSE)

You may need to install a software (exe, MSI etc..) on your Azure virtual machines as per the on-boarding process. The traditional way of doing this is to RDP to your virtual machine and then install the software.

Azure and PowerShell make this task simple by introducing “Custom Script Extension (CSE)” for Azure Virtual machines. Using CSE you can install the executables without login into the servers. The process also reduces human effort by a lot, hence increasing the ROI for your team.

As an example, let us see how to deploy a BigFix client into an Azure Windows Virtual Machine:

The process requires two scripts:

Script 1: installAgent.ps1

This script does the silent installation of the agents. This script must be uploaded into Azure Storage Account along with the exe/MSI.

Script 2: triggerCSE.ps1

This script installs the CSE on the Windows Azure virtual machine. Checks if the Virtual Machine is STOPPED. If it is stopped, it will start the virtual machine, install the CSE, and then it will stop the virtual machine.

Steps to be followed

  1. Upload all the necessary files (BigFix installation files) into Azure Storage account and provide Anonymous access to the container.
  2. Upload the installAgent.ps1 PowerShell script into Azure Storage account and provide Anonymous access to the container.
  3. Execute the triggerCSE.ps1 from your laptop or you can completely automate the solution using Azure Automation Account.




# Script to install Big Fix agents in Singapore region

# Create a directory to hold BigFix files

new-item 'c:\bigfix' -ItemType directory -force

# Copy BigFix files from Azure storage to local directory

Invoke-WebRequest -Uri -outfile 'c:\bigfix\clientsettings.cfg'

Invoke-WebRequest -Uri -outfile 'c:\bigfix\masthead.afxm'

Invoke-WebRequest -Uri -outfile 'c:\bigfix\setup.exe'

# Execute the setup file

$arguments = "/S /v/qn"

$filepath = "c:\bigfix\setup.exe"

Start-Process $filepath $arguments -wait




##### Installing BigFix client on virtual machine #####

        # Declaring variables

        # storage account name where the custom script is stored

        $storage_account_name = "<INSTERT_STORAGE_ACCOUNT_NAME>"

        # storage account key of where the custom script is stored

        $storage_account_key = "<INSERT_STORAGE_ACCOUNT_KEY>"

        # custom script file name

        $bigfix_file_name = "installAgent.ps1"

        # container name where the custom script is stored

        $bigfix_container_name_singapore = "<INSERT_AZURE_STORAGE_CONTAINER_NAME>"

        # Assuming the state of the virtual machine is not de-allocated

        $is_dellocated = $false



        # Checking if the Webhook data has the Resource Group and Virtual Machine.

        if($resource_group -eq $null -or $vm_name -eq $null){

            "Either Resource Group or Virtual Machine name, not present. This could be because the input variables could be misspelled. Make sure the input names are - 'ResourceGroup' and 'VirtualMachine'. " | write-output



        #### Checking if the Virtual Machine is a Windows machine ########

        # Obtaining the Virtual Machine object

        $vm = get-azurermvm -ResourceGroupName $resource_group -Name $vm_name

        # Obtaining the Virtual Machine status object

        $vm_status = get-azurermvm -ResourceGroupName $resource_group -Name $vm_name -Status

        "Displaying the status of Virtual machine...." | write-output

        $vm_status.Statuses[1].DisplayStatus | write-output

        "" | write-output

        "" | write-output

        "Checking if the VM is Windows or not. Expect some output below if the Virtual machine is Windows... If you DONOT GET ANY OUTPUT, STOP EXECUTING..." | write-output

        $vm.OSProfile.WindowsConfiguration | write-output


        if($vm.OSProfile.WindowsConfiguration -eq $null){

            "The Virtual machine is either a custom image or is not Windows Virtual Machine. Cannot proceed with installing Custom Script Extenstion.. " | write-output






        ######## Checking the status of the Virtual Machine ########


            VM Generalized --> Do not take any action. Exit Execution

            VM Deallocated --> Start the Virtual Machine

            VM Running --> Do not take any action, Proceed with Execution


        if($vm_status.Statuses[1].DisplayStatus -eq "VM Generalized"){

            "Virtual Machine is in the GENERALIZED state. Do not proceed further... " | write-output

            "" | write-output

            "" | write-output



        if($vm_status.Statuses[1].DisplayStatus -eq "VM deallocated"){

            "Virtual Machine is STOPPED. Starting the virtual machine... " | write-output

            $is_dellocated = $true

            $vm | Start-AzureRmVM

            "Successfully started Virtual Machine.." | write-output

            ""| write-output

            "" | write-output


        if($vm_status.Statuses[1].DisplayStatus -eq "VM running"){

            "Virtual Machine is already RUNNING. Proceeding with agents installation" | write-output

            "" | write-output

            "" | write-output



        # Checking if the virtual machine already has a Custom Script Extension

        $vm = get-azurermvm -ResourceGroupName $resource_group -Name $vm_name

        $vm_status = get-azurermvm -ResourceGroupName $resource_group -Name $vm_name -Status

        $vm_extensions = $vm.Extensions

        foreach($vm_extensions_iterator in $vm_extensions){

            if($vm_extensions_iterator.VirtualMachineExtensionType -eq "CustomScriptExtension"){

                "Removing the CSE..." | write-output

                Remove-AzureRmVMCustomScriptExtension -Name $vm_extensions_iterator.Name -ResourceGroupName $resource_group -VMName $vm_name -force

                "Removed  the CSE " | write-output

                "" | write-output

                "" | write-output



        # Re-creating the Virtual Machine object, since one of the above condition - starts the virtual machine

        $vm = get-azurermvm -ResourceGroupName $resource_group -Name $vm_name

        $vm_status = get-azurermvm -ResourceGroupName $resource_group -Name $vm_name -Status

        ########### Installing BIGFIX client via Azure Custom Script Extension ###########

        if($vm_status.Statuses[1].DisplayStatus -eq "VM running" -and $vm.OSProfile.WindowsConfiguration -ne $null){

            "Installing BigFix extension..." | write-output

            # azure powershell cmdlet to execute add the custom script extension and to execute the powershell file

            Set-AzureRmVMCustomScriptExtension -ResourceGroupName $resource_group -Location $vm.Location -VMName $vm_name -Name "ibm_bigfix_agent_install_extension" -TypeHandlerVersion "1.1" -StorageAccountName $storage_account_name -StorageAccountKey $storage_account_key -FileName $bigfix_file_name -ContainerName $bigfix_container_name_singapore


        "waiting for 10 seconds..." | write-output

        "" | write-output

        "" | write-output

        Start-Sleep -s 10

        ######## Stopping the Virtual machine that we had started ########

        if($is_dellocated -eq $true){

            "We had started the virtual machine before installing the BigFix agent. STOPPING the virtual machine to preserve the initial state..." | write-output

            $vm | Stop-AzureRmVM -force

            "Successfully stopped the virtual machine" | write-output

            "" | write-output

            "" | write-output




As an enhancement, you can add additional checks, create a log file and have it uploaded to another Storage Account. Or, create an Azure Storage Table, and write the updates to it tracking how many virtual machines the CSE is installed.


Click here to download my PowerShell scripts for Free !!

Click here for Azure tutorial videos !!


Azure – Copy Data disk from one Azure virtual machine to another


Just like any other computer, virtual machines in Azure use disks as a place to store an operating system, applications, and data. All Azure virtual machines have at least two disks – a Windows operating system disk and a temporary disk. The operating system disk is created from an image, and both the operating system disk and the image are virtual hard disks (VHDs) stored in an Azure storage account. Virtual machines also can have one or more data disks, that are also stored as VHDs.

Consider a case where you have configured an Azure virtual machine that hosts applications and you have saved an application data in multiple data disks. Now you want to create multiple virtual machines or copy all those data disks to other virtual machines.

You can now perform a copy Data Disk operation from one Azure virtual machine to another Azure virtual machine by using a PowerShell script.

Download the script

Click here to download my PowerShell scripts for Free !!

Click here for Azure tutorial videos !!