Cloud Skills Blog

Closing the Skills Gap One Student at a Time

Bootstrapping a Virtual Machine with Windows Azure

Posted on: November 8, 2012 by Michael Washam

In my Advanced IaaS Talk at Build I showed a demo where you can configure a PowerShell script that can download a zip file with multiple actions (unzip or execute) that gives you similar functionality to a Windows Azure startup task for web and worker roles.

This is a very simple example but it does show some of the capabilities you can do.

The bootstrap.ps1 file below is the main script that is responsible for downloading the file from your storage account. You should create a directory called c:BootStrap and place the script inside and reference it from the startup task on your virtual machine.

In this demonstration I am pulling from a public storage container. If you want to contain anything secure in your you should modify the url below to use a shared access signature..


$rootpath = 'C:BootStrap'
$manifest = 'C:BootStrapWorkingmanifest.xml'
$workingdir = 'C:BootStrapWorking'
$downloaddir = ''
$packagesource = ''
function GetPayload()
    $retries = 5
	while($retries -gt 0)
		CheckFolder $workingdir
	    try {
		    $wc = New-Object System.Net.WebClient
		    $wc.DownloadFile($packagesource, $downloaddir)
	     catch [System.Net.WebException] {
		    # $_ is set to the ErrorRecord of the exception
	        if ($_.Exception.InnerException) {
	     	   $_.Exception.InnerException.Message | Out-File c:BootStraperror.txt -Append
	        } else {
	           $_.Exception.Message | Out-File c:BootStraperror.txt -Append
			Start-Sleep -Seconds 15
			$retries = $retries - 1
     UnzipFileTo $downloaddir $workingdir
function BootStrapVM()
  if((Test-Path HKLM:SoftwareVMBootStrap) -eq $true)
     Write-Host "Already Ran"
  [xml] $manifest = Get-Content $manifest
  $counter = 0
  $manifest.StartupManifest.Items.Item | foreach { 
	$action = $_.action 
	$path = $_."#text"
	$target = $ 
	$sourcefullpath = $workingdir + $path
	   "execute" {
		  Write-Host "Executing command: " $sourcefullpath
		  ExecuteCommand $sourcefullpath
	   "unzip" {
		  $sourcefullpath = $workingdir + $path
		  Write-Host "Unzipping " $sourcefullpath " to " $target 
	      UnzipFileTo $sourcefullpath $target
  New-Item -Path HKLM:Software -Name VMBootStrap –Force | Out-Null
  Set-Item -Path HKLM:SoftwareVMBootStrap -Value "ran" | Out-Null
function ExecuteCommand($commandpath)
	& $commandpath
function UnzipFileTo($sourcepath, $destinationpath)
	CheckFolder $destinationpath
	$shell_app = new-object -com shell.application
	$zip_file = $shell_app.namespace($sourcepath)
	$destination = $shell_app.namespace($destinationpath)
	$destination.Copyhere($zip_file.items(), 16)
function CheckFolder($path)
	if((Test-Path $path) -eq $false)
   		New-Item -ItemType directory -Path $path -Force | Out-Null

Here are two sample configs I put together: Enables Remote PowerShell Installs IIS, WebPI, MySQL and WordPress

The file contains a manifest.xml file and all of the entities you need to upload.

Example of the manifest.xml section of the
[sourcecode language=”xml”]
<Item action="execute">InstallRolesConfigureRoles.ps1</Item>
<Item action="unzip" target="c:webpi"></Item>
<Item action="execute">InstallPackagesEnableWebPI.cmd</Item>

All that is needed to configure the script to run when your VM boots is to configure a startup task using group policy.

Run: mmc
File -> Add/Remove Snapin
Select -> Group Policy Object Editor (Local Computer)
Expand -> Computer Configuration -> Windows Settings -> Scripts Startup/Shutdown

Once the script is configured you will need to change the execution policy on the virtual machine before you run sysprep and capture on your image otherwise the script will not execute on the next boot.

 Set-ExecutionPolicy RemoteSigned

Finally, if you do enable to the remote PowerShell task here is the command line you can use to connect.

Enter-PSSession -ComputerName {hostname} -Authentication Basic -Credential Administrator -UseSSL -SessionOption (New-PSSessionOption -SkipCACheck -SkipCNCheck)

leave a reply

Share this page


Connect with Opsgility