0

Input:

I want to print variable $VarX value by referencing its name through another variable, $VarA:


Code:

$VarX = "They can swim"
$VarA = '$VarX'
"What do dogs do? $($VarA)"

I also tried this:

$VarX = "They can swim"
$VarA = '$VarX'
"What do dogs do? `$($VarA)"

Desired Output:

What do dogs do? They can swim

Edit1: More expalanation as requested

I am writing a PowerShell script that will let me write then execute a simple AutoHotkey script at the terminal. So I can test very simple lines of code in AutoHotkey. This is something I am constantly finding myself doing:

  • Need to test AHK code
  • Create a .ahk file in some random path
  • #include <json>
  • #include...
  • Test done
  • Forget to delete file

I want to instead do this at the terminal:

Interactive-AHK 'MsgBox, % "The current version is " A_AhkVersion' 

Interactive-AHK "MsgBox, % "The current version is " A_AhkVersion" -NoHeaderFooter

"@
MsgBox, % "The current version is " A_AhkVersion
"@ | Interactive-AHK AdvancedHeader, AdvancedExit

The command is stored in a .psm1 file, there are also variables stored in this same file, which I need to be able to reference in the function but hide from the terminal:

Function Build-AutHotkeyScript{
    param(
        [parameter(Position = 1, ValueFromPipeline)]
        [string]$Code,
        [parameter(Position = 2)]
        [ArgumentCompletions("SingleNoenvJson", "AdvancedHeader", "BasicExit", "AdvancedExit")]
        [Array]$HeaderFooter = "SingleNoenvJson", "BasicExit"     #This may make no sense but its how I like to work
        [switch]$NoHeaderFooter
    )
    $Source = "C:\Users\..\Documents\PowerShell\Modules\AutoHotkey\Resources\InteractiveAHK.ahk"  #The Path which to set the content to
    Set-Content -LiteralPath $Source -Value "$($NoHeaderFooter -eq $True ? $null : $HeaderFooter[0]), $Code, $($NoHeaderFooter -eq $True ? $null : $HeaderFooter[1])" # If "NoHeaderFooter Switch is used dont preappend or append anything to the $Code string"
    . $source       # Run the file
}

# ---- Headers ----
    $SingleNoenvJson = @"
    #singleinstance, force
    #NoEnv
    #Include <Json>
    "@
    $AdvancedHeader = @"
    #singleinstance, force
    #Include <XML>
    #Include <SomeSuperCoolLib>
    #Include <HackingTheSystem>
    [Some more line]
    "@

    [More Headers coming soon ]

# ---- Footers ----
    $BasicExit = @"
    ExitApp
    [Some more lines coming soon]
    [Some more lines coming soon]
    "@

    $AdvancedExit = @"
    ExitApp
    [Some more lines coming soon]
    [Some more lines coming soon]
    "@

    [More Footers coming soon ]

With an invocation of Interactive-AHK 'MsgBox, % "The current version is " A_AhkVersion' , the InteractiveAHK.ahk file should look like:

#singleinstance, force
#NoEnv
#Include <Json>

MsgBox, % "The current version is " A_AhkVersion

ExitApp
[Some more lines coming soon]
[Some more lines coming soon]
  • 1
    What problem are you trying to solve here? Can you give a concrete example? I'm guessing you're trying to build something dynamic, where the contents of the variable determines behavior. If that's the case, there are *many* better ways of accomplishing your objective. But in order to make a recommendation, we need to understand the objective. – Daniel Mann Aug 01 '23 at 17:20
  • @DanielMann, Hello I edited my post and added more context. Thanks! – Ralf_Reddings Aug 01 '23 at 18:26

1 Answers1

1

You could use Get-Variable if trimming the $ from that string, otherwise you can use ExpandString Method:

$VarX = 'They can swim'
$VarA = '$VarX'
"What do dogs do? $(Get-Variable $VarA.Trim('$') -ValueOnly)"
"What do dogs do? $($ExecutionContext.InvokeCommand.ExpandString($VarA))"

Creating a scriptblock from $VarA and invoking or using Invoke-Expression would also be a possibility:

"What do dogs do? $([scriptblock]::Create($VarA).InvokeReturnAsIs())"

Do note this would allow for arbitrary code execution and you should be very careful if this comes from user input. See this answer for some ways you could prevent this.

Santiago Squarzon
  • 41,465
  • 5
  • 14
  • 37