1

I am having an issue with passing variables to a remote powershell session and I've searched everywhere on the internet I can think of so I'm hoping someone out there can help. I have a function calling a job which is telling it to start a scriptblock

What I'm trying to do is write a script to allow me to failover clusters from one VM. It works fine if everything is hardcoded but that means I have to change the script for every failover and that just won't save me anytime at all.

$Computer = Server1
$Clustergrp = Cluster1


function FAILOVER(){
$job = Start-Job -scriptblock $JobScript
do {[System.Windows.Form.Application]::DoEvent() } until ($Job.State -eq "Completed")


$JobScript = 
{
Invoke-Command -ComputerName $using:Computer -ScriptBlock {Move-ClusterGroup -Name $using:Clustergrp}
}

What am I missing here? Help please!

I've tried using arguments and $using:variable but nothing seems to work. Yet if I hardcode everything in the scriptblock it works everytime.

I've also tried just using -ComputerName $Computer -ScriptBlock{.....} but that didn't work either.

Progman
  • 16,827
  • 6
  • 33
  • 48
Todd
  • 25
  • 4

2 Answers2

1

General points:

  • Invoke-Command has an -AsJob parameter, so there's no need for creating a job with Start-Job first.

  • To wait for a job's completion, use the Wait-Job cmdlet.

  • If you want to wait right away, i.e. if you want synchronous execution to begin with, simply omit -AsJob.

    • Note that Invoke-Command's -ComputerName parameter accepts an array of computer names that are then targeted in parallel.

As for what you tried:

You're nesting two out-of-runspace (out-of-process) scopes, which also requires nesting the use of the $using: scope:

$Computer = 'Server1'
$Clustergrp = 'Cluster1'

$JobScript = {
  # Create a *local* variable from the caller's
  # $Clustergrp value, so it can again be referenced with
  # $using: in the remotely executing Invoke-Command script block.
  $Clustergrp = $using:Clustergrp
  Invoke-Command -ComputerName $using:Computer -ScriptBlock { 
    Move-ClusterGroup -Name $using:Clustergrp
  }
}

function FAILOVER {
  $job = Start-Job -ScriptBlock $JobScript
  $job | Wait-Job
}
mklement0
  • 382,024
  • 64
  • 607
  • 775
  • Thank you for your answer / solution. I thought it had to do with a scoping issue but I was too deep in the weeds to see it! Thank you Mklement0 – Todd Jun 06 '23 at 15:08
  • Glad to hear it helped, @Todd; my pleasure. (It _is_ a scoping issue of sorts: the `Invoke-Command` script block sees only the job script block's own variables via `$using:`) – mklement0 Jun 06 '23 at 15:14
  • 1
    I will definitely remember this for next time! Thanks again! – Todd Jun 06 '23 at 15:34
0
Invoke-Command -ComputerName $using:Computer -ArgumentList $arg1 -ScriptBlock {param($arg) Move-ClusterGroup -Name $arg[0]}
Dom
  • 168
  • 8
  • That didn't seem to work. Was $arg1 supposed to be $arg[1], I tried that too and that didn't work. – Todd Jun 05 '23 at 19:04
  • also tried `-ArgumentList $args[1] -ScriptBlock {param($arg) Move-ClusterGroup -Name $args[0]}` – Todd Jun 05 '23 at 19:16
  • Invoke-Command -ComputerName $Computer -ArgumentList $arg1 -ScriptBlock {param($arg) Move-ClusterGroup -Name $arg[0]} – Dom Jun 05 '23 at 19:57
  • Dom, nope that didn't work either. I have a bunch of write-hosts in the function that show that $Clustergrp and $Computer have values. – Todd Jun 05 '23 at 20:06
  • I can upload the entire code if that will help. – Todd Jun 05 '23 at 20:31
  • 2
    Thank you for contributing to the Stack Overflow community. This may be a correct answer, but it’d be really useful to provide additional explanation of your code so developers can understand your reasoning. This is especially useful for new developers who aren’t as familiar with the syntax or struggling to understand the concepts. **Would you kindly [edit] your answer to include additional details for the benefit of the community?** – Jeremy Caney Jun 06 '23 at 00:58
  • What I'm trying to achieve is to be able to select from a drop down list, a cluster node and have powershell fail that cluster over to the other server while displaying a progress bar so it doesn't look like its stuck and then let me know the status of said failover. Was it successful or did it fail. I have the code working from the command line for a single cluster so I know the failover cluster part works. And I would of edited my answer as requested but there were too many edits at the time and I wanted to get my explanation out here. – Todd Jun 06 '23 at 12:34