【问题标题】:Run powershell script as local script if ComputerName is localhost or '.'如果 ComputerName 是 localhost 或“.”,则将 powershell 脚本作为本地脚本运行
【发布时间】:2014-10-22 15:34:58
【问题描述】:

我有这个脚本应该能够在远程和本地主机上运行。它接受 -ComputerName 作为带有 '.' 的参数。 (localhost) 作为默认值。

目前我正在测试如何验证新的远程会话并为它编写了一个小 cmdlet。问题是,如果我使用 '.' 运行这个脚本或 localhost 作为 ComputerName 脚本尝试连接到我计算机上的新远程会话。这不起作用,因为我没有启用 PSRemoting。

这是我的测试脚本:

Function Test-PsRemoting {
[CmdletBinding()]
param(
    $ComputerName = ".",
    $Credentials    
)

$ErrorActionPreference = "Stop"

Test-Connection -ComputerName $ComputerName -Count 1 | 
    Format-List -Property PSComputerName,Address,IPV4Address,IPV6Address

Test-WSMan $ComputerName

$session = New-PSSession -ComputerName $ComputerName -Credential $Credentials
Invoke-Command -ComputerName $computername { 1 }
}

所有命令,Test-WSMan、New-PSSession 和 Invoke-Command 都将失败,因为它们假设我要建立远程连接

如果 $ComputerName 是 '.' 是否可以让 Powershell 在本地会话中运行命令或 localhost 还是我必须在 if/else 子句中自己处理?

该脚本旨在在本地和远程计算机上运行,​​我不希望启用 PSRemoting 成为本地运行脚本的要求

【问题讨论】:

  • invoke-command localhost 需要提升的命令提示符。

标签: powershell powershell-remoting


【解决方案1】:

AFAIK 没有$localsession-变量。您可以使用 if-tests:

Function Test-PsRemoting {
    [CmdletBinding()]
    param(
        $ComputerName = ".",
        $Credentials    
    )

    $ErrorActionPreference = "Stop"

    $remote = $ComputerName -notmatch '\.|localhost'
    $sc = { 1 }

    #If remote computer, test connection create sessions
    if($remote) {
        Test-Connection -ComputerName $ComputerName -Count 1 | 
            Format-List -Property PSComputerName,Address,IPV4Address,IPV6Address

        Test-WSMan $ComputerName

        $session = New-PSSession -ComputerName $ComputerName -Credential $Credentials
    }

    if($remote) {
        #If remote computer
        Invoke-Command -ComputerName $computername -ScriptBlock $sc
    } else { 
        #Localhost
        Invoke-Command -ScriptBlock $sc
    }

}

【讨论】:

  • 感谢您的提示,仍然是 Powershell 学习者,并没有想过将其作为 ScriptBlock。
  • 您没有在 Test-WsMan cmdlet 上使用凭据;这是故意的吗?在这种情况下它仍然返回有效结果吗?
  • 我修改了他的脚本来回答他的问题。我没有运行它,我不知道Test-WSMan 是否需要凭据才能完成它的工作。这是一个单独的“问题”。 :-)
【解决方案2】:

您似乎正在尝试检查 PowerShell 远程处理是否已在计算机上启用/工作。如果您不希望 yoru 函数在本地计算机上运行,​​您可以过滤掉本地计算机,或者由调用Test-PsRemoting 的人来传递非本地计算机名称。如果他们确实传入了本地计算机,那么他们将得到一个未启用 PowerShell Remoting 的结果。

function Test-PsRemoting 
{
    [CmdletBinding()]
    param(
        [Parameter(Mandatory=$true)]
        [string[]]
        # The computers to check.
        $ComputerName,

        [Management.Automation.PSCredential
        # The credentials to use to connect to the computers.
        $Credentials    
    )

    # Filter out local computer names
    $ComputerName = $ComputerName | Where-Object { $_ -ne '.' -and $_ -ne $env:COMPUTERNAME }

    Test-Connection -ComputerName $ComputerName -Count 1 | 
        Format-List -Property PSComputerName,Address,IPV4Address,IPV6Address

    $credentialsParam = @{ }
    if( $Credentials )
    {
        $credentialsParam.Credentials = $Credentials
    }

    Test-WSMan -ComputerName $ComputerName @credentialsParam

    Invoke-Command -ComputerName $ComputerName { hostname } @credentialsParam
}

【讨论】:

  • 感谢您的意见。我认为Frodes的答案更接近。即使用户将 localhost 作为参数传递,我确实希望脚本运行,但这不需要 PSRemoting,所以在这种情况下我想将命令作为常规脚本运行。
【解决方案3】:

回复一个非常老的帖子,以防其他人偶然发现它。 Frode 的回答很好,但我也想分享我自己的解决方案,因为它更容易维护。如果定义了 ComputerName 参数,则该函数会远程调用自身。

这不适用于所有脚本,您需要小心避免递归错误。这是一个简单的例子:

function Invoke-LocalOrRemote
{
    param
    (
        [string]$ExampleArgument,
        [string]$ComputerName
    )

    # Invoke the function remotely if a valid computer name is defined
    if ( $ComputerName -and ( Test-Connection $ComputerName -Count 1 -ErrorAction SilentlyContinue ) )
    {
        return Invoke-Command -ComputerName $ComputerName -ScriptBlock ${function:Invoke-LocalOrRemote} -ArgumentList $ExampleArgument
    }
    elseif ( $ComputerName ) { return "Error: Could not connect to remote computer '$ComputerName'" }

    # Actual function contents
    return "Function run with argument '$ExampleArgument' on computer '$($env:COMPUTERNAME)'"
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-02-15
    • 1970-01-01
    • 1970-01-01
    • 2017-04-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多