How to stop and start Azure VMs in bulk

Starting and stopping Azure VMs in bulk is pretty easy in PowerShell, but you want to filter your VMs based on the correct property. VMs have a Status property that includes StoppedDeallocated, Stopped, RoleReady, etc. If you are attempting to identify VMs based on status, your PowerShell will have to write your script to filter on multiple criteria.

A better option is to use the PowerState property. Your VMs are going to have a PowerState of “Started” or “Stopped”, so turning them on (or off) in bulk based on this property is quite simple. You could take these one-liners into simple Windows scheduled tasks to turn your development and test environments down after quitting time and bring them back online before the team gets into the office the next morning, reducing your Azure spend on non-production compute resources.

Below are a handful of one-liners and a description of the nuances of each.

This first one-liner will shut down every VM in your subscription, but you will be prompted on the last / only VM in a cloud service with an “continuing will result in a new IP address for your deployment” message, and further direction that using the -StayProvisioned parameter will ensure your VM will keep it’s IP address. However, when you use that parameter, the VM remains provisioned, so you also keep getting billed. For test and dev environments, dynamic DNS registration and short time-to-live (TTL) on DNS records should be good enough to allow you to simply shutdown and deallocate to save dollars.

Get-AzureVM |  Where-Object {$_.powerstate -eq ‘Started’} | Stop-AzureVM

If you add the -Force parameter to the end of the one-liner (as shown below), the VMs are stopped and deallocated (meaning you are only being billed for the storage they consume) without the prompt.

Get-AzureVM |  Where-Object {$_.powerstate -eq ‘Started’} | Stop-AzureVM -Force

Replace the -Force parameter with -StayProvisioned as shown below and the annoying prompt is still avoided, but your VMs wind up in with a status of “Stopped” instead of “StoppedDeallocated”. This means the VMs will come back online with the same IP address, but the billing does not stop between power off and the next power on.

Get-AzureVM |  Where-Object {$_.powerstate -eq ‘Started’} | Stop-AzureVM -StayProvisioned

To start the VMs up again, you can simply reverse the flow with a couple of small changes, as shown below.

Get-AzureVM |  Where-Object {$_.powerstate -eq ‘Stopped’} | Start-AzureVM

Naturally, you can add multiple criteria to the Where-Object filtering to filter based on VM name, cloud service name and other properties to shut down specific subsets of your VMs. In a future post we will look at scheduled tasks, time-based actions and moving this process into Azure’s PowerShell Workflow based orchestration engine, Azure Automation.

How to find if an Azure VM exists via PowerShell

One task that can be help to optimize deployments in Azure is checking for the existence of a VM before you attempt to deploy. This can be particularly useful when you attempt to restart a failed deployment of multiple VMs. Because every VM in Azure resides within a cloud service, checking for a VM can be a bit more work than in an on-premises scenario with VMM and Hyper-V.

If you know the name of the service the VM should reside within your Azure subscription, the check is quick and easy.

if (!(Get-AzureVM -ServiceName "MyCloudService" -Name "MyVMName"))

On the other hand, sometimes you will not know which cloud service the VM resides in (as when generating random cloud service names in a bulk deployment). In this case, you will need to check every cloud service for the existence of the VM. The function below is one example of to determine if a VM exists within an Azure subscription if you do not know the name of the cloud service. The last line calls the function and provides the name of  a VM.

 Function Check-AllServices4VM ($vmName) {

 $cloudServices = Get-AzureService 

 ForEach ($Service in $cloudServices) {

 If (Get-AzureVM -ServiceName $Service.ServiceName -Name $vmName) {

 Write-Host "Azure VM by that name already exists in service " $Service.ServiceName " ...terminating"
    Write-Host "Azure VM does not exist is service " $Service.ServiceName
 } # end of function 

 # Call the function and provide VM name
 Check-AllServices4VM -vmName SQLClient

That’s all for today. Leave any thoughts in comments.

How to Create an Azure SQL Database via PowerShell

As I mentioned yesterday in “How to Create an Azure SQL Instance via PowerShell“, Azure SQL provides some cost advantages over running SQL in Azure VMs for scenarios where all you need is a database. In yesterday’s article, we created an Azure SQL database instance, as well as a firewall rule on the instance to allow remote connections.

Now, we are ready to create a database in our new Azure SQL instance. Start by connecting to your Azure subscription in the standard manner (see resources in the article linked above if connecting to your Azure sub in PowerShell is not familiar).

Then, we create a credential to store the user and password we will use to authenticate to the Azure SQL instance.

$User = “pzerger”
$PWord = ConvertTo-SecureString –String ‘Pa$$w0rd!’ –AsPlainText -Force
$Credential = New-Object –TypeName System.Management.Automation.PSCredential `
–ArgumentList $User, $PWord

Next, we will connect and authenticate to the instance.

$sqlContext = New-AzureSqlDatabaseServerContext `
-ServerName “xne7lwczta" -Credential $Credential

Then, we will select the level of service, which determines the max database size, connection and session count, and transaction rate. There are many levels of service across the Basic, Standard and Premium tiers. You can find a current list of available

In this example, I will specify S0, the lowest level of the Standard tier, and provide along with that the sqlContext object from the previous step, which stores the SQL instance name and credentials.

$S0 = Get-AzureSqlDatabaseServiceObjective `
-Context $sqlContext -ServiceObjectiveName S0

In the last step, we create the database. In this case, I am creating a database named “InsideTheMSCloud”.

New-AzureSqlDatabase -ConnectionContext $sqlContext `
-DatabaseName “InsideTheMSCloud" -Edition “Standard” -MaxSizeGB 1 `
-Collation “SQL_Latin1_General_CP1_CI_AS” -ServiceObjective $S0

Now we have a Azure (PaaS) SQL instance, a firewall rule to allow remote connections and a database. In the next post on this topic, we’ll do something with this database.

How to Create an Azure SQL Instance via PowerShell

I wanted to share a bit about Azure SQL (PaaS) in Azure, as I believe it will commonly used by IT Pros in the future, particularly as a logging and reference databasew when working with Azure Automation. One compelling reason to Azure SQL instance of SQL Server in Azure VMs is cost. If you just need a little database, you can have what you need in Azure SQL for as little as free or a few cents a month. SQL Server in Azure VMs is going to cost the price of the VM and the SQL license if you don’t bring your own. You can read about the differences between the two at

To create an Azure SQL Server instance, start by connecting to your Azure subscription in PowerShell as you normally do. If you are unsure of the steps, see

Next, we create an Azure SQL instance as follows. This creates a new Azure SQL Server instance, with a random name chosen by Azure.

#Create Azure SQL Server
$location = 'East US'
$login = 'pzerger'
$password = 'Pa$$w0rd!'
$newSqlServer = New-AzureSqlDatabaseServer -Location $location -AdministratorLogin $login `
-AdministratorLoginPassword $password -Version "2.0"

Get the name of the Azure SQL instance name like so:


All connections to this SQL instance will be blocked by default, so you need to create a firewall rule to allow all connections. For this one, I just create a rule to allow connections from any IP address.

New-AzureSqlDatabaseServerFirewallRule -ServerName $newSQLServer.ServerName `
-RuleName "Allow all IP addresses to connect" `
-StartIpAddress -EndIpAddress

Now we have an Azure SQL Server instance that allows connections from any IP Address. In a future post, we will connect and create a database and start making use of our resources.

Retrieve the latest version of a Gallery Image in Azure PowerShell

Here is a handy snippet I use fairly often. When you retrieve an Azure gallery image by name, you will find there are multiple versions of the image.

Get-AzureVMImage -Verbose:$false | Where-Object {$_.label -like “Windows Server 2012 Datacenter*”} | Select-Object Label, PublishedDate

You will typically find at least two versions of each image, which can be differentiated by date, as shown below.

Label       PublishedDate
—–         ————-
Windows Server 2012 Datacenter, February 2015 2/11/2015 2:00:00 AM
Windows Server 2012 Datacenter, March 2015 3/12/2015 2:00:00 AM

Finding the latest image is as simple as retrieving all of them and sorting in descending order based on the published date. The code below will arrange the images in descending order by published date, then retrieve the first in the list.

(Get-AzureVMImage -Verbose:$false | Where-Object {$_.label -like “Windows Server 2012 Datacenter*”}| Sort-Object –Descending PublishedDate)[0].ImageName

We can save this result to a variable and proceed with deployment.

$winImageName = (Get-AzureVMImage | where {$_.label –like “Windows Server 2012 Datacenter*”} | sort PublishedDate -Descending)[0].ImageName

I’ll follow this post with a many more in this vein, offering some tips to optimize your Azure scripting.