如果计算机名称是localhost或'.',则将PowerShell脚本作为本地脚本运行

4
我有一个脚本,应该能在远程和本地主机上运行。它接受“-ComputerName”作为参数,默认值为“.”(本地主机)。
目前我正在测试如何验证新的远程会话,并为此编写了一个小的 cmdlet。问题是,如果我使用“.”或本地主机作为计算机名称来运行此脚本,则脚本会尝试在我的计算机上连接到新的远程会话。这不起作用,因为我没有启用 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是 '.' 或者 localhost,那么是否可以让Powershell在本地会话中运行这些命令?或者我必须在if/else子句中自己处理? 该脚本旨在在本地和远程机器上运行,我不希望运行该脚本需要启用PSRemoting。

"invoke-command localhost" 需要管理员权限的命令提示符。 - js2010
3个回答

2
据我所知,没有$localsession变量。您可以使用if测试:
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。 - Oskar Emil
您在 Test-WsMan 命令中没有使用凭据,这是故意的吗?在这种情况下它是否仍然返回有效结果? - Michael Sorens
我修改了他的脚本以回答他的问题。我没有运行它,也不知道 Test-WSMan 是否需要凭据来完成它的工作。那是一个单独的“问题”。 :-) - Frode F.

0

看起来你正在尝试检查计算机上是否启用/工作了PowerShell远程。如果你不想让你的函数针对本地计算机运行,你可以过滤掉本地计算机,或者让调用Test-PsRemoting的人传递一个非本地计算机名称。如果他们传递了一个本地计算机,那么他们将得到一个结果,即PowerShell远程未启用。

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
}

1
感谢您的输入。我认为Frodes的答案更接近。即使用户将localhost作为参数传递,我仍希望脚本能够运行,但这并不需要PSRemoting,所以在这种情况下,我希望将命令作为常规脚本运行。 - Oskar Emil

0

回应一个非常老的帖子,以防其他人偶然发现它。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)'"
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接