0

I've written a script to help me delete Azure VMs and all the things that go with them (NICs, IPs, disks, etc.). Currently, the script works great, but as a VM can take 4-5 minutes to remove, I'm trying to update the script to run in parallel when removing multiple VMs.

The params of the script are as follows, with things like IDs and names stripped out for security's sake.

[CmdletBinding()]
Param (
    [Parameter(Mandatory=$false)]
    [string]$SubscriptionId = '[an id]',

    [Parameter(Mandatory=$true)]
    [string]$ResourceGroupName,

    [string]$VmName,

    [ValidateScript({ 
        if ($VmName -eq $null -or $VmName -eq '') {
            throw "The -Force switch cannot be used without specifying -VmName."
        }
        else { $true }
    })]
    [switch]$Force,

    [Parameter(Mandatory=$false)]
    [string]$ScriptPath
)

I need to use $ScriptPath because $PSScriptRoot isn't populated when calling a script using Start-Job.

I'm calling this script using the following:

$jobArgs = @($SubscriptionId,$ResourceGroupName,$VmName,$true)
$newJob = Start-Job -FilePath ".\Remove-VmAndAssets2.ps1" -ArgumentList $jobArgs

The reason I'm not sending the $ScriptPath over is because if I do, it claims it can't find a parameter to bind to. This seemed weird to me, so I cut it down to four arguments, and my first segment of code in the script is to dump the parameters to a file (since I can't see live output in a Job). Checking out the parameters that are taken in by the script after calling it as above, shows this:

    Subscription ID: [the right ID]
Resource Group Name: [the right name]
            VM Name: [the right name]
              Force: False
        Script Path: True

It's taking my fourth argument, $true, and passing it in to the fifth position. No matter what I do, I can't make something hit that -Force switch. I've tried "-Force:$true", "Force", "-Force", "-Force $true", "-Force=$true". Everything I could think of. I've tried sending the parameters in as "-SubscriptionId $SubscriptionID", etc, but then the values of the parameters end up being literally those strings.

What the heck am I missing?

Edit: Updated the ValidateScript on $Force to reflect what I actually have correctly.

Elestriel
  • 23
  • 4
  • `[bool]$force`? – 4c74356b41 Dec 06 '16 at 17:14
  • If I use `[bool]$Force`, I can't use it as a switch any more, though, right? I can't simply call it as `.\Remove-VmAndAssets2.ps1 -VmName 'SomeVM' -Force`. – Elestriel Dec 06 '16 at 17:16
  • why not? `if ($force) {}` or you could do a `[ValidateSet("True","False")]` – 4c74356b41 Dec 06 '16 at 17:18
  • You could also use multiple parameter sets to accommodate a switch or bool argument, so that way it would work in either your start-job setting or within code where it is being called directly. – Mike Garuccio Dec 06 '16 at 17:19
  • It would go from being called as `.\Remove-VmAndAssets2.ps1 -VmName 'SomeVM' -Force` to `.\Remove-VmAndAssets2.ps1 -VmName 'SomeVM' -Force $true`, which isn't exactly good practice. Further, this script can be called directly by users, so having switches instead of booleans is significantly cleaner. @MikeGaruccio you mean make a set as it is currently, and make a set that accepts a bool in the place of the Force switch? I hadn't thought about doing that. – Elestriel Dec 06 '16 at 17:20
  • Exactly, its not ideal but it would be transparent to end users and make your code work correctly in the job. – Mike Garuccio Dec 06 '16 at 17:25
  • well, I've just copied it to ise and it runs fine (with proper validation or without it), it also runs from the powershell. – 4c74356b41 Dec 06 '16 at 17:58

0 Answers0