UpdateManagement-RunCommand.ps1
<#PSScriptInfo .VERSION 1.0 .GUID 5494503d-d282-435f-99c4-575a66335141 .AUTHOR zachal .COMPANYNAME Microsoft .COPYRIGHT .TAGS UpdateManagement, Automation .LICENSEURI .PROJECTURI .ICONURI .EXTERNALMODULEDEPENDENCIES ThreadJob .REQUIREDSCRIPTS .EXTERNALSCRIPTDEPENDENCIES .RELEASENOTES .PRIVATEDATA #> <# .DESCRIPTION This script is intended to be run as a part of Update Management Pre/Post scripts. It uses RunCommand to execute a PowerShell script to stop a service. #> <# .SYNOPSIS Stop a service on an AzureRM using RunCommand .DESCRIPTION This script is intended to be run as a part of Update Management Pre/Post scripts. It uses RunCommand to execute a PowerShell script to stop a service. .PARAMETER SoftwareUpdateConfigurationRunContext This is a system variable which is automatically passed in by Update Management during a deployment. #> #requires -Modules ThreadJob param( [string]$SoftwareUpdateConfigurationRunContext ) #region BoilerplateAuthentication #This requires a RunAs account $ServicePrincipalConnection = Get-AutomationConnection -Name 'AzureRunAsConnection' Add-AzureRmAccount ` -ServicePrincipal ` -TenantId $ServicePrincipalConnection.TenantId ` -ApplicationId $ServicePrincipalConnection.ApplicationId ` -CertificateThumbprint $ServicePrincipalConnection.CertificateThumbprint $AzureContext = Select-AzureRmSubscription -SubscriptionId $ServicePrincipalConnection.SubscriptionID #endregion BoilerplateAuthentication #If you wish to use the run context, it must be converted from JSON $context = ConvertFrom-Json $SoftwareUpdateConfigurationRunContext $vmIds = $context.SoftwareUpdateConfigurationSettings.AzureVirtualMachines $runId = $context.SoftwareUpdateConfigurationRunId if (!$vmIds) { #Workaround: Had to change JSON formatting $Settings = ConvertFrom-Json $context.SoftwareUpdateConfigurationSettings #Write-Output "List of settings: $Settings" $VmIds = $Settings.AzureVirtualMachines #Write-Output "Azure VMs: $VmIds" if (!$vmIds) { Write-Output "No Azure VMs found" return } } #The script you wish to run on each VM $scriptBlock = @" Stop-Service -Name "AudioSvc" "@ $scriptPath = "$runID.ps1" #The cmdlet only accepts a file, so temporarily write the script to disk using runID as a unique name Out-File -FilePath $scriptPath -InputObject $scriptBlock $scriptFile = get-item $scriptpath $fullPath = $scriptfile.fullname $jobIDs= New-Object System.Collections.Generic.List[System.Object] #Start script on each machine $vmIds | ForEach-Object { $vmId = $_ $split = $vmId -split "/"; $subscriptionId = $split[2]; $rg = $split[4]; $name = $split[8]; Write-Output ("Subscription Id: " + $subscriptionId) $mute = Select-AzureRmSubscription -Subscription $subscriptionId Write-Output "Invoking command on '$($name)' ..." $newJob = Start-ThreadJob -ScriptBlock { param($resourceGroup, $vmName, $scriptPath) Invoke-AzureRmVMRunCommand -ResourceGroupName $resourceGroup -Name $VmName -CommandId 'RunPowerShellScript' -ScriptPath $scriptPath} -ArgumentList $rg, $name, $fullPath $jobIDs.Add($newJob.Id) } $jobsList = $jobIDs.ToArray() if ($jobsList) { Write-Output "Waiting for machines to finish executing..." Wait-Job -Id $jobsList } foreach($id in $jobsList) { $job = Get-Job -Id $id if ($job.Error) { Write-Output $job.Error } } #Clean up our variables: Remove-Item -Path "$runID.ps1" |