The introduction of agents and extensions bring a lot of possibilities to virtual machines in Azure. The CustomScript extension let you run one or a set of scripts on a virtual machine. The usage is simple, you upload one or many scripts & their required files if any to Azure Storage, then you invoke the CustomScript extension. The extension will download the designated files on the virtual machine in the extension directory: C:\Packages\Plugins\Microsoft.Compute.CustomScriptExtension{version-number}\Downloads{iteration} and will execute the script designed to run.

There can be just one

You might be tempted to think that you'll create a script to install a database server, another one for configuring IIS and another one to join the machine to a domain and invoke 3 times the extension. If you call the Set-AzureVMCustomScriptExtension cmdlet and you already used a CustomScript extension with a difference reference name on that particular VM, you'll get this error:

Set-AzureVMCustomScriptExtension : BadRequest: Multiple extensions per handler not supported for OS type 'Windows'.
Extension 'InstallDevVMPowerShellScript' with handler 'Microsoft.Compute.CustomScriptExtension' already added.
At D:\wkspc\Repos\ARMProvisioning\ProofOfConcepts\VMInTheCloud\v2.1\Invoke-VMExtension.ps1:13 char:1

  • Set-AzureVMCustomScriptExtension -ResourceGroupName TestARM95165 -VMN ...
  •   + CategoryInfo          : CloseError: (:) [Set-AzureVMCustomScriptExtension], CloudException
      + FullyQualifiedErrorId : Microsoft.Azure.Commands.Compute.SetAzureVMCustomScriptExtensionCommand

How can I do this?

Simple, instead of calling the CustomScript extension multiple times for different scripts, specify all your scripts using the -Filename or -FileUri parameters.

Here is an example where you have 3 scripts, script1.ps1, script2.ps1 and script3.ps1. The 3 files will be automatically downloaded in the download folder by the extension. Since script1.ps1 is designated to run, it is this script that'll be launched by the extension. Here we have 3 scripts but what you specify in the -Filename or -FileUri parameters can be zip files or any other file types that you want. The minimum you need is one script to download and run.

PS C:\> Set-AzureVMCustomScriptExtension -VM $x -ContainerName 'test' -FileName 'script1.ps1','script2.ps1','script3.ps1' -Run 'script1.ps1' -Argument 'arg1 arg2' | Update-AzureVM

-FileUri is helpful when you want to use blobs with a SAS token. That way you don't have to specify any storage key or storage context like when you use the -Filename parameter.