From 3a897936f3f7e7a18a9bedc3a397afa913f1674b Mon Sep 17 00:00:00 2001 From: Dongbo Wang Date: Wed, 5 Aug 2026 20:06:11 -0700 Subject: [PATCH 1/2] Fix Copy-Item tests --- .../Copy-Item.Tests.ps1 | 66 +++++++------------ 1 file changed, 24 insertions(+), 42 deletions(-) diff --git a/test/powershell/Modules/Microsoft.PowerShell.Management/Copy-Item.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Management/Copy-Item.Tests.ps1 index 1ec37b9c5b5..1d77747debc 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Management/Copy-Item.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Management/Copy-Item.Tests.ps1 @@ -14,23 +14,7 @@ Describe "Validate Copy-Item locally" -Tags "CI" { } } -# This is a Pester test suite to validate Copy-Item remotely using a remote session. - -# If PS Remoting is not available, do not run the suite. -function ShouldRun -{ - if ( $IsCoreCLR ) { return $false } - $result = Invoke-Command -ComputerName . -ScriptBlock {1} -ErrorAction SilentlyContinue - return ($result -eq 1) -} - -if (-not (ShouldRun)) -{ - Write-Host "PS Remoting is not available, skipping tests..." -ForegroundColor Cyan - return -} - -Describe "Validate Copy-Item Remotely" -Tags "CI" { +Describe "Validate Copy-Item Remotely" -Tags @('CI', 'RequireAdminOnWindows') { # Validate a copy item operation. # $filePath is the source file path @@ -83,7 +67,7 @@ Describe "Validate Copy-Item Remotely" -Tags "CI" { } BeforeAll { - $s = New-PSSession -ComputerName . -ErrorAction SilentlyContinue + $s = New-RemoteSession if (-not $s) { throw "Failed to create PSSession for remote copy operations." @@ -495,18 +479,9 @@ Describe "Validate Copy-Item Remotely" -Tags "CI" { } It "Copy-Item parameters -FromSession and -ToSession are mutually exclusive." { - try - { - $s1 = New-PSSession -ComputerName . -ErrorAction SilentlyContinue - $s1 | Should -Not -BeNullOrEmpty - $filePath = CreateTestFile - $destinationFolderPath = GetDestinationFolderPath - { Copy-Item -Path $filePath -Destination $destinationFolderPath -FromSession $s -ToSession $s1 -ErrorAction Stop } | Should -Throw -ErrorId "InvalidInput,Microsoft.PowerShell.Commands.CopyItemCommand" - } - finally - { - Remove-PSSession -Session $s1 -ErrorAction SilentlyContinue - } + $filePath = CreateTestFile + $destinationFolderPath = GetDestinationFolderPath + { Copy-Item -Path $filePath -Destination $destinationFolderPath -FromSession $s -ToSession $s -ErrorAction Stop } | Should -Throw -ErrorId "InvalidInput,Microsoft.PowerShell.Commands.CopyItemCommand" } } @@ -570,7 +545,7 @@ Describe "Validate Copy-Item Remotely" -Tags "CI" { } else { - It "Copy-Item ToSession -Destination '$path' throws $expectedFullyQualifiedErrorId" { + It "Copy-Item ToSession -Destination '$destination' throws $expectedFullyQualifiedErrorId" { { Copy-Item -Path $path -ToSession $s -Destination $destination -ErrorAction Stop } | Should -Throw -ErrorId $expectedFullyQualifiedErrorId } @@ -654,9 +629,21 @@ Describe "Validate Copy-Item Remotely" -Tags "CI" { } } -Describe "Validate Copy-Item error for target sessions not in FullLanguageMode." -Tags "Feature" { +Describe "Validate Copy-Item error for target sessions not in FullLanguageMode." -Tags @('Feature', 'RequireAdminOnWindows') { + + It "Copy-Item throws 'SessionIsNotInFullLanguageMode' error for a session in non-FullLanguageMode" -Pending { + ## A placeholder test to show that the real test is pending. Remove this once the real tests below are enabled. + } BeforeAll { + # Keep track of the sessions. + $testSessions = @{} + # Keep track of the session names to be unregistered. + $sessionToUnregister = @() + + ## Test not validated yet. For now, make it do nothing. + $skipTestSuite = $true + if ($skipTestSuite) { return } $testDirectory = "TestDrive:\" @@ -670,12 +657,6 @@ Describe "Validate Copy-Item error for target sessions not in FullLanguageMode." $testFilePath = Join-Path $source "testfile.txt" "File test content" | Out-File $testFilePath -Force - # Keep track of the sessions. - $testSessions = @{} - - # Keep track of the session names to be unregistered. - $sessionToUnregister = @() - $languageModes = @("ConstrainedLanguage", "NoLanguage", "RestrictedLanguage") $id = (Get-Random).ToString() @@ -703,6 +684,7 @@ Describe "Validate Copy-Item error for target sessions not in FullLanguageMode." } AfterAll { + if ($skipTestSuite) { return } $testSessions.Values | Remove-PSSession -ErrorAction SilentlyContinue @@ -728,12 +710,12 @@ Describe "Validate Copy-Item error for target sessions not in FullLanguageMode." } } -Describe "Copy-Item can use Recurse and Exclude together" -Tags "Feature" { +Describe "Copy-Item can use Recurse and Exclude together" -Tags @('CI', 'RequireAdminOnWindows') { Context "Local and Remote Tests" { BeforeAll { - $s = New-PSSession -ComputerName . -ErrorAction SilentlyContinue + $s = New-RemoteSession if (-not $s) { throw "Failed to create PSSession for remote copy operations." @@ -773,10 +755,10 @@ Describe "Copy-Item can use Recurse and Exclude together" -Tags "Feature" { } } -Describe "Copy-Item remotely bug fixes" -Tags "Feature" { +Describe "Copy-Item remotely bug fixes" -Tags @('CI', 'RequireAdminOnWindows') { BeforeAll { - $s = New-PSSession -ComputerName . -ErrorAction SilentlyContinue + $s = New-RemoteSession if (-not $s) { throw "Failed to create PSSession for remote copy operations." From 563fec464a7ca8a2c8ff1aa604897bc7e3b4020c Mon Sep 17 00:00:00 2001 From: Dongbo Wang Date: Thu, 6 Aug 2026 10:39:34 -0700 Subject: [PATCH 2/2] Fix the copy scripts --- .../engine/hostifaces/HostUtilities.cs | 6 ++++- .../namespaces/FileSystemProvider.cs | 26 +++++++++---------- .../Copy-Item.Tests.ps1 | 8 ++++++ 3 files changed, 26 insertions(+), 14 deletions(-) diff --git a/src/System.Management.Automation/engine/hostifaces/HostUtilities.cs b/src/System.Management.Automation/engine/hostifaces/HostUtilities.cs index 8e5d30be71f..0e2a987f291 100644 --- a/src/System.Management.Automation/engine/hostifaces/HostUtilities.cs +++ b/src/System.Management.Automation/engine/hostifaces/HostUtilities.cs @@ -372,7 +372,11 @@ public static Collection InvokeOnRunspace(PSCommand command, Runspace $filePathName = $_.FullName # Get file contents - $contentBytes = Get-Content -Path $filePathName -Raw -Encoding Byte + $contentBytes = if ($PSVersionTable.PSEdition -eq 'Desktop') { + Get-Content -Path $filePathName -Raw -Encoding Byte + } else { + Get-Content -Path $filePathName -Raw -AsByteStream + } # Notify client for file open. New-Event -SourceIdentifier PSISERemoteSessionOpenFile -EventArguments @($filePathName, $contentBytes) > $null diff --git a/src/System.Management.Automation/namespaces/FileSystemProvider.cs b/src/System.Management.Automation/namespaces/FileSystemProvider.cs index 05c8fff76e0..e453899e885 100644 --- a/src/System.Management.Automation/namespaces/FileSystemProvider.cs +++ b/src/System.Management.Automation/namespaces/FileSystemProvider.cs @@ -8420,7 +8420,6 @@ internal static class CopyFileRemoteUtils [Parameter(ParameterSetName=""PSCopyFileToRemoteSession"")] [Parameter(ParameterSetName=""PSCopyAlternateStreamToRemoteSession"")] {0} - [string] $copyToFilePath, [Parameter(ParameterSetName=""PSCopyFileToRemoteSession"", Mandatory=$false)] @@ -8440,12 +8439,10 @@ internal static class CopyFileRemoteUtils [Parameter(ParameterSetName=""PSTargetSupportsAlternateStreams"", Mandatory=$true)] {0} - [string] $supportAltStreamPath, [Parameter(ParameterSetName=""PSSetFileMetadata"", Mandatory=$true)] {0} - [string] $metaDataFilePath, [Parameter(ParameterSetName=""PSSetFileMetadata"", Mandatory=$true)] @@ -8454,17 +8451,14 @@ internal static class CopyFileRemoteUtils [Parameter(ParameterSetName=""PSRemoteDestinationPathIsFile"", Mandatory=$true)] {0} - [string] $isFilePath, [Parameter(ParameterSetName=""PSGetRemotePathInfo"", Mandatory=$true)] {0} - [string] $remotePath, [Parameter(ParameterSetName=""PSCreateDirectoryOnRemoteSession"", Mandatory=$true)] {0} - [string] $createDirectoryPath, [Parameter(ParameterSetName=""PSCreateDirectoryOnRemoteSession"")] @@ -8601,7 +8595,13 @@ function PSCopyFileAlternateStreamToRemoteSession CheckPSDriveSize $resolvedPath $fragment.Length # Write the stream - Microsoft.PowerShell.Management\Add-Content -Path ($resolvedPath.ProviderPath) -Value $fragment -Encoding Byte -Stream $streamName -ErrorAction Stop + if ($PSVersionTable.PSEdition -eq 'Desktop') {{ + Microsoft.PowerShell.Management\Add-Content -Path ($resolvedPath.ProviderPath) -Value $fragment -Encoding Byte -Stream $streamName -ErrorAction Stop + }} + else {{ + Microsoft.PowerShell.Management\Add-Content -Path ($resolvedPath.ProviderPath) -Value $fragment -AsByteStream -Stream $streamName -ErrorAction Stop + }} + $op['BytesWritten'] = $fragment.Length }} catch @@ -8886,7 +8886,6 @@ function PSCreateDirectoryOnRemoteSession param ( [Parameter(ParameterSetName=""PSCopyFileFromRemoteSession"", Mandatory=$true)] {0} - [string] $copyFromFilePath, [Parameter(ParameterSetName=""PSCopyFileFromRemoteSession"", Mandatory=$true)] @@ -8909,22 +8908,18 @@ function PSCreateDirectoryOnRemoteSession [Parameter(ParameterSetName=""PSSourceSupportsAlternateStreams"", Mandatory=$true)] {0} - [string] $supportAltStreamPath, [Parameter(ParameterSetName=""PSGetFileMetadata"", Mandatory=$true)] {0} - [string] $getMetaFilePath, [Parameter(ParameterSetName=""PSGetPathItems"", Mandatory=$true)] {0} - [string] $getPathItems, [Parameter(ParameterSetName=""PSGetPathDirAndFiles"", Mandatory=$true)] {0} - [string] $getPathDir ) @@ -8973,7 +8968,12 @@ function PerformCopyFileFromRemoteSession {{ if ($isAlternateStream) {{ - $content = Microsoft.PowerShell.Management\Get-Content $filePath -stream $streamName -Encoding Byte -Raw + $content = if ($PSVersionTable.PSEdition -eq 'Desktop') {{ + Microsoft.PowerShell.Management\Get-Content $filePath -stream $streamName -Encoding Byte -Raw + }} + else {{ + Microsoft.PowerShell.Management\Get-Content $filePath -stream $streamName -AsByteStream -Raw + }} $rstream = [System.IO.MemoryStream]::new($content) }} else diff --git a/test/powershell/Modules/Microsoft.PowerShell.Management/Copy-Item.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Management/Copy-Item.Tests.ps1 index 1d77747debc..6eda9dfb671 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Management/Copy-Item.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Management/Copy-Item.Tests.ps1 @@ -14,6 +14,14 @@ Describe "Validate Copy-Item locally" -Tags "CI" { } } +# This is a Pester test suite to validate Copy-Item remotely using a remote session. +# We cannot create a PS Remoting session on non-Windows, so do not run the suite on those platforms. +if (-not $IsWindows) +{ + Write-Host "The 'HelpersRemoting' module works on Windows only, skipping remote tests for Copy-Item ..." -ForegroundColor Cyan + return +} + Describe "Validate Copy-Item Remotely" -Tags @('CI', 'RequireAdminOnWindows') { # Validate a copy item operation.