1
votes

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!

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
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 stackoverflow.com/a/54317129/45375 for the full story.mklement0
@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 stackoverflow.com/a/41254359/45375mklement0

1 Answers

2
votes

$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