为什么不设置 $MyInvocation.ScriptName 和字符串比较?

Why is $MyInvocation.ScriptName not set and string comparisons?

这开始是为了让所有四 (4) 个 PowerShell 配置文件脚本识别它们自己和它们的位置。

$MyInvocation.ScriptName 被建议用于获取脚本名称,但我还没有看到它不是空字符串。不,不是 $null,空的 ('')。这似乎与这里关于 SO 的许多建议背道而驰。

我的第一个假设是 $MyInvocation.ScriptName$null,但事实并非如此。然而,令我惊讶的是,它被认为是 -lt 0。将 String 与 Int32 进行比较的基本原理是什么?

我确实找到了 $MyInvocation.InvocationName,它似乎给出了脚本名称,但没有给出它的目录路径。

PS C:\Users\lit\Documents\PowerShell> Get-Content .\profile.ps1
Write-Host "Current User, All Hosts @ $(Split-Path -Parent $MyInvocation.MyCommand.Definition)$(Split-Path -Leaf $MyInvocation.MyCommand.Definition)"
Write-Host "`$MyInvocation.ScriptName is $MyInvocation.ScriptName"
Write-Host "`$MyInvocation.ScriptName -eq `$null results in $($MyInvocation.ScriptName -eq $null)"
Write-Host "`$($MyInvocation.ScriptName -eq 0) results in $($MyInvocation.ScriptName -eq 0)"
Write-Host "`$($MyInvocation.ScriptName -lt 0) results in $($MyInvocation.ScriptName -lt 0)"
Write-Host "`$($MyInvocation.ScriptName -eq '') results in $($MyInvocation.ScriptName -eq '')"

Try { '' -eq 0 }
Catch { Write-Host "Caught -lt 0" }

Write-Host $MyInvocation.InvocationName

PS C:\Users\lit\Documents\PowerShell> .\profile.ps1
Current User, All Hosts @ C:\Users\lit\Documents\PowerShell\profile.ps1
$MyInvocation.ScriptName is System.Management.Automation.InvocationInfo.ScriptName
$MyInvocation.ScriptName -eq $null results in False
$(System.Management.Automation.InvocationInfo.ScriptName -eq 0) results in False
$(System.Management.Automation.InvocationInfo.ScriptName -lt 0) results in True
$(System.Management.Automation.InvocationInfo.ScriptName -eq '') results in True
False
.\profile.ps1

JosefZ 的建议有效。

PS C:\src\my-powershell> type .\gname.ps1
Write-Host "`$MyInvocation.InvocationName is $((Resolve-Path $MyInvocation.InvocationName).Path)"
Write-Host (Resolve-Path $MyInvocation.InvocationName).Path

PS C:\src\my-powershell> .\gname.ps1
$MyInvocation.InvocationName is C:\src\my-powershell\gname.ps1
C:\src\my-powershell\gname.ps1

我已经尝试收集这些可能的答案,但仍然只有一两个可以提供所需的答案。 $MyInvocation.Command 始终为 $null 并且 $MyInvocation.ScriptName 始终为空字符串 ('').

PS C:\src\t> Get-Content callme.ps1
"=== These two give the full path and invocation path"
Write-Host "$(Split-Path -Parent $MyInvocation.MyCommand.Definition)$(Split-Path -Leaf $MyInvocation.MyCommand.Definition)"
Write-Host "`$(`$MyInvocation.InvocationName) is $($MyInvocation.InvocationName)"
"=== `$MyInvocation.Command is `$null, but it, and its Source member, do have a type"
Write-Host "`$MyInvocation.Command -eq `$null is $($MyInvocation.Command -eq $null)"
Write-Host "`$MyInvocation.Command is $MyInvocation.Command"
Write-Host "`$(`$MyInvocation.Command) is $($MyInvocation.Command)"
Write-Host "`$MyInvocation.Command.Source is $MyInvocation.Command.Source"
Write-Host "`$(`$MyInvocation.Command.Source) is $($MyInvocation.Command.Source)"
"==="
Write-Host "`$MyInvocation.ScriptName -eq `$null is $($MyInvocation.ScriptName -eq $null)"
Write-Host "`$MyInvocation.ScriptName -eq '' is $($MyInvocation.ScriptName -eq '')"
Write-Host "`$MyInvocation.ScriptName is $MyInvocation.ScriptName"
Write-Host "`$(`$MyInvocation.ScriptName) is $($MyInvocation.ScriptName)"

PS C:\src\t> .\callme.ps1
=== These two give the full path and invocation path
C:\src\t\callme.ps1
$($MyInvocation.InvocationName) is .\callme.ps1
=== $MyInvocation.Command is $null, but it, and its Source member, do have a type
$MyInvocation.Command -eq $null is True
$MyInvocation.Command is System.Management.Automation.InvocationInfo.Command
$($MyInvocation.Command) is
$MyInvocation.Command.Source is System.Management.Automation.InvocationInfo.Command.Source
$($MyInvocation.Command.Source) is
===
$MyInvocation.ScriptName -eq $null is False
$MyInvocation.ScriptName -eq '' is True
$MyInvocation.ScriptName is System.Management.Automation.InvocationInfo.ScriptName
$($MyInvocation.ScriptName) is

首先,您的脚本的第 2 行存在错误。您可能想将 $MyInvocation.ScriptName 包装在 $(...):

Write-Host "`$MyInvocation.ScriptName is $($MyInvocation.ScriptName)"

接下来,try{}catch{} 只有在 try{} 块中的表达式抛出异常时才会起作用。简单的比较并不能做到这一点。如果您希望 PowerShell 抱怨您正在比较尝试不同的类型,那么......它不会。见下文。

@PetSerAl 的评论是中肯的。当您从 PowerShell 提示符 运行 配置文件时,ScriptName 就是调用当前命令的内容。如果您要从 另一个 脚本调用您的配置文件脚本,您会看到调用脚本名称。我认为您可能想按照 Matthias 的建议查看 $MyInvocation.MyCommand 属性。

最后...

当您按照自己的方式将字符串与数字进行比较时,PowerShell "protects" 会自动将第二个实体(数字)视为字符串,然后您将进行字符串比较:空字符串 "" 是否小于 字符串 "0"?为什么,是的。也小于"-9999":

[PS]> "" -lt -9999
True

所以 -9999 聊胜于无?让我们把它们换过来检查一下,我们看到同样的原理在起作用:

[PS]> -9999 -gt ""
False

这看似矛盾,除非您记得在每种情况下比较右侧的元素都被视为字符串或整数,具体取决于左侧是什么。