2

I'm trying to learn how to use Workflow in Powershell and how to get around the restrictions applied to variables (And objects in my case). But I'm facing an issue when I'm trying to modify a workflow-scope object from an InlineScript activity.

What the code does :

  1. Set $VMSettings with a Json file content. This file contains settings for VM that I want to create in Hyper-V;
  2. Set $VMHostSettings with the Hyper-V host parameters;
  3. Start a Foreach -Parallel loop to work on each VM in parallel:
    1. In sequence, I write the name and the path to the VM from the Workflow scope;
    2. In an InlineScript activity, I'm writing the name of the VM with $using as a test with how scopes work;
    3. If $VM.path is empty, I'm starting a new InlineScript activity in which I:
      1. Set a new variable with the content of the $VM variable from the workflow scope;
      2. Change the path property of this new variable and display it;
    4. I display the workflow-scope $VM.path again to see if something has changed.

Here's the code:

Workflow New-VMFromJson {
    $VMSettings = Get-Content -Raw -Path $ConfigurationFile | ConvertFrom-Json
    $VMHostSettings = Get-VMHost

    ForEach -Parallel ($VM In $VMSettings.virtualMachines) {          
        sequence {
            'Name form Workflow: ' + $VM.name
            'Path form Workflow: ' + $VM.path
            InlineScript {
                Write-Host "Name from InlineScript (using): $($using:VM.name)"
            }
            # If VM path is not set, use default Hyper-V settings instead
            If (!$VM.path) {            
                InlineScript {
                $VM = $using:VM                   
                $VM.path = $($using:VMHostSettings.VirtualMachinePath) + 'Virtual Machines'
                'Name from Inlinescript: ' + $VM.name
                'Path from Inlinescript: ' + $VM.path
            }

            'Path form Workflow again: ' + $VM.path               
            }
        }        
    }
    Write-Verbose "End of Workflow"
}
New-VMFromJson -Verbose

So far, everything is good when I feed the workflow with data where $VM.path is empty (So I can enter the If block) and I get this result :

VERBOSE: 7fc31127-bee1-445f-acaa-275cc5c0c39d:[localhost]:Workflow started !
Name form Workflow: NewVM2
Name form Workflow: NewVM
Path form Workflow:
Path form Workflow:
Name from InlineScript (using): NewVM2
Name from Inlinescript: NewVM2
Path from Inlinescript: C:\Hyper-V\VM\Virtual Machines
Path form Workflow again:
Name from InlineScript (using): NewVM
Name from Inlinescript: NewVM
Path from Inlinescript: C:\Hyper-V\VM\Virtual Machines
Path form Workflow again:
VERBOSE: 7fc31127-bee1-445f-acaa-275cc5c0c39d:[localhost]:End of Workflow

We can see that everything works as it should. The InlineScript-scope modification of the new $VM variable has no impact on the workflow-scope variable of the same name and that's a normal behavior.

Now, if I want to modify the workflow-scope variable from the InlineScript activity, I get some problems. I have been following information from this Microsoft Doc page where they show this piece of code:

workflow Test-Workflow
{
  $a = 3

  # Changes to an InlineScript variable do not affect
  # the workflow variable.
  InlineScript {$a = $using:a+1; "Inline A = $a"}
  "Workflow A = $a"

  # To change the value in workflow scope, return the new value.
  $a = InlineScript {$a = $Using:a+1; $a}
  "Workflow New A = $a"
}   

PS C:\> Test-Workflow
Inline A = 4
Workflow A = 3
Workflow New A = 4

So I have been changing my own code to do this instead :

If (!$VM.path) { 
      $VM = InlineScript {
        $VM = $using:VM
        $VM.path = $($using:VMHostSettings.VirtualMachinePath) + 'Virtual Machines'                
        Return $VM
    }
}

I'm setting the workflow-scope $VM variable with the content of the InlineScript activity. In this activity, I'm still copying the content of the workflow-scope variable to a InlineScript-scope one, doing changes to the InlineScript-scope variable and then, I'm returning it.

When doing this, I get the following error : Property 'path' cannot be found on this object; make sure it exists and is settable. This error appears at the line corresponding to $VM = InlineScript {. I should also mention that I get this result after running the script. Like if the workflow-scope $VM variable was erased instead of set:

VERBOSE: 7fc31127-bee1-445f-acaa-275cc5c0c39d:[localhost]:Workflow started !
Name form Workflow: 
Name form Workflow: 
Path form Workflow:
Path form Workflow:
Name from InlineScript (using): 
Name from Inlinescript: 
Path from Inlinescript: 
Path form Workflow again:
Name from InlineScript (using): 
Name from Inlinescript: 
Path from Inlinescript: 
Path form Workflow again:
VERBOSE: 7fc31127-bee1-445f-acaa-275cc5c0c39d:[localhost]:End of Workflow

Any clue on what I am doing wrong ?

6
  • When you assign $VM = $using:VM, I suspect the type is unknown, so you're trying to delve into a property that doesn't actually exist. You'll need to use $VM|Add-Member ... to add the .path and then assign it. Commented Mar 22, 2018 at 14:53
  • @TheIncorrigible1 When I check the type during the first part (Just reading the values), I get System.Object which is fine. If I try while I'm doing the $VM = InlineScript {...}, I get nothing as if the script was even failing to enter the InlineScript activity. Commented Mar 22, 2018 at 15:31
  • Try using .GetType() or $VM | Get-Member to see if the object is actually being passed. Certain objects are by reference versus value and may interact differently than you expect Commented Mar 22, 2018 at 15:33
  • No more luck with Get-Member when trying to set the variable. It works fine when I'm just reading the values though. By the way, I have added the result when I'm trying to set the workflow-scope variable. It looks like it is emptied instead. Commented Mar 22, 2018 at 15:41
  • Sorry I'm unable to help further. I don't see the workflow framework used and would probably do something with jobs/runspaces for parallelization instead. Commented Mar 22, 2018 at 15:43

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.