Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Invoke-Command $using improvements #24025

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

jborean93
Copy link
Collaborator

PR Summary

Always use the v5.1 $using: logic when dealing with any connection type that is not based on the WSManConnectionInfo. This allows the caller to use the more advanced $using features like vars with special names, $using vars inside sub scopes and more. WSMan based connections might still communicate with older versions but as the oldest supported version is v3 on Server 2012 we don't need to keep the default as v2 to support some of the newer features.

PR Context

There are three different ways that Invoke-Command deals with $using: inside a ScriptBlock:

  • V2 - replaces the ScriptBlock text to change $using:var to $__using_var and modifies the param block to pass in that variable
  • V3/4 - builds an array containing the $using:var and passes it to the remote pipeline through --%
  • V5+ - like the above but uses a hashtable and has better support for $using: in child scopes

The V2 method is quite rudimentary, it fails when using a variable with an invalid char in like -, or in a very improbable scenario someone named their var as $__using_var themselves. The - problem is typically encountered when you try to inject a function into the scriptblock, for example this fails today

Function Test-Function { 'foo' }

Invoke-Command -HostName server {
    ${function:Test-Function} = ${using:function:Test-Function}
    
    Test-Function
}
At line:1 char:29
+ param($__using_function_Test-Function)
+                             ~
Missing ')' in function parameter list.

At line:1 char:38
+ param($__using_function_Test-Function)
+                                      ~
Unexpected token ')' in expression or statement.

At line:3 char:55
+     ${function:Test-Function} = $__using_function_Test-Function
+                                                       ~~~~~~~~~
Unexpected token '-Function' in expression or statement.

The workaround is to store the function in an intermediate var or define the function without - in the name:

Function Test-Function { 'foo' }

$testFunction = ${function:Test-Function}
Invoke-Command -HostName server {
    ${function:Test-Function} = ${using:testFunction}
    
    Test-Function
}

# or

Function Function { 'foo' }

Invoke-Command -HostName server {
    ${function:Test-Function} = ${using:function:Function}
    
    Test-Function
}

The V3/4, V5 logic works just fine with vars with special chars in the name

Function Test-Function { 'foo' }

$s = New-PSSession -UseWindowsPowerShell
Invoke-Command -Session $s {
    ${function:Test-Function} = ${using:function:Test-Function}
    
    Test-Function
}
$s | Remove-PSSession

The current logic for determining what logic to use is as follows

  • If the connection info is NewProcessConnectionInfo use V5
    • This only applies to Start-Job or if using -Session $s where the $s is from New-PSSession -UseWindowsPowerShell
  • If not an explicit PSSession through the -Session parameter use V2
  • If the PSSession supports disconnection operations
    • Use the PSVersionTable.PSVersion to determine the version
    • Only WSMan on Windows satisfies this check
  • All other scenarios default to V2

This means that V3/4, V5 is only used when the PSSession from New-PSSession -UseWindowsPowerShell or New-PSSession -ComputerName ... is given to Invoke-Command -Session .... The more common scenarios like Invoke-Command -ComputerName ... or Invoke-Command -HostName ... will always use the old V2 logic and thus cannot use the newer $using: features.

This PR simplifies the checks to set the baseline to V3/4 for a WSMan based connection and treat the rest of the connection types as V5. This is because only the WSMan connection was supported before 5.1 and can guarantee the target is PowerShell 5.1 or newer. The baseline for WSMan was set to V3/4 as V2 was last in box with Windows 7/Server 2008/08 R2 which is end of life. V3/4 is also strictly end of life but considering it's still supported in Azure I didn't think it was time to drop that just yet.

PR Checklist

@jborean93 jborean93 force-pushed the psremoting-v2 branch 2 times, most recently from 3e0af19 to aa0bdbc Compare July 9, 2024 04:27
Always use the v5.1 $using: logic when dealing with any connection type
that is not based on the WSManConnectionInfo. This allows the caller to
use the more advanced $using features like vars with special names,
$using vars inside sub scopes and more. WSMan based connections might
still communicate with older versions but as the oldest supported
version is v3 on Server 2012 we don't need to keep the default as v2 to
support some of the newer features.
@@ -551,7 +551,7 @@ function Get-HelpNetworkTestCases

# Command discovery does not follow symlinks to network locations for module qualified paths
$networkBlockedError = "CommandNameNotAllowed,Microsoft.PowerShell.Commands.GetHelpCommand"
$scriptBlockedError = "ScriptsNotAllowed"
$scriptBlockedError = "CommandNotFoundException"
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@TravisEz13 This is a change from your PR #20593 which added these tests. As this PR changed default pipeline logic to the V3 branch it now sends the Get-Help -Name ... command used by this test as a Command rather than a Script. I don't fully understand the logic done by this test but this gets it working again. I would appreciate it if you could have a look over to ensure this isn't going to be a problem.

Copy link
Contributor

This pull request has been automatically marked as Review Needed because it has been there has not been any activity for 7 days.
Maintainer, please provide feedback and/or mark it as Waiting on Author

@microsoft-github-policy-service microsoft-github-policy-service bot added the Review - Needed The PR is being reviewed label Jul 16, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Review - Needed The PR is being reviewed
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

1 participant