【问题标题】:Powershell function unexpectedly returns no objectPowershell 函数意外返回无对象
【发布时间】:2018-03-02 06:57:31
【问题描述】:

我希望在 .ps1 文件中包含一些代码,以创建可在其他 .ps1 脚本中使用的 PSSession(以避免代码重复)。

起初我以为我需要一个创建 PSSession 并返回它的函数,但我对函数输出的工作方式感到困惑。

这是我的功能:

function newRemoteSession
{
    param([string]$ipAddress)

    $accountName = 'admin'
    $accountPassword = 'admin'
    $accountPasswordSecure = ConvertTo-SecureString $accountPassword -AsPlainText -Force
    $accountCredential = New-Object System.Management.Automation.PSCredential ($accountName, $accountPasswordSecure)

    Try
    {
        $remoteSession = New-PSSession -ComputerName $ipAddress -UseSSL -Credential $accountCredential -SessionOption (New-PSSessionOption -SkipCACheck -SkipCNCheck) -ErrorAction Stop
    }
    Catch [System.Management.Automation.RuntimeException] #PSRemotingTransportException
    {
        Write-Host 'Could not connect with default credentials. Please enter credentials...'    
        $remoteSession = New-PSSession -ComputerName $ipAddress -UseSSL -Credential (Get-Credential) -SessionOption (New-PSSessionOption -SkipCACheck -SkipCNCheck) -ErrorAction Stop
        Break
    }

    return $remoteSession
}

但是当我打电话给$s = newRemoteSession(192.168.1.10) 时,$s 是空的。

当我运行脚本时

Write-Host '00'
$s = newRemoteSession('192.168.1.10')
$s
Write-Host '02'

function newRemoteSession
{
        ........
    Write-Host '01'
    $remoteSession
}

我在控制台中只得到“00”,但我知道该函数运行,因为我得到了凭据提示。

编辑:

好的,现在可以了:

  • 捕捞中断正在阻止一切。
  • 函数调用必须不带括号。
  • 第二个代码错误,因为函数必须在调用之前定义。

【问题讨论】:

  • 如果你把函数放在你试图调用它的同一个文件中,它会起作用吗?
  • 运行$s = newRemoteSession '192.168.1.10' 不带括号
  • $s = newRemoteSession '192.168.1.10' $s = newRemoteSession -ipAddress '192.168.1.10' 得到相同的结果
  • 尝试从你的 catch 块中去掉限定符
  • 第二个块是完整的脚本吗?该函数需要在调用之前定义。正如@JosefZ 所说,您还需要从函数调用中删除括号。如果可能,尝试在 PowerShell_ISE 中编写脚本,然后逐步调试。您也不需要在 catch 块中休息。

标签: powershell syntax control-flow


【解决方案1】:

你自己发现了问题,但由于它们是常见的陷阱,让我详细说明一下:

  • 只在循环中使用break / continue 在循环中forforeachwhiledo)或在分支处理程序中switch 声明.

    • 否则,PowerShell 会在调用堆栈中查找封闭循环,如果没有,退出脚本

      李>
    • 这就是 break 在您的 catch 块中发生的情况。

  • 不要使用(...) 括起函数(命令)参数列表,也不要使用, 分隔参数

    • 在 PowerShell 中,函数 - 就像 cmdlet - 使用 shell-like 语法调用,不带括号空格分隔参数,仅用于构造一个数组作为单个参数传递)[ 1] .

      # WRONG: method-invocation syntax does NOT apply to *functions*
      # (It *happens* to work *in this case*, however, because only a
      # a *single* argument is passed and the (...) is a no-op in this case,
      # but this syntax should never be used.)
      newRemoteSession('192.168.1.10')
      
      # OK: Shell-like syntax, which PowerShell calls *argument mode*:
      # Note that the argument needn't be quoted, because it 
      # contains no shell metacharacters.
      # If there were additional arguments, you'd separate them with *whitespace*
      newRemoteSession 192.168.1.10
      
      # BETTER: You can even use *parameter names* (again, as with cmdlets),
      # which helps readability.
      newRemoteSession -ipAddress 192.168.1.10
      
  • 在 PowerShell 中,必须在定义函数之前才能调用它们。

    • 您最初没有注意到,因为您的newRemoteSession 函数的先前定义恰好存在。

[1] 有关 PowerShell 的两种基本解析模式的更多信息 - 参数模式表达式模式 - 参见我的this answer

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-27
    • 1970-01-01
    • 2015-07-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多