Uploading WinAutomation Screenshots to Azure Container Storage Using Invoke-AzVMRunCommand

Microsoft Power Automate Flows, UI Flows, & Automation Runbooks: Part Six of a series


In this blog post, I will cover how I uploaded the WinAutomation screenshots to Azure container storage from a virtual machine that was created by an Azure Automation runbook without any human interaction using Invoke-AzVMRunCommand.


Now that the test environment was complete and the virtual machine (VM) could run WinAutomation processes, I needed to upload proof that the simulated user workflow executed correctly. During the Robotic Process Automation (RPA) simulated workflow, several screenshots were taken and stored on the virtual machine. I decided that these could be used as proof of successful execution. The critical step here is to upload the screenshots from the VM running WinAutomation to an Azure container before the test environment was deleted, which happens at the end of the flow.


In order to accomplish this, I decided I would first compress the screenshots into a zip file and use AzCopy to upload them. The virtual machine snapshot being used had AzCopy installed on it, but the virtual machine still needed the instructions to zip the screenshots and upload the zipped file to a specific destination. When performing these remote commands on the virtual machine, it is easy, just open a prompt or PowerShell window and execute the commands similar to the one below.


Compress-Archive -Path C:\Users\AzureUser\Desktop\WinAutomation\ - DestinationPath C:\Users\AzureUser\Desktop\WinAutomation; azcopy copy 'C:\Users\AzureUser\Desktop\WinAutomation' 'https://rpademoshare.blob.core.windows.net/winautomation-logs/?sv=2019-12-12&ss=bfqt&srt=co&sp=rwdlacupx&se=2020-10-30T21:16:54Z&st=2020-10-01T13:16:54Z&spr=https&sig=XJKXJKXUwuuwwnnw2B59PiClxeV8YIthG7qtjnYM%3D' –recursive


There are two PowerShell commands shown in the box above, separated by a semicolon. The first PowerShell command compresses and stores all of the screenshots in the WinAutomation folder on the desktop. The second PowerShell command tells Azcopy to copy all of the files in the WinAutomation directory and upload them to a blob container.


My initial thought was to run this command using a custom script extension, similarly to how I copied the Proccess.dat file over in Using Azure Custom Script Extensions to Copy an Updated WinAutomation Database for RPA. However, I learned the hard way that there is a limit of one custom script extension per virtual machine.


Microsoft Power Automate Flows_Part6_image 1


Azure cli provides the az vm run-command as a way of executing commands on an Azure virtual machine, but az cli commands are not allowed in automation runbooks. The solution I found was to use Invoke-AzRunCommand. Invoke-AzRunCommand allows command execution on Azure virtual machines and can be executed with automation runbooks.


Invoke-AzRunCommand requires several parameters for proper execution. One of those parameters is -ScriptPath, the path of the script to execute. I could have had script already on the machine, but that would be one more additional requirement needed on the base image and I wanted to limit base image requirements as much as possible. Instead, I had the runbook write the script at runtime so it could be executed from temp directory used by the runbook. The runbook that leverages Invoke-AzRunCommand looks like this.


#Required Parameters
[Parameter (Mandatory= $true)]
[string]$VMNAME = "$vendor-VM",
[string]$ResourceGroupName = "$vendor-ResourceGroup"

#Service Principal Authentication
Connect-AzAccount -CertificateThumbprint $Thumbprint -
ApplicationId $ApplicationId -Tenant $TenantId -ServicePrincipal

#Create Script
echo " Compress-Archive -Path C:\Users\AzureUser\Desktop\WinAutomation\ -
DestinationPath C:\Users\AzureUser\Desktop\WinAutomation;
azcopy copy 'C:\Users\AzureUser\Desktop\WinAutomation' 'https://rpademoshare.blob.core.windows.net/winautomation-logs/?sv=2019-12-12&ss=bfqt&srt=co&sp=rwdlacupx&se=2020-10-30T21:16:54Z&st=2020-10-01T13:16:54Z&spr=https&sig=XJKXJKXUwuuwwnnw2B59PiCretrYIthG7qtjnYM%3D' --recursive"

#Run Script
Invoke-AzVMRunCommand -ResourceGroupName 'RPA-RG-Test' -VMName 'RPA-
-CommandId 'RunPowerShellScript' -ScriptPath ".\script.ps1"


After the required parameters and service principal authentication sections, there are two main commands listed under #Create Script and #Run Script. Create Script creates a script.ps1 file that zips the screenshots and uploads the file. The Run Script command executes the script.ps1 file from the temp directory.


When the flow gets to this step, it will perform the actions in the runbook above.


Microsoft Power Automate Flows_Part6_image 2


This is what the process looks like at a high level:


Microsoft Power Automate Flows_Part6_image 3


Verification that the zip file has been uploaded can be done through the Azure console by viewing the container:


Microsoft Power Automate Flows_Part6_image 4


Current Flow


Microsoft Power Automate Flows_Part6_image 5


In the next and last post in this series I will cover how I used Power Automate Flows and Azure Runbooks to tear down Azure Resources and reply, with proof, to the original flow requestor that execution was successful.


Additional Information and Links:
Azcopy Getting Started: https://docs.microsoft.com/en-us/azure/storage/common/storage-use-azcopy-v10
Azcopy copy: https://docs.microsoft.com/en-us/azure/storage/common/storage-ref-azcopy-copy
Az VM Run-Command: https://docs.microsoft.com/en-us/cli/azure/vm/run-command?view=azure-cli-latest
Invoke-AzVMRunCommand: https://docs.microsoft.com/en-us/powershell/module/az.compute/invoke-azvmruncommand?view=azps-4.6.1
Custom Scrip Extension for Windows: https://docs.microsoft.com/en-us/azure/virtual-machines/extensions/custom-script-windows


Here's a review of related posts on this series:

Dan Kiraly
Senior Research Scientist | Optiv
Dan Kiraly is senior research scientist on Optiv’s R&D team. In this role he's responsible for use case development and the vetting of security products for Optiv.