Run script inside Azure VM from PowerShell

Today I was working on a way to initialize and format disks inside an Azure VM from PowerShell, specifically outside the VM itself.

The two most common ways to accomplish this are:

One of my key requirements was to not have the VM itself go and grab the script file to run; I wanted to pass a scriptblock to my VM from PowerShell instead. This immediately ruled out Set-AzVMCustomScriptExtension, as it needs a file that is accessible to the VM in order to run.

I had originally thought the same about Invoke-AzVmRunCommand. The example I saw for the ‘-ScriptPath’ parameter were all from a storage account or something similar. However after testing, I found that this ScriptPath could be local to MY computer, where I was running the PowerShell, not the VM itself. The command will inject the contents of the script file into the VM.

In order to simulate the “scriptblock” effect without having too many files, I put my code into a script file at runtime (so that it would be wherever the user was running the prompt), referenced it, and then removed it afterwards, like this:

# Build a command that will be run inside the VM.
$remoteCommand =
#Get first disk that is raw with the lowest disk number (because we may not know what number it will be)
# F volume
Get-Disk | Where-Object partitionstyle -eq 'raw' | Sort-Object Number | Select-Object -first 1 | Initialize-Disk -PartitionStyle GPT  -confirm:$false -PassThru |
New-Partition -DriveLetter 'F' -UseMaximumSize |
Format-Volume -FileSystem NTFS -NewFileSystemLabel "F volume" -Confirm:$false
# Save the command to a local file
Set-Content -Path .\DriveCommand.ps1 -Value $remoteCommand
# Invoke the command on the VM, using the local file
Invoke-AzureRmVMRunCommand -Name $ -ResourceGroupName $vm.ResourceGroupName -CommandId 'RunPowerShellScript' -ScriptPath .\DriveCommand.ps1
# Clean-up the local file
Remove-Item .\DriveCommand.ps1


4 thoughts to “Run script inside Azure VM from PowerShell”

  1. Hello,
    Thanks for your ‘remoteCommand’ option for setting the -ScriptPath, it really helped me as I was searching for a whole day before finding this. What I cannot figure out though is how to get the complete output of the script, every command line script that I put in the ‘script block’ comes back with the same result, even when I put wrong code. The script does what I want it to do, but the Output is always the same and is not detailed enough for me. I am trying to get the console output from the VM, do you have any idea how to do this.

    1. With the PowerShell script running inside the VM in my example, I’m not actually putting anything on the output stream, so I am not expecting to receive anything back from where I’m actually calling Invoke-AzVMRunCommand (direct or automation runbook).

      What you need to make sure you’re doing is putting what you want to receive as output on the output stream, inside the script, with “Write-Output”.

      Here’s an example from stackoverflow.

Leave a Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.