.GetType().FullName或Subaction不能直接在PowerShell中对函数调用起作用?

izj3ouym  于 2022-11-10  发布在  Shell
关注(0)|答案(1)|浏览(136)

我在安装了Powershell7.1的Win10 Pro计算机上遇到了以下问题:以下是脚本:

function hoursInSeconds ([String] $hour){
    # $hour expected format: hh:mm:ss
    $par = $hour.Split(":")
    $secs = [int]$par[0] * 3600 + [int]$par[1] * 60 + [int]$par[2]
    return $secs
}
$a = "17:55:11"
$b = "18:06:00"
$c = hoursInSeconds($b) - hoursInSeconds($a)
Write-Host "c:" $c
$aSec = hoursInSeconds($a)
$bSec = hoursInSeconds($b)
$d = $bSec - $aSec
$bSec.GetType().FullName
hoursInSeconds($a).GetType().FullName
Write-Host "a, b, aSec, bSec, d:" $a $b $aSec $bSec $d

因为函数调用的构造并没有像我预期的那样工作
我原以为(64511-65160=649,结果是“c:65160”),
通过查看函数调用的格式,我试图找出原因:

hoursInSeconds($a).GetType().FullName

但后来我收到了另一个错误。
以下是全部输出:

c: 65160
System.Int32
a, b, aSec, bSec, d: 17:55:11 18:06:00 64511 65160 649
Cannot convert value "System.String" to type "System.Int32". Error: "Input string was not in a correct format."
At D:\DEVELOP\Powershell\TimeFunctions_1.ps1:4 char:5
+     $secs = [int]$par[0] * 3600 + [int]$par[1] * 60 + [int]$par[2]
+     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [], RuntimeException
    + FullyQualifiedErrorId : InvalidCastFromStringToInteger

因此,这里有两个问题,可能是相互依赖的:
1.为什么不这样做呢?和
1.为什么.GetType().FullName不是这样工作的?
有什么想法吗?
谢谢

w6lpcovy

w6lpcovy1#

您有一个语法问题

hoursInSeconds($b) - hoursInSeconds($a)  # WRONG
hoursInSeconds($a).GetType().FullName    # WRONG

注:此上下文中的错误意味着:语法在形式上是有效的,但并没有如您所期望的那样
它应该是:

(hoursInSeconds $b) - (hoursInSeconds $a)  # -> 649
(hoursInSeconds $a).GetType().FullName     # -> 'System.Int32'

请注意更正:

  • 函数调用作为一个整体现在包含在(...)中。
  • 在PowerShell术语中,函数调用是命令,而对于参与*表达式的命令-例如使用-、减法运算符,或方法调用和/或属性访问-例如.GetType().FullName-**它们必须包含在(...)**分组运算符中-有关详细信息,请参阅this answer

要传递给函数的参数现在与函数名之间用空格分隔;类似地,必须使用空格(而不是,)来分隔多个参数
简而言之:PowerShell命令(函数、cmdlet、脚本和外部程序)必须像外壳命令-foo arg1 arg2-而不是像C#方法那样被调用-
foo('arg1', 'arg2')

**如果使用,而不是空格来分隔参数,则会构造一个数组,命令会将其视为单个参数

为了防止意外使用方法语法,您可以使用Set-StrictMode -Version 2或更高版本,但请注意它的其他影响。有关详细信息,请参阅this answer
至于您的命令是如何解释的

  • 您的hoursInSeconds($b) - hoursInSeconds($a)调用意外地被解析为hoursInSeconds单个调用,其值为$b,逐字地为-hoursInSeconds,最后将$a的值all作为参数传递给该单个调用-由于您的函数不强制传递什么(额外的)参数,因此它们不会被注意到,因此实际上只执行了hoursInSeconds $b
  • 原因是此调用是在参数模式(命令模式)下解析的,这是PowerShell的两种基本解析模式之一(另一种是表达式模式),因为它以命令的名称开头-同样,请参见this answer
  • 有关PowerShell如何在参数模式下解析不带引号的令牌的全面讨论,请参阅this answer
  • 您的hoursInSeconds($a).GetType().FullName调用的解析如下:($a).GetType().FullName先计算*,因为$a字符串,所以结果是逐字字符串System.String,然后将其作为参数传递给函数hoursInSeconds-这会失败,因为参数不是预期的"HH:mm:ss"字符串格式。

另外,您可以简化您的函数,使用[timespan](System.TimeSpan)类:

function hoursInSeconds ([string] $timeOfDay){
  [int] ([timespan] $timeOfDay).TotalSeconds
}

请注意,在这个简单的例子中,return不是必需的;在PowerShell中,您只需要return来执行控制流,而不是数据输出。任何命令或表达式的输出既没有被捕获、重定向,也没有通过管道发送到另一个命令,就是隐式输出-有关更多信息,请参阅this answer的底部部分。

相关问题