How to avoid reinventing the wheel in Azure Automation

Doctor Scripto

Summary: Take advantage of existing scripts to create your own solutions.


Automation is the number one technical skill that IT needs to have to thrive in today’s quickly changing world. My recommendation is that anything you do for automation you should do in PowerShell, and you should use Azure Automation as your go-to automation solution.

Powershell Wizard (PoSH Wizard illustration courtesy of

The Microsoft Operations Management Suite provides functionality around log analysis, backup and recovery, security and compliance, and IT automation. IT automation uses Azure Automation and is described as a method to “automate manual and repeated tasks using runbooks and graphical workflow-authoring tools”. As you drill into the IT automation parts of OMS, what you find is that this IT automation solution is Azure Automation. Azure Automation enables you to utilize PowerShell or PowerShell workflows (or graphically based workflows) to provide automation both in the cloud and in your on-premises environment (using the Azure Hybrid Runbook Worker).

When you are coding in PowerShell, it is best to work from what already exists rather than creating it from scratch. This not only shortens the time to create new scripts, it also increases the quality through working from other functional approaches. This leads to the logical question – “Where do you find reusable PowerShell scripts?” To answer this question, I reached out to the Catapult Systems Launch PowerShell team, and I asked them where they get their scripts when they are building new functions for Launch. Here are the top 15 recommendations that I received from the team:

  1. Start with your search engine of choice (Bing, Google). These are still the quickest way to get results most of the time.
  2. TechNet Blogs/documentation (
  3. TechNet Forums (
  4. TechNet Gallery (
  5. TechNet ScriptCenter “Scripting Guys” (
  6. Stack Overflow (
  7. Reddit (
  8. org (
  9. CodePlex (
  10. GitHub (
  11. SS64 (
  12. MSDN documentation (
  13. Azure documentation (
  14. Azure Automation Runbook Gallery
  15. Service Management Automation sample runbooks

So, how can you take these scripts and examples that you find online and use them in your environment? Well, there are a couple of tips that I can give to help you. The first is, you don’t necessarily need to find a script that does exactly what you are looking to automate. Usually, you find a script that does about 80% of what you want. Then, all you have to do is finish the other 20%. Second, learn what the script is doing and how it is doing it. Doing this will help you manipulate the scripts and examples to get the results you want. Open the script in the PowerShell integrated scripting environment (ISE) and go through it line by line. Then, if you ever have any problems, you’ll have a good idea of where to start troubleshooting. And finally, don’t be afraid to ask questions. Most of the sites mentioned previously are community sites that have user boards and comment sections. Feel free to ask any questions. Most people on those sites are there to help, and enjoy it. Now, let’s look at a few examples to give you some ideas of how you can apply these practices.

Let’s say, for example, that we want to connect to an Azure virtual machine and return any Windows Services that are set to start automatically but are not currently running. We could connect via remote desktop (RDP), open the PowerShell window, and run the following command.

Get-WMIObject win32_service -Filter "startmode = 'auto' AND state != 'running'"

Windows Services that are set to start automatically but are not currently running

But, let’s say that we need to run this on multiple virtual machines a couple times a day. In this case, we will want to automate it. To do this, we will need to determine the required steps. In this instance, we will first need to connect to the virtual machine and then run the script. Because we already have the command that we need to run, all we need to do is figure out how to connect to an Azure virtual machine.

If you connect to your Azure Automation instance, you can browse the gallery for existing scripts.

Browse gallery button

If you look through the gallery, you’ll find a script named Connect to an Azure Virtual Machine, which looks like it fulfills the step we need of connecting to an Azure virtual machine.

The "Connect to an Azure Virtual Machine" script in the gallery

You can import this script directly from the Azure Automation gallery to your Azure Automation instance. Script imported from the Azure Automation gallery to an Azure Automation instance

After you have it imported, you’ll want to open it in Edit mode and look at the script. The first thing you’ll want to do is look through the help information at the top. Luckily this script, unlike many you will find out there, contains a lot of help information in the header. Second, you want to take a look at the parameters. Looking at the parameters of this script, you’ll see that it is asking for three strings, the Azure subscription name, service name, and virtual machine name. There is also a fourth parameter named $AzureOrgIdCredential, and it is PSCredential type.

Param (

[parameter(Mandatory=$true)] [String] $AzureSubscriptionName,

[parameter(Mandatory=$true)] [PSCredential] $AzureOrgIdCredential,

[parameter(Mandatory=$true)] [String] $ServiceName,

[parameter(Mandatory=$true)] [String] $VMName


Because you can’t pass a PSCredential object by using the Test Pane or the Start Runbook link, you must figure out how you can execute this runbook. There are two options I can see here. One, you can invoke this runbook from another runbook by passing a credential object. Or, you can change this credential parameter to a string, and add a command to the runbook’s script to return a credential asset from Azure Automation. Either way is a viable option, but you will need to think about the pros and cons of each. If you invoke the runbook from another runbook, you could cause a headache if you needed to troubleshoot the runbook because you will not be able to run it from the Test Pane directly. However, if you change it to a string and add the command to use an Azure Automation credential, you’ve now made this script unique to Azure Automation. Because Azure Automation is going to be the only place we will use this script, let’s go with option two.

Now as you can see in the following example, I’ve updated the parameter to be a string and changed its name. Then, I added a line to the parameters to return the Azure Automation asset based on the string provided.

Param (

[parameter(Mandatory=$true)] [String] $AzureSubscriptionName,

[parameter(Mandatory=$true)] [string] $AzureOrgIdCredentialAsset,

[parameter(Mandatory=$true)] [String] $ServiceName,

[parameter(Mandatory=$true)] [String] $VMName


$AzureOrgIdCredential = Get-AutomationPSCredential -Name $AzureOrgIdCredentialAsset

Now you can run this script by using the Test Pane. After the script finishes, you will see that it returns the WinRM Uri that you then can use to connect to your virtual machine.

Results from the script

This now leaves us with another choice. We can save this Uri to a variable in this script and then use the Invoke-Command cmdlet to run our command that checks the services. Or, we can call this runbook from another runbook, save the output as a variable, and then use the Invoke-Command cmdlet in this second runbook. This time the decision is a lot easier to make. If we go with option one, then this entire runbook with all the connection commands will be tied to this very specific task of querying the services. However, option two will let us to reuse this runbook for other automations that we may have in the future. Take, for example, if something changes in the way you need to return an Uri, you will only have to update one runbook, not every single runbook that you may have copy and pasted these commands into. You can see this all put together in the following example.

workflow Check-AzureVMServices {

Param (

[parameter(Mandatory=$true)] [String] $AzureSubscriptionName,

[parameter(Mandatory=$true)] [string] $AzureOrgIdCredentialAsset,

[parameter(Mandatory=$true)] [String] $ServiceName,

[parameter(Mandatory=$true)] [String] $VMName,

[parameter(Mandatory=$true)] [String] $VMCreds


# Get the WinRM Uri so that it can be used to connect to the VM $WinRmUri = Connect-AzureVM -AzureSubscriptionName $AzureSubscriptionName -ServiceName $ServiceName -VMName $VMName -AzureOrgIdCredential $AzureOrgIdCredentialAsset

# Get the credential asset with permissions to connect to the VM $Creds = Get-AutomationPSCredential -Name $VMCreds

InlineScript { # Execute the script block on the remote VM Invoke-Command -ConnectionUri $Using:WinRmUri `

-Credential $Using:Creds ` -ScriptBlock {Get-WMIObject win32_service -Filter "startmode = 'auto' AND state != 'running'"}



You might have noticed in this example that I used a PowerShell Workflow runbook. There are a couple of reasons for this. The first one is that you can only call an Azure Automation PowerShell Workflow runbook from another PowerShell Workflow runbook. The second is that PowerShell Workflow works great for platforms like Azure Automation because it can create Checkpoints, Pause, and Resume. For more information about this, refer to Ed’s previous post PowerShell Workflows: Job Engine.

Using existing scripts

The previous example is a great use case for using Azure Automation to connect to cloud-based resources, but what if you need to run scripts in your on-premises environments. Well, Azure Automation provides a great mechanism for that, the Hybrid Worker. When the Hybrid Worker is connected to your OMS subscription, you can execute Azure Automation runbooks locally. This provides multiple advantages such as source control, scheduling, secure credential storage, logging, and auditing. For example, you could set up a script to run via a scheduled task. But, you would need to keep a copy of that script somewhere so the server can access it and hope that nobody edits or deletes it. Plus, you will need to store your credentials in the task, or, even worse, directly in the script. Now, imagine that you need to do this for 100 or even 10 machines. It would be a logistical nightmare. With Azure Automation and the Hybrid Worker, you can achieve this very easily.

In this example we’re going to use one of the most downloaded scripts from the TechNet gallery, Delete files older than x-days – Cleanup Script. However, keep in mind, these steps can apply to pretty much any script that you currently have or plan to write. This script does exactly what the name implies, It can be used to delete files over a set number of days old. Even though this script was not designed for Azure Automation, we can download it from TechNet, import it to Azure Automation, and it is pretty much ready to run on my Hybrid Worker.

Importing an existing runbook

I said pretty much ready to run because there are a couple of things you need to do before you can execute the script on your Hybrid Worker. This first, and this goes for every script that you import, you need to publish it. All scripts import in a New state and cannot be run until they are published.

The Publish button

The second thing we’ll need to do for this particular script is to change the parameters that are a Switch type to a Boolean type. It is considered best practices to use Boolean in Azure Automation runbooks, and, in most cases, the Switch and Boolean parameters function the same inside the script. More details about why this is the case can be found in this post, but we will see one of the main reasons here shortly when we schedule this runbook to execute.

The updated parameters

Now that you have your parameter types updated and your runbook published, you are all set to schedule it to run on your Hybrid Worker. Just go to the runbook in Azure Automation and click Schedule.

The Schedule button

In the Schedule blade, click Link a schedule to your runbook, and set the schedule you would like for this script to run. In this example I am setting it to run every Sunday at 1 AM.

Setting the schedule values for the runbook

After you create the schedule, you can click Configure parameters and run settings. Here you can set the parameters that you want for this job.

Setting parameters for the job

There are a few things you’ll notice in the parameters. First, all the Boolean values have a drop-down to select True or False. Switch parameters do not do this so that is why it is advantageous to use Boolean values here. Also, at the very bottom, you’ll see an option for Run Settings. By switching this to Hybrid Worker, you can select the Hybrid Worker that you want this script to execute on.

Selecting Hybrid Worker for run settings

Once you set the parameters and click OK, the schedule is set. You can create multiple different schedules here, each with their own set of parameters and Hybrid Worker. You can view your existing schedules either at the runbook level or for all runbooks under Assets at the Automation Account level.

View scheduled runbooks

One final note, keep in mind that when these runbooks execute on your Hybrid Worker, they function like any other script. This means that for our previous example, you don’t necessarily need to create a Hybrid Worker for every server I want to run this script on. You can set the path to a network share, or you can do like we did in the first example and use Invoke-Command to execute on a remote system. I’ve said it before and I’ll continue to say, if you can dream, and you can script it, Azure Automation can do it.

Summary: Azure Automation is an extremely powerful component of the Microsoft Operations Management Suite. If you haven’t had the time to kick the tires on it yet, this is worth checking out. When you are looking for scripts to work from, utilize the list in this post to help you to get a jump-start on what you need to create.


Discussion is closed.

Feedback usabilla icon