This article will focus on a very common task done when administering Virtual Machines (VM) in Azure: run a PowerShell script in these Virtual Machines.
In order to run PowerShell scripts in Azure VMs, there are many options that can be used:
The first two options have a limitation; You have to open ports on the Virtual Machine to remotely connect to it. Therefore, if you want to run a .ps1 script automatically without opening any ports you need to find another solution.
The third option, schedule a task on the VM, is not the best one as you may want to run the PowerShell script on demand.
It leaves us with another very interesting option which is to use the Custom Script Extension.
This feature uses the VM agent to allow you to ask the Virtual Machine to automatically download a script from somewhere (ex: A Blob Storage) and ask it to execute the
PowerShell script. There are many references (https://azure.microsoft.com/en-us/blog/automating-vm-customization-tasks-using-custom-script-extension/) on how to use PowerShells, however, none of the references actually cover using C# and specifically for ARM Virtual machine.
Let’s start to write code to execute a simple line of PowerShell inside an ARM Virtual Machine with closed ports.
The CmdLet, also called AzureVMCustomScriptExtension, allows you to specify a Virtual Machine Name and the path of the script to execute. An easy way to write .NET code when you know there is a CmdLet that exists is to open IlSpy and look at the code.
In our case, for ARM Virtual Machines, you will be able to open the assembly from the following path:
C:\Program Files (x86)\Microsoft SDKs\Azure\PowerShell\ResourceManager\AzureResourceManager\AzureRM.Compute
Open the Microsoft.Azure.Commands.Compute in ILSpy and open the class named SetAzureVMCustomScriptExtensionCommand (note: the CmdLet Name is AzureRmVMCustomScriptExtension, however, the actual name of the method has no RM in in it).
As you can see, there is an ExecuteCmdlet method that will contain exactly the code that we need:
Basically, It creates an object of type VirtualMachineExtension that contains all the parameters. It then uses a Virtual Machine Client (include this nugget: https://www.nuget.org/packages/Microsoft.Azure.Management.Compute/11.2.0-prerelease. If you are not familiar with this library, you should refer to: http://www.bradygaster.com/getting-started-with-the-windows-azure-management-libraries) to ask the Virtual Machine to execute the PowerShell script.
In this case, the CmdLet allows you to specify the URL of the script to execute. If you just want to execute a few lines of PowerShell without having to create a separate file, you can specify it directly in the Settings property of the VirtualMachineExtension object:
string text = string.Format(“powershell \”{0}\””, “THE POWERSHELL COMMAND”);
string text = string.Format(“powershell \”{0}\””, “THE POWERSHELL COMMAND”);
Hashtable hashtable = new Hashtable();
hashtable.Add(“commandToExecute”, text ?? “”);
VirtualMachineExtension extensionParameters = new
VirtualMachineExtension
{
Location = currentVM.Location,
Publisher = “Microsoft.Compute”,
VirtualMachineExtensionType = “CustomScriptExtension”,
TypeHandlerVersion = “1.4”,
Settings = hashtable,
AutoUpgradeMinorVersion = new
bool?(true)
};
VirtualMachineExtension busyExtensionTest = client.VirtualMachineExtensions.Get(
currentVMRG,currentVM.Name,
“WinRMCustomScriptExtension”, “instanceView”
);
With only these few lines of C# you can start any .ps1 script.
View more on https://www.cloudockit.com