How Can We Help?
< Back
You are here:
Print

Here string and variable substitution

As mentioned in another Dive (see Here strings and the ExpandString method) Here strings are a convenient way to prepare scripts you are submitting through Invoke-VMScript or Invoke-VMScriptPlus.

But there are some caveats you should be aware off. Most of these are how the variable substitution will work when you call the ExpandString method.

  • For variables you don’t want to be substituted, you need to escape the dollar sign with a back-tick. Note that this is also true for the Booleans $true and $false.

  • Put strings in quotes, otherwise PowerShell will try to interpret them as cmdlets or functions.

  • When referencing properties from an object, use the correct notation.

4 Comments

    Another Rhoads

    LucD,

    I’ve followed you for many years now and have appreciated you sharing your expertise.

    Nowadays I’m still finding your help!

    My example:

    Tried to use escaped variables embedded into the here-string but could
    not get the string to update during the ForEach-Object loop so using
    “{0} -f placeholders”

    *** Example – NOW working – of using escaped variables:

    ${HelpTop} = @”
    \\hshome\Shared\IS\TSS\ESG\Backup\!\Dev\PowerShell\Help$(${PSItem}.Name) cmdlet.txt

    Open explorer to all help files
    Start \\hshome\Shared\IS\TSS\ESG\Backup\!\Dev\PowerShell\Help\

    Get-Help $(${PSItem}.Name) -Full | clip

    “@

    ${HelpTop}
    ———-
    \\hshome\Shared\IS\TSS\ESG\Backup\!\Dev\PowerShell\Help\$(${PSItem}.Name) cmdlet.txt

    Open explorer to all help files
    Start \\hshome\Shared\IS\TSS\ESG\Backup\!\Dev\PowerShell\Help\

    Get-Help $(${PSItem}.Name) -Full | clip

    ———-

    (Get-Command -Verb Write).Where({${PSItem}.CommandType -eq “Cmdlet”}) |
    ForEach-Object {
    $ExecutionContext.InvokeCommand.ExpandString(${HelpTop} )
    }

    Get-Command -Module RobocopyPS |
    ForEach-Object {
    $ExecutionContext.InvokeCommand.ExpandString(${HelpTop} )
    }

    *** Example – working – of using placeholders (just one {0}):

    ${HelpTop} = @”
    \\hshome\Shared\IS\TSS\ESG\Backup\!\Dev\PowerShell\Help\{0} cmdlet.txt

    Open explorer to all help files
    Start \\hshome\Shared\IS\TSS\ESG\Backup\!\Dev\PowerShell\Help\

    Get-Help {0} -Full | clip

    “@

    (Get-Command -Verb Write).Where({${PSItem}.CommandType -eq “Cmdlet”}) |
    ForEach-Object {
    ${HelpTop} -f $(${PSItem}.Name)
    }

    Get-Command -Module RobocopyPS |
    ForEach-Object {
    ${HelpTop} -f $(${PSItem}.Name)
    }

    Get-Command -Module RobocopyPS |
    ForEach-Object {
    ${HelpTop} -f $(${PSItem}.Name) | Out-File -FilePath \\hshome\Shared\IS\TSS\ESG\Backup\!\Dev\PowerShell\Help\”$(${PSItem}.Name) cmdlet.txt” -Force
    Get-Help $(${PSItem}.Name) -Full |
    Out-File -FilePath \\hshome\Shared\IS\TSS\ESG\Backup\!\Dev\PowerShell\Help\”$(${PSItem}.Name) cmdlet.txt” -Append
    “========== nnn" | Out-File -FilePath \\hshome\Shared\IS\TSS\ESG\Backup\!\Dev\PowerShell\Help\"$(${PSItem}.Name) cmdlet.txt" -Append
    }

    (Get-Command -Verb Write).Where({${PSItem}.CommandType -eq "Cmdlet"}) |
    ForEach-Object {
    ${HelpTop} -f $(${PSItem}.Name)
    }

    (Get-Command -Verb Write).Where({${PSItem}.CommandType -eq "Cmdlet"}) |
    ForEach-Object {
    ${HelpTop} -f $(${PSItem}.Name) | Out-File -FilePath \\hshome\Shared\IS\TSS\ESG\Backup\!\Dev\PowerShell\Help\"$(${PSItem}.Name) cmdlet.txt" -Force
    Get-Help $(${PSItem}.Name) -Full |
    Out-File -FilePath \\hshome\Shared\IS\TSS\ESG\Backup\!\Dev\PowerShell\Help\"$(${PSItem}.Name) cmdlet.txt" -Append
    "==========
    nnn” | Out-File -FilePath \\hshome\Shared\IS\TSS\ESG\Backup\!\Dev\PowerShell\Help\”$(${PSItem}.Name) cmdlet.txt” -Append
    }

    Levent

    THANK YOU SIR, that worked perfectly 🙂

    Levent

    Hi, Thanks for your work.

    I’m trying to use Invoke-VMScript to run the linux sed command on VM guest.
    I could really do with your expertise to help ?
    Problem I’m having, is that it doesn’t like the double-quotes ” and is not using the variable :
    $scripttext1=”sed -i -e “s/$vm.templateip/$vm.guestip/g” /etc/sysconfig/network-scripts/ifcfg-eth0 && cat /etc/sysconfig/network-scripts/ifcfg-eth0″
    Write-host “$scripttext1”

    Get-VM $vm.guestname | Invoke-VMScript -ScriptText $($scripttext1) -GuestCredential $template_root_credential

    =====
    Output :
    PS F:\vmscripts> .\test_script.ps1
    At F:\vmscripts\test_script.ps1:61 char:27
    + … “sed -i -e “s/$vm.templateip/$vm.guestip/g” /etc/sysconfig/network-sc …
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    Unexpected token ‘s/$vm.templateip/$vm.guestip/g” /etc/sysconfig/network-scripts/ifcfg-eth0 && cat /etc/sysconfig/network-scripts/ifcfg-eth0″‘ in expression or statement.
    + CategoryInfo : ParserError: (:) [], ParseException
    + FullyQualifiedErrorId : UnexpectedToken

    I would sincerely appreciate any assistance you may be able to provide ?

    THANKS

      LucD

      Hi Levent,
      When you want to mention properties of an object in a string, you need to enclose them in $().
      That way PowerShell knows how to substitute them.

      Try something like this

      $scripttext = @'
      sed -i -e "s/$($vm.templateip)/$($vm.guestip)/g" /etc/sysconfig/network-scripts/ifcfg-eth0; cat /etc/sysconfig/network-scripts/ifcfg-eth0
      '@

      $scripttext1 = $ExecutionContext.InvokeCommand.ExpandString($scripttext)

      Write-host "$scripttext1"

      Get-VM $vm.guestname |
      Invoke-VMScript -ScriptText $scripttext1 -GuestCredential $template_root_credential

Leave a Reply

Your email address will not be published. Required fields are marked *

*
*

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Table of Contents