1

So I have a personal project I'm working on where I want to set the value of $Name to the name of the script without the path or file extensions. I thought I could do this as a global variable since it needs to called a few times.

I've used the set-variable command and used $global:Name but nothing seems to work when I call the variable in the function. I've also used other variable names such as "foo" and it still wasn't working. Here are some example code snippets:

Set-Variable -name Name -value [IO.Path]::GetFileNameWithoutExtension($MyInvocation.ScriptName) -scope global
function test {
    $Name
}
test
Pause

I've also tried:

Set-Variable -name Name -value [IO.Path]::GetFileNameWithoutExtension($MyInvocation.ScriptName) -scope global
function test {
    $global:Name
}
test
Pause

And:

$global:Name = [IO.Path]::GetFileNameWithoutExtension($MyInvocation.ScriptName)

function test {
    $Name
}
test
Pause

And:

$global:Name = [IO.Path]::GetFileNameWithoutExtension($MyInvocation.ScriptName)
function test {
    $global:Name
}
test
Pause

And:

$script:Name = [IO.Path]::GetFileNameWithoutExtension($MyInvocation.ScriptName)
function test {
    $script:Name
}
test
Pause

And:

$script:Name = [IO.Path]::GetFileNameWithoutExtension($MyInvocation.ScriptName)
function test {
    $Name
}
test
Pause

I was expecting the name of the script to appear but it just returns null. Anyone know why this is happening? Any advice is much appreciated!

mklement0
  • 382,024
  • 64
  • 607
  • 775
Excallypurr
  • 319
  • 1
  • 16
  • 1
    my understanding is that once you define a `$Global:` variable, you must **_always_** refer to it as such ... otherwise you will risk creating a new variable in the current scope. – Lee_Dailey Jul 17 '19 at 22:59
  • 1
    Always using `$global:` is definitely the most robust way to refer to a global variable; specifically, it is _assigning_ to a variable of the same name without the `$global:` scope in a non-global scope that creates a _local_ variable that shadows the global one - see https://stackoverflow.com/a/54317129/45375 for the full story. – mklement0 Jul 18 '19 at 02:11
  • 1
    @Excallypurr, zdan's answer solves your problem, but as an aside: using `Set-Variable` means that _argument-mode_ parsing is applied, so to use an _expression_ such as `[IO.Path]::GetFileNameWithoutExtension($MyInvocation.ScriptName)` you need to enclose it in `(...)` - see https://stackoverflow.com/a/41254359/45375 – mklement0 Jul 18 '19 at 02:14

1 Answers1

2

$MyInvocation does not provide information about the current script. It tells you about who called the script. As per the help:

Unlike the $PSScriptRoot and $PSCommandPath automatic variables, the PSScriptRoot and PSCommandPath properties of the $MyInvocation automatic variable contain information about the invoker or calling script, not the current script.

So what you want to use is $PSCommandPath, like this:

$global:Name = [IO.Path]::GetFileNameWithoutExtension($PSCommandPath)
function test {
    $Name
}
test
zdan
  • 28,667
  • 7
  • 60
  • 71