2
votes

I have this script that should be able to run on both remote and localhost. It accepts -ComputerName as parameter with '.' (localhost) as default.

Currently I am testing how to validate a new remote session and wrote a little cmdlet for it. Problem is, if I run this script with '.' or localhost as the ComputerName the script tries to connect to a new remote session on my computer. That will not work as I do not have PSRemoting enabled.

This is my test script:

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 }
}

All of the commands, Test-WSMan, New-PSSession and Invoke-Command will fail as they assume I want to make a remote connection

Is it possible to let Powershell run the commands in the local session if $ComputerName is '.' or localhost or do I have to handle this myself in an if/else clause ?

The script is meant to run both local and on remote machines and I do not want PSRemoting enabled to be a requirement for running the script locally

3
invoke-command localhost needs an elevated command prompt.js2010

3 Answers

2
votes

AFAIK there is no $localsession-variable. You could use 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
    }

}
0
votes

It looks like you're trying to check if PowerShell Remoting is enabled/working on a computer. If you don't want yoru function to run against the local computer, you can just filter out local computers, or leave it up to whoever is calling Test-PsRemoting to pass in a non-local computer name. If they do pass in a local computer, well, then they'll get a result that PowerShell Remoting isn't enabled.

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
}
0
votes

Responding to a really old thread in case anyone else stumbles upon it. Frode's answer works just fine, but I wanted to share my own solution as well since it's easier to maintain. If the ComputerName param is defined, the function invokes itself remotely.

This won't work for all scripts, and you'll need to be careful to avoid recursive errors. Here's a quick example:

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)'"
}