You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PowerShell Workflow中Azure VM脚本报unexpected Token错误,求修正

Fixing PowerShell Workflow Errors for Azure VM Parallel Startup

Let's break down the issues in your script and fix them step by step:

1. Immediate Syntax Error Fix

The error Unexpected Token in Expression or Statement on the line $tags2 ['ShutdownSchedule_AllowStop'] = "$False"; comes down to whitespace strictness in PowerShell Workflows. Unlike regular PowerShell, Workflows don't allow spaces between a variable and its indexing brackets.

Change this:

$tags2 ['ShutdownSchedule_AllowStop'] = "$False";

To this:

$tags2['ShutdownSchedule_AllowStop'] = $false; # Use boolean $false instead of string "$False" for better compatibility

Note: Using the boolean $false instead of a string "$False" is better practice, as Azure resources expect native boolean values for tag fields when applicable.

2. Additional Logic & Scope Issues

Your script has a few other hidden problems that will prevent it from working correctly even after fixing the syntax error:

a. Incorrect Pipeline Variable Usage

Inside your ForEach ($vm in $vms) loop, you're using $_.Tags—but $_ (the pipeline automatic variable) doesn't exist here. Since you're iterating with a named variable $vm, you need to reference $vm.Tags instead.

b. Misplaced Set-AzureRmResource Command

You're calling Set-AzureRmResource outside the inner VM loop, which means it will only apply tag changes to the last VM processed in the loop. Move this command inside the ForEach ($vm in $vms) block to update every VM's tags.

c. Parallel Loop Variable Scope

When using ForEach -Parallel in a Workflow, you need to ensure the variable containing your VM list is accessible in the parallel execution scope. First, collect all target VMs into a single array outside the parallel loop, then use the $Using: scope modifier to reference it from within the parallel block.

d. Handling VMs with No Existing Tags

If a VM has no existing tags, $vm.Tags will be $null, which will cause errors when trying to modify it. We'll add a check to create an empty hashtable in this case.

Fixed Complete Script

workflow Set-AzureRmTags-and-Start {
    [CmdletBinding()]
    Param(
        [Parameter(Mandatory=$True)]
        [string]$VmRG
    )

    $Start = Get-Date
    Write-Output "Start Time: $Start"

    # Collect all matching resource groups
    $VmRGs = Get-AzureRmResourceGroup | Where-Object { $_.ResourceGroupName -like "*$VmRG*" }
    
    # Initialize array to hold all VMs for parallel startup later
    $allVMs = @()

    foreach ($rg in $VmRGs) {
        $VMs = Get-AzureRmVM -ResourceGroupName $rg.ResourceGroupName
        $allVMs += $VMs

        ForEach ($vm in $VMs) {
            # Handle VMs with no existing tags by creating an empty hashtable
            $tags2 = if ($vm.Tags) { $vm.Tags.Clone() } else { @{} }
            # Update the tag with a boolean value
            $tags2['ShutdownSchedule_AllowStop'] = $false;
            
            # Apply tag changes to the current VM
            Set-AzureRmResource -ResourceName $vm.Name `
                                -ResourceGroupName $vm.ResourceGroupName `
                                -ResourceType "Microsoft.Compute/virtualMachines" `
                                -Tag $tags2 `
                                -Force `
                                -Verbose
        }
    }

    $Middle = Get-Date
    Write-Output "Time Taken To Assign Tags: $((Get-Date) - $Start).Minutes Minutes"

    # Parallel VM startup using $Using: to access the allVMs array from workflow scope
    ForEach -Parallel ($vm in $Using:allVMs) {
        Start-AzureRmVM -Name $vm.Name `
                        -ResourceGroupName $vm.ResourceGroupName `
                        -Verbose `
                        -Confirm:$false
    }

    $End = Get-Date
    Write-Output "Time Taken To Start VMs: $((Get-Date) - $Middle).Minutes Minutes"
    Write-Output "Total Time Taken: $((Get-Date) - $Start).Minutes Minutes"
}

Key Changes Explained

  • Fixed the whitespace in hashtable indexing and switched to native boolean $false.
  • Replaced $_.Tags with $vm.Tags to correctly reference the current VM's tags.
  • Moved Set-AzureRmResource inside the VM loop to ensure every VM gets updated tags.
  • Collected all VMs into $allVMs and used $Using:allVMs to make the array accessible in the parallel loop.
  • Added logic to handle VMs with no existing tags, preventing null reference errors.

内容的提问来源于stack exchange,提问作者Norrin Rad

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:47:37