debugging 哈希表关键字取决于定义函数的位置

m4pnthwp  于 2022-11-14  发布在  其他
关注(0)|答案(1)|浏览(144)

我遇到了最奇怪的问题与powershell代码。
我有两个文件,A.ps1和B.ps1。B包含非常简单的代码,它将环境Map到一周中的几天,然后使用当前环境获得正确的几天:

$Location\A.ps1 # import Detect-Environment
$currentEnv = Detect-Environment

# 0 as Sunday, 6 as Saturday
$activatedEnvsAndWeekdays = @{
    [CurrentEnv]::LOCAL = @(0, 1, 2, 3, 4, 5, 6)
    [CurrentEnv]::DEV   = @(0, 1, 2, 3, 4, 5, 6)
    [CurrentEnv]::UAT   = @()
    [CurrentEnv]::PROD  = @(1)
}

$activatedWeekdayNums = $activatedEnvsAndWeekdays[$currentEnv]

A.ps1包含:

enum CurrentEnv {
    LOCAL
    DEV
    UAT
    PROD
}

function Detect-CinchyEnvironment {
    $hostName = [System.Net.Dns]::GetHostName()
    switch -Wildcard ($hostName) {
        '*CINCHYPRD*' { [CurrentEnv]::PROD }
        '*CINCHYUAT*' { [CurrentEnv]::UAT }
        '*CINCHYDEV*' { [CurrentEnv]::DEV }
        Default { [CurrentEnv]::LOCAL }
    }
}

因为我当前的env是[CurrentEnv]::LOCAL,所以$activatedWeekdayNums应该是列表@(0, 1, 2, 3, 4, 5, 6)。但它不是!它是$null。经过深入研究,我发现了原因。
当我在文件中定义和调用Detect-Environment时,代码运行正常,但当我在另一个名为A.ps1的文件中定义Detect-Environment,然后用. $Location\A.ps1导入它时,代码就不工作了,即使$currentEnv说它等于[CurrentEnv]::LOCAL(本地函数)到$currentEnv2(导入函数),$currentEnv2 -eq $currentEnv返回True。但结果与$activatedEnvsAndWeekdays不同。完全混淆。
任何帮助都是感激不尽的!很高兴提供更多的上下文/代码。
编辑:$currentEnv1.GetType()等于:

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     CurrentEnv                               System.Enum

$currentEnv2.GetType()等于相同的东西:

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     CurrentEnv                               System.Enum

编辑2:要添加更多信息,即使我执行$activatedEnvsAndWeekdays[[CurrentCinchyEnv]::LOCAL],所以我根本没有使用$currentEnv,当导入Detect-Environmentenum CurrentCinchyEnv时,它也不会返回任何内容。

6ju8rftf

6ju8rftf1#

按照评论中的要求发布这个答案。对于想知道如何重现这个 bug(?) 的人,这里有一个最小的可重现的例子。

*一月一日

enum TestEnum {
    Test
}

$key = . .\script2.ps1
$map = @{ [TestEnum]::Test = 'hello' }
$map[$key]

*一个月一个月

[TestEnum]::Test

如果我们尝试在 * 干净的PS会话 * 中运行**script1.ps1,我们应该获得正确的值hello,但是,对script1.ps1**的任何后续更新(必须是定义enum.ps1)都将导致PowerShell发出具有相同名称的新类型:

PS /> [AppDomain]::CurrentDomain.GetAssemblies().GetTypes() |
    Where-Object Name -EQ TestEnum

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     TestEnum                                 System.Enum
True     True     TestEnum                                 System.Enum

以及较新的组件版本:

PS /> [AppDomain]::CurrentDomain.GetAssemblies().GetTypes() |
    Where-Object Name -EQ TestEnum | ForEach-Object AssemblyQualifiedName

TestEnum, PowerShell Class Assembly, Version=1.0.0.2, Culture=neutral, PublicKeyToken=null
TestEnum, PowerShell Class Assembly, Version=1.0.0.3, Culture=neutral, PublicKeyToken=null

值得注意的是,这只会影响我们在代码上的工作,但该错误不应在干净的会话中重现,换句话说,如果您希望在hashtable上使用引用类型键,并且可以忍受在每次更新代码时必须重新启动PowerShell会话,那么在运行时应该没有问题。

作为个人建议,我会使用字符串作为哈希表键来避免这种情况。

作为解决方法,转换类型应该可以修复此问题,而无需重新启动会话:

$map[[TestEnum] $keyEnum]

相关问题