【问题标题】:Array of variables in PowerShell has null membersPowerShell 中的变量数组具有空成员
【发布时间】:2019-05-19 16:25:29
【问题描述】:

我有一个 PowerShell 脚本,我想在继续之前确保某些变量具有值。

所以我有以下内容:

$dataRow = $sheet.Cells.Find($country).Row
$serverCol = $sheet.Cells.Find($serverString).Column
$databaseCol = $sheet.Cells.Find($databaseString).Column
$userCol = $sheet.Cells.Find($userString).Column
$passwordCol = $sheet.Cells.Find($passString).Column
$partnerCol = $sheet.Cells.Find($partnerString).Column

#All variables in this array are required. If one is empty - the script cannot continue
$requiredVars = @($dataRow, $serverCol, $databaseCol, $userCol, $passwordCol, $partnerCol)

但是当我像这样遍历数组时:

foreach ($var in $requiredVars)
{
    Write-Host DataRow = ($dataRow -eq $var)
    Write-Host ServerCol = ($serverCol -eq $var)
    Write-Host DatabaseCol = ($databaseCol -eq $var)
    Write-Host UserCol = ($userCol -eq $var)
    Write-Host PasswordCol = ($passwordCol -eq $var)
    Write-Host PartnerCol = ($partnerCol -eq $var)
    if ($var -eq $null)
    {
        [System.Windows.Forms.MessageBox]::Show("No data found for given string!")
        $excel.Quit()
        return
    }
}

我总是得到消息框。我添加了“Write-Host”部分来查看每个变量的值,然后更改它以查看哪个变量为空,但所有变量都包含值,并且您在此处看到的所有检查都返回“False”。

我想知道我做错了什么以及$requiredVars 数组是否只复制值,而不是引用或其他东西。

【问题讨论】:

  • 一种令人困惑的写法。当然,这些语句中的 80%返回 false。
  • 另外,你应该改写$null -eq $var。你试过吗?看这里:rencore.com/blog/powershell-null-comparison
  • 在将值添加到数组之前是否检查过?
  • @montonero,我没有,但有区别吗?
  • @marsze,为什么会让人困惑?如果您的意思是“写主机”位,那仅用于调试/测试目的。但我仍然欢迎任何关于改进的建议。请透露。

标签: arrays powershell


【解决方案1】:

您可以考虑使用哈希表来存储所有变量,而不是使用单独的变量。
这使得检查单个项目变得更加简单:

# get the data from Excel and store everything in a Hashtable
# to use any of the items, use syntax like $excelData.passwordCol or $excelData['passwordCol']
$excelData = @{
    'dataRow'     = $sheet.Cells.Find($country).Row
    'serverCol'   = $sheet.Cells.Find($serverString).Column
    'databaseCol' = $sheet.Cells.Find($databaseString).Column
    'userCol'     = $sheet.Cells.Find($userString).Column
    'passwordCol' = $sheet.Cells.Find($passString).Column
    'partnerCol'  = $sheet.Cells.Find($partnerString).Column
}

# check all items in the hash. If any item is $null then exit
foreach ($item in $excelData.Keys) {
    # or use: if ($null -eq $excelData[$item])
    if (-not $excelData[$item]) {   
        [System.Windows.Forms.MessageBox]::Show("No data found for item $item!")
        $excel.Quit()

        # IMPORTANT: clean-up used COM objects from memory when done with them
        [System.Runtime.Interopservices.Marshal]::ReleaseComObject($sheet) | Out-Null
        # Your code doesn't show this, but you'll have a $workbook object in there too
        # [System.Runtime.Interopservices.Marshal]::ReleaseComObject($workbook) | Out-Null
        [System.Runtime.Interopservices.Marshal]::ReleaseComObject($excel) | Out-Null
        [System.GC]::Collect()
        [System.GC]::WaitForPendingFinalizers()

        return
    }
}

【讨论】:

    【解决方案2】:

    直接解决您的问题的一种方法是:

    $a = "foo"
    $b = "bar"
    $c = $null
    
    $requiredVariables = $a, $b, $c
    
    # How many total entries in array?
    ($requiredVariables).Count
    
    # How many of them have a value?
    ($requiredVariables | Where-Object {$_}).Count
    
    # So one option for a single check would be:
    if (($requiredVariables.Count) -ne ($requiredVariables | Where-Object {$_}).Count) {
        Write-Warning "Not all values provided"
    }
    

    然而,另一种 [更好的] 方法是将您的代码放入一个包含参数验证的函数

    function YourCustomFunction {
        Param (
        [ValidateNotNullOrEmpty()]
        $a
        ,
        [ValidateNotNullOrEmpty()]
        $b
        ,
        [ValidateNotNullOrEmpty()]
        $c
        )
    
        Process {
            Write-Output "Your function code goes here..."
        }
    }
    
    # Call your function with the params
    YourCustomFunction -a $a -b $b -c $c
    

    示例输出:

    Test-YourCustomFunction:无法验证参数“c”上的参数。参数为 null 或空。提供一个不为 null 或空的参数,并且 然后再次尝试该命令。 在 line:39 char:48

    【讨论】:

    • 谢谢,但脚本的重点是从 Excel 文件中读取提到的变量。我添加了验证以检查读取是否成功。
    • 简单:将 Excel 部分放在函数调用之前。
    • 我是否正确假设使用您的方法错误只会显示在命令行上?因为我有一个启动我的脚本的快捷方式,并且窗口在它返回后几乎立即关闭。我想保持这种状态,这就是我使用MessageBox的原因。
    猜你喜欢
    • 2023-03-30
    • 2015-05-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-18
    • 1970-01-01
    • 1970-01-01
    • 2017-02-19
    相关资源
    最近更新 更多