Using variables with invoke-command

This topic contains 2 replies, has 2 voices, and was last updated by Profile photo of Matt Allford Matt Allford 3 years, 5 months ago.

  • Author
    Posts
  • #12400
    Profile photo of Matt Allford
    Matt Allford
    Participant

    Hi all,

    Firstly, what a great resource. Thanks to everyone who dedicates their time to helping the powershell community. I am new to powershell and only which that I got on the powershell train 5 years ago when I entered IT.

    I am wondering if someone can assist and explain how to use a variable when using invoke-command. Here is a part of a script I am working on:

    $data = Import-Csv C:\Scripts\ExchangeServerData.csv
    foreach($d in $data){
    Invoke-Command -ComputerName $d.MailboxServer -ScriptBlock { 
        Get-Disk | Where-Object {$_.PartitionStyle -eq "Raw"} | Initialize-Disk -PartitionStyle MBR -PassThru | New-Partition -UseMaximumSize | Format-Volume -FileSystem NTFS -NewFileSystemLabel "$($d.ActiveDatabase)-Active" -Confirm:$false
        }
    }

    The issue I am having is towards the end of that main 'one-liner', where I have tried to use -NewFileSystemLabel "$($d.ActiveDatabase)-Active". The value from my CSV file under 'ActiveDatabase' did not get passed through and instead I ended up with a volume that has a label of '-Active'.

    Can someone shed some light on how to make this work and more importantly (for me), take a few mins to explain it as well. I understand that the variable does not work, because the remote machine does not know about the local variable.

    Also, is there a way to use powershell to assign this newly created volume a mount point instead of a drive letter?

    Cheers!

  • #12402
    Profile photo of Dave Wyatt
    Dave Wyatt
    Moderator

    The script block that you pass to Invoke-Command runs in a new PowerShell session on the remote computer; it doesn't automatically inherit the variables in your local scope (such as $d). When that script block runs, $d on the remote server hasn't been set, so it evaluates to $null.

    You can pass variables to a remote script block in two ways: You can use the -ArgumentList parameter to Invoke-Command, or, if both the local and remote computers are running PowerShell 3.0, you can use the "using" variable scope modifier. Personally, I prefer ArgumentList, even when all computers are running the latest version:

    $scriptBlock = {
        param ($activeDatabase)
        
        Get-Disk |
        Where-Object {$_.PartitionStyle -eq "Raw"} |
        Initialize-Disk -PartitionStyle MBR -PassThru |
        New-Partition -UseMaximumSize |
        Format-Volume -FileSystem NTFS -NewFileSystemLabel "${activeDatabase}-Active" -Confirm:$false
    }
    
    $data = Import-Csv C:\Scripts\ExchangeServerData.csv
    foreach($d in $data){
        Invoke-Command -ComputerName $d.MailboxServer -ScriptBlock $scriptBlock -ArgumentList $d.ActiveDatabase
    }
    
  • #12451
    Profile photo of Matt Allford
    Matt Allford
    Participant

    Awesome thanks so much Dave. I'll have to do some more reading into arguments with invoke-command.

You must be logged in to reply to this topic.